Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Itterate over " selected " enums.

Discussion in 'Scripting' started by Patrick234, Jul 28, 2014.

  1. Patrick234

    Patrick234

    Joined:
    Jun 25, 2014
    Posts:
    88
    Good day, i ran into an issue. I dont know how to itterate over selected enums.

    I thought Enum.GetValues would do the trick, but this only accepts a structure.

    I have a variable that is a user based selection of that structure. And i need to loop through the user selection instead. How would that work?

    Thanks! :)
     
  2. mafiadude1

    mafiadude1

    Joined:
    Jun 28, 2012
    Posts:
    59
  3. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    You could either loop through each value of the enum and check against it:

    Code (csharp):
    1.  
    2. foreach(YourFlagEnum flag in Enum.GetValues(typeof(YourFlagEnum)))
    3. {
    4.     if (bitmask & flag > 0)
    5.    {
    6.    
    7.    }
    8. }
    9.  
    But you could run into obvious issues if you defined compound helper flags (like Potatoe = 0x01, Carot = 0x10, PotatoeAndCarot = 0x11).

    Or, if that is an issue for you, you can check all the bits, considering you know how many bits you're using as a small optimization:

    Code (csharp):
    1.  
    2.         YourFlagEnum userSelectedFlags = 0x1111;
    3.         int highestBitmaskValue = 0xffff; //highest bit value in flags
    4.         for (int bitmask = 1; bitmask <= highestBitmaskValue; bitmask *= 2)
    5.         {
    6.             if ((userSelectedFlags & bitmask) > 0)
    7.             {
    8.                 Debug.Log("User selected: " + (YourFlagEnum)bitmask);
    9.             }
    10.         }
    11.  
     
  4. Patrick234

    Patrick234

    Joined:
    Jun 25, 2014
    Posts:
    88
    Thanks guys!

    I ran into this http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx so it can be done in Unity but needs the [] array part added and [Flag] option to enable the .hasFlag().

    I went with _met44, bitwise. Works great!

    Code (CSharp):
    1.     public float angleFindNext(float currentAngle){
    2.         currentAngle = Mathf.Round(currentAngle / 22.5f) * 22.5f;
    3.         ValidAngles myAngle;
    4.         foreach(ValidAngles angle in Enum.GetValues(typeof(ValidAngles))){
    5.             if(currentAngle==angleEnumToAngle(angle)){
    6.                 myAngle = angle;
    7.                 for(int i = 1; i <= 16; i++){
    8.                     if(myAngle == ValidAngles.NNW)
    9.                         myAngle = ValidAngles.N;
    10.                     else
    11.                         myAngle = (ValidAngles)(((int)myAngle)*2);
    12.                     if((myAngle & useAngles)!= 0){
    13.                         Debug.Log(i);
    14.                         return (i * 22.5f);
    15.                     }
    16.                 }
    17.             }
    18.         }
    19.         return 0;
    20.     }
    I know its not "clean" but it does the job. Theres 1 thing that won't change. the 16 directional Enum (ValidAngles) based of which i could write this up. " useAngles" is the local objects " selected" angles form the ValidAngles enum.

    upload_2014-7-28_23-53-3.png

    So it does 16 itterations to find the next valid angle :) translates that to the new angle float, which is then translated to a Quaternion and applied to the object.

    Player can now press E to rotate an object.
     
    Last edited: Jul 28, 2014
  5. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    You should have presented your problem from the start.

    Simply give the enums values from 0 to 16, to find the next you do :

    Round(angle / 22.5) == angleNum
    nextAngleNum = angleNum + 1
    nextAngle = nextAngleNum * 22.5

    No flag, no iteration !

    ps: and if you need the compound values to match because you use the flags elsewhere, use power of 2 values instead and you're done.
     
  6. Patrick234

    Patrick234

    Joined:
    Jun 25, 2014
    Posts:
    88
    Well, that wouldnt work with Unity Inspector. The trick is to get the Enum widget like this.

    A custom editor is an undesired effect also should you want to enforce it somehow.

    Right nw i can stack classes however i want and change the enums (i used to have 8 when i upped it to 16 of recent) and it propegates through the entire program.

    But i should point out, its not about getting the next angle like that. Its for an editor (while it also supports the Inspector) so people can select for example: West, North, North East, East and leave it at that.
    The only proper way to itterate that is by counting the itterations needed before getting to a valid next angle, and then multiply the itteration by 22.5f :)
    Because we are dealing with users you want to make it as visual and easy as possible for them.
     
  7. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    Hmmm then with power of 2 as unit for the enum it should be something like:

    Code (Pseudo):
    1. angleNum = Round(angle / 22.5)
    2. angleFlag = power2(angleNum)
    3. while ((angleNum < lastAngleNum) && (angleFlag & validAngleFlags == 0))
    4.     angleNum++
    5.     angleFlag *= 2
    6. if (angleNum < lastAngleNum)
    7.    nextAngle = angleNum * 22.5
    This would make your angleFlag snap from a power of 2 unit to the next until you find a matching flag while extracting the corresponding angleNum.