Pie menu - rotate left and right

import bgeimport math


def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    up = cont.sensors['Up']
    down = cont.sensors['Down']
    
        
    if type(own['Icons']) is str:
        own['Icons']=eval(own['Icons'])
    X = len(own['Icons'])
    Empty= own.children['Empty']
    index=0
    choices=[]
    for choice in own['Icons']:
        
        added = own.scene.addObject('Text',own,1)
        added2 = own.scene.addObject('HL',own,1)
        rot = own.worldOrientation.to_euler()
        rot.z+=own['Offset']
        rot.z+=((360/X)*0.0174533)*index-((360/X)*0.0174533)
        Empty.worldOrientation=rot
        
        D = X*.33
        if D<4:
            D=4
        poz = own.worldPosition+(Empty.worldOrientation.col[1]*D)
        added.worldPosition=poz
        added2.worldPosition =poz
        added['Text']=choice
        local = added.worldPosition-own.worldPosition
        local = own.worldOrientation.inverted()*local
        if local.y>0:
            if abs(local.x)<.5:
                added.color = [1,1,1,1]
                added.localScale = [1,1,1]
        index+=1
            
    if up.positive and own['Time']==0:
        own['Time']=30    
        own['Add']=((360/X)*0.0174533)/30
    if down.positive and own['Time']==0:
        own['Time']=30    
        own['Add']=-((360/X)*0.0174533)/30    
    if own['Time']>=1:
        own['Time']-=1
        if (own['Offset']+own['Add'])<6.28:
            if (own['Offset']+own['Add'])>0:
                own['Offset']+=own['Add']
            else:
                own['Offset']=6.28-own['Offset']
                     
        else:
            D =own['Offset']+own['Add']
            D-=6.28
            own['Offset']=D
                  
        
main()



un-optimized more of a proof of concept

[ and ] rotate the selections

Attachments

RotateMenu.blend (622 KB)

import bge
import math


def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    up = cont.sensors['Up']
    down = cont.sensors['Down']
    
        
    if type(own['Icons']) is str:
        own['Icons']=eval(own['Icons'])
    X = len(own['Icons'])
    Empty= own.children['Empty']
    index=0
    
    if 'Created' not in own:
        own['Created']=[]
        for choice in own['Icons']:
            
            added = own.scene.addObject('Text',own,0)
            own['Created'].append(added)
            added2 = own.scene.addObject('HL',own,1)
            rot = own.worldOrientation.to_euler()
            rot.z+=own['Offset']
            rot.z+=((360/X)*0.0174533)*index-((360/X)*0.0174533)
            Empty.worldOrientation=rot
            
            D = X*.33
            if D<4:
                D=4
            poz = own.worldPosition+(Empty.worldOrientation.col[1]*D)
            added.worldPosition=poz
            added2.worldPosition =poz
            added['Text']=choice
            local = added.worldPosition-own.worldPosition
            local = own.worldOrientation.inverted()*local
            if local.y>0:
                if abs(local.x)<.5:
                    added.color = [1,1,1,1]
                    added.localScale = [1,1,1]
            index+=1
    else:
        index=0
        for added in own['Created']:
            rot = own.worldOrientation.to_euler()
            rot.z+=own['Offset']
            rot.z+=((360/X)*0.0174533)*index-((360/X)*0.0174533)
            Empty.worldOrientation=rot
            
            D = X*.33
            if D<4:
                D=4
            poz = own.worldPosition+(Empty.worldOrientation.col[1]*D)
            added.worldPosition=poz
            index+=1
            local = added.worldPosition-own.worldPosition
            local = own.worldOrientation.inverted()*local
            if local.y>0:
                if abs(local.x)<.5:
                    added.color = [1,1,1,1]
                    added.localScale = [1,1,1]
                else:
                    added.color = [1,1,1,.1]    
            else:
                added.color = [1,1,1,.1]
                        
                    
            
                
    if up.positive and own['Time']==0:
        own['Time']=30    
        own['Add']=((360/X)*0.0174533)/30
    if down.positive and own['Time']==0:
        own['Time']=30    
        own['Add']=-((360/X)*0.0174533)/30    
    if own['Time']>=1:
        own['Time']-=1
        if (own['Offset']+own['Add'])<6.28:
            if (own['Offset']+own['Add'])>0:
                own['Offset']+=own['Add']
            else:
                own['Offset']=6.28-own['Offset']
                     
        else:
            D =own['Offset']+own['Add']
            D-=6.28
            own['Offset']=D
                  
        
main()



optimized but not coded pretty or commented :smiley:

Attachments

RotateMenuOpto.blend (626 KB)

Looks cool!

It’s really great. :slight_smile: How about a radial menu too, where you toggle an arrow out from the center to the weapon you want (with all the owned weapons being distributed evenly around the circle)? You could use vector.angle to see which is closest to the direction you toggled/ dragged with the mouse.

On a side note I notice in some places you write numbers directly in to calculations like:

rot.z+=((360/X)*0.0174533)*index-((360/X)*0.0174533)

While this reduces the length of you code, saving some lines it can make it easier for other users to parse your code if you assert variables and then use the variables in your code:

number_of_items = len(own['icons'])
spacing = 360.0 / number_of_items
some_strange_factor = 0.0174533
rotation_calculation = spacing * some_strange_factor
rot.z+= rotation_calculation * index - rotation_calculation

If I wanted to modify the code it would help to know what 0.0174533 represents. I eventually figured out it is 1 degree in radians. If so you can use:

import math
rotation_calculation = math.radians(spacing)

This may seem like could make the code slower, but it really doesn’t. In fact, asserting values can sometimes increase speed as you often only need to make the calculation once (in this case you only have to make it each time the number of icons changes, not every tic).

For example:
If I was encapsulating this in a behavior Class, I would use a class function to change number of icons, which would recalculate rotation_calculation at the same time:

def pick_up_item(self,item):
    self.icons.append(item)
    self.number_of_icons = len(self.icons)
    self.spacing = math.radians(360.0 / number_of_items) 
...

self.pick_up_item("SWORD")

Thanks smoking mirror :slight_smile:

I tend to try stuff out directly and refine it, rather than plan…

so what you see was what happened from tinkering for about 45 minutes or so,

I always intended on cleaning it up a bit a commenting etc,

about only updating on changes, I did this in the most recent version by only running the script on keypress or if the timer was not Zero, so the script shuts off when a rotation is complete*