Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Knox on Wed 30/10/2013 20:15:56

Title: Looping through all existing labels? [SOLVED]
Post by: Knox on Wed 30/10/2013 20:15:56
I've got a script that makes a list of labels visible, or invisible depending on the mode I enter. Since I'm not sure how many labels will exist in the game, is there a way to loop through all existing labels? Right now I'm manually adding all labels into the script, then setting the visibility to true or false.

Pseudo code example:

Code (ags) Select

void toggleLabels(int iMode)
{
  if (iMode == 0) //HIDE ALL LABELS
  {
    int i;
    while (i < Game.LabelCount) //PSEUDO CODE
    {
      Label[i].Visible = false; //PSEUDO CODE
      i++;
    }
  }
  else if (iMode == 1) //SHOW ALL LABELS
  {
    int i;
    while (i < Game.LabelCount) //PSEUDO CODE
    {
      Label[i].Visible = true; //PSEUDO CODE
      i++;
    }
  }
}
Title: Re: Looping through all existing labels?
Post by: monkey0506 on Wed 30/10/2013 22:31:54
There's not really anything built-in to track all GUIControls of a given type. If I understand you correctly, it seems like you've already done something like this, which is the best alternative ATM:

Code (ags) Select
// top of script
Label *labels[];
int labelCount = 0;

function game_start()
{
  Label *tmp[] = new Label[Game.GUICount * AGS_MAX_CONTROLS_PER_GUI];
  int g = 0;
  while (g < Game.GUICount) // iterate all GUIs
  {
    int c = 0;
    while (c < gui[g].ControlCount) // iterate all GUIControls
    {
      if (gui[g].Controls[c].AsLabel != null) // found a Label
      {
        tmp[labelCount] = gui[g].Controls[c].AsLabel;
        labelCount++;
      }
      c++;
    }
    g++;
  }
  if (labelCount == 0) return; // we're done if there are no labels
  labels = new Label[labelCount]; // this is just to preserve memory
  // if necessary you *could* just do "labels = tmp;" to save time/speed (at the cost of the run-time memory)
  int l = 0;
  while (l < labelCount) // store the labels we found
  {
    labels[l] = tmp[l];
    l++;
  }
}

void toggleLabels(bool visible) // we're not returning anything, and we're using a boolean parameter
{
  int i = 0;
  while (i < labelCount)
  {
    labels[i].Visible = visible; // no need for a second loop here
    i++;
  }
}


I'm skeptical that something like GUIControl.Labels[n] would really be generally useful. If the engine is keeping track of it for any reason (I'll take a look at the code) then it wouldn't hurt to expose it, but I see no reason to add the additional burden for those who wouldn't be using it. ;)
Title: Re: Looping through all existing labels?
Post by: Crimson Wizard on Wed 30/10/2013 23:05:24
Quote from: monkey_05_06 on Wed 30/10/2013 22:31:54
If the engine is keeping track of it for any reason (I'll take a look at the code) then it wouldn't hurt to expose it, but I see no reason to add the additional burden for those who wouldn't be using it. ;)
Actually it does, in global array per each control type, although the reason might be simply a choice of architecture rather than necessity... I recall I was planning to change that in "develop" branch at some point.
Title: Re: Looping through all existing labels?
Post by: Knox on Thu 31/10/2013 14:23:28
Hey Monkey!

This works perfect! I'll be recycling your code for other purposes too, got to start chopping down that ugly monster I created. :)

I'm not sure what this means, but does "exposing" gui controls in the engine make the calculation faster or something? Personally I'm content with just using your script if changing the engine is too time consuming just to get a little gain in speed or efficiency or something.
Title: Re: Looping through all existing labels? [SOLVED]
Post by: Crimson Wizard on Thu 31/10/2013 14:35:56
Frankly, I would question why would you need to show/hide ALL labels altogether: this kind of action sounds is too general IMO. Imagine you will add more guis with labels, that should not be hidden, somewhere on later stages of development...

Perhaps using properties may help to distinguish labels, or guis with special labels.
Title: Re: Looping through all existing labels?
Post by: Knox on Thu 31/10/2013 14:45:45
Yeah, I just ran into that actually...heh.

Is there a way I can add to the list ONLY the labels that contain the word "_Hotspot" in their name? Naming convention is: lblMyGui_Hotspot

Its for a game feature where if the user turns "hints" off in the general settings, all labels on GUIs that offer hints will just be made invisible.

I know Id have to tokenize the name once  the script has found a label and if "_Hotspot" is found, than add it to the list...only thing is, how do I query the actual label's name? Seems I can only grab the ID.

**EDIT**
Quote from: Crimson Wizard on Thu 31/10/2013 14:35:56
Perhaps using properties may help to distinguish labels, or guis with special labels.

Can we add custom properties to GUI controls? That would be awesome! :)
(I already reached my properties limit so I have to wait until 3.4 is more stable to do any tests.)
Title: Re: Looping through all existing labels?
Post by: Khris on Thu 31/10/2013 20:31:45
You can't get object names in String form, no. What you can do is change the labels' height by a pixel, and have the code only show/hide labels with an even height.
Title: Re: Looping through all existing labels?
Post by: Monsieur OUXX on Thu 31/10/2013 23:39:24
i can't remember if controls have them but the common practice is to use the description property. E.g. set the label's description to "label1" and then check it as a String.

PS: Knox, if you wish, I can have a look at your code and give you advice on how to re-engineer it to make it more compact and, more importantly, more maintainable.
Title: Re: Looping through all existing labels?
Post by: Khris on Fri 01/11/2013 00:13:20
What description property? I'm not seeing that in the GUI editor or the scripting reference.
Title: Re: Looping through all existing labels?
Post by: Monsieur OUXX on Fri 01/11/2013 12:27:18
Quote from: Khris on Fri 01/11/2013 00:13:20
What description property? I'm not seeing that in the GUI editor or the scripting reference.

As I wrote, I didn't remember if GUI controls have it. I just checked; unfortunately they don't. Only hotspots have a description. The 9-verb template uses the description of the hotspots to set their "type" (door, etc.).
Monkey's script seems to be the best (and only) solution.
Title: Re: Looping through all existing labels?
Post by: Knox on Fri 01/11/2013 12:48:14
I guess I'll use Monkey's script for now, in conjunction with Khris' suggestion (only add labels with a height of say 14 into the array). I can live with that :)

@Monsieur OUXX: The whole thing? That's quite a generous offer there...Ok, I'll send you a PM.

**EDIT**
Ok I added this line, seems to do the trick. I'll just make sure all hotspot labels are 14 in height, and all the others never have that value.
Code (ags) Select

      if (gui[g].Controls[c].AsLabel != null && gui[g].Controls[c].AsLabel.Height == 14) // found a Label with 14 as height, the hotspot labels
      {
        tmp[labelCount] = gui[g].Controls[c].AsLabel;
        labelCount++;
      }
      c++;