Dynamically build the name of a GUI

Started by valter, Sun 08/11/2015 12:03:18

Previous topic - Next topic

valter

Can I dynamically create a name for GUI declaration?
I have this code:

Code: ags

short bubbleHeight;
short lblBubbleHeight;

switch(increment)
{
case 1: 
    py = py - GetViewportY()-15-70;
    bubbleHeight = 70;
    lblBubbleHeight = 20;
    break;
case 2: 
    py = py - GetViewportY()-15-90;
    bubbleHeight = 90;
    lblBubbleHeight = 40;
    break;
case 3: 
    py = py - GetViewportY()-15-110;
    bubbleHeight = 110;
    lblBubbleHeight = 60;
    break;
case 4: 
    py = py - GetViewportY()-15-130;
    bubbleHeight = 130;
    lblBubbleHeight = 80;
}
bool bubble_out = (py <= 30);

// three GUIs are declared in the global variables
GUI *gSideSx;
GUI *gSideDx;
GUI *gSideCentre;
bool is_sx = px < (System.ViewportWidth / 2);
bool is_centre = ((!bubble_out) && (px - (tx / 2) > 30) && (px + (tx / 2) < (inv_ScreenResX - 30)));

if(is_centre) {
    if(increment == 1) { 
        gSideSx = gBubble_dim_sx_70; gSideDx = gBubble_dim_dx_70; gSideCentre = gBubble_centre_70;
    } else if(increment == 2) {
	gSideSx = gBubble_dim_sx_90; gSideDx = gBubble_dim_dx_90; gSideCentre = gBubble_centre_90;
    } else if(increment == 3) {
	gSideSx = gBubble_dim_sx_110; gSideDx = gBubble_dim_dx_110; gSideCentre = gBubble_centre_110;
    } else if(increment == 4) {
	gSideSx = gBubble_dim_sx_130; gSideDx = gBubble_dim_dx_130; gSideCentre = gBubble_centre_130;
    }
}
else if(is_sx) {
    if(bubble_out) {
        if(increment == 1) {
	    gSideSx = gBubbleOS_sx_70; gSideDx = gBubble_dim_dx_70;
	} else if(increment == 2) {
	    gSideSx = gBubbleOS_sx_90; gSideDx = gBubble_dim_dx_90;
	} else if(increment == 3) {
	    gSideSx = gBubbleOS_sx_110; gSideDx = gBubble_dim_dx_110;
	} else if(increment == 4) {
	    gSideSx = gBubbleOS_sx_130; gSideDx = gBubble_dim_dx_130;
	}
    [ ... ]


Currently I use a series of IF to assign gSideSx, gSideDx and gSideCentre correct GUI name.

If I could do something like:

Code: ags

String nameGui = "gBubble_dim_sx_";
nameGui = nameGui.Append(bubbleHeight); // bubbleHeight = 70 or 90 or 110 or 130
gSideSx = nameGui;


I could greatly reduce the code.
This above is just an example because of course raises error.

Is there a way to do something similar?
I've read all the manual several times but I haven't found any useful information.
In any case, are there alternative ways?

Valter

Snarky

#1
No, variable names cannot be set dynamically. There's a strict distinction between Strings, which are objects that can hold text while the game is running, and variable names, which are labels in your source code that the compiler can recognize. Those labels aren't strings as far as AGS is concerned (ultimately they're just a handy way to keep track of a memory address), and cannot be manipulated like strings.

Therefore, this is also wrong:

Quote from: valter on Sun 08/11/2015 12:03:18
Currently I use a series of IF to assign gSideSx, gSideDx and gSideCentre correct GUI name.

That's not actually what you're doing. You're assigning different GUI object values to the gSideSx/Dx/Centre GUI pointer variables. They still have the same names (gSideSx is still called gSideSx, etc.), but they're referring (pointing) to different GUIs.

In order to do that depending on some String value you do need a series of if-statements or switch/case statements (in AGS 3.4), but I would first of all question whether that's really the right approach. Is there a reason you need to use different GUIs depending on the size? Can't you just always use the same GUI and adjust its dimensions? (You know about GUI.SetPosition() and GUI.SetSize(), right?)

valter

#2
Thanks for your reply.
I use both functions you mentioned to assemble the GUI final

Code: ags

// begin universal code
gBubbleText.Height = bubbleHeight;
lblBubbleText.Width = tx + 10;
lblBubbleText.Height = lblBubbleHeight;
lblBubbleText.Text = testo;
gBubbleText.Width = tx + 50;
gBubbleText.ZOrder = 200;
// end universal code
if(is_centre) {
    gSideCentre.Width = (tx / 2) - 20;
    gSideCentre.SetPosition(px-10, py);
    px = px - (tx / 2) - 30;
    gSideSx.Width = gSideCentre.X - px; 
    gSideSx.SetPosition(px, py);
    gSideDx.SetPosition((gSideCentre.X + gSideCentre.Width), py);
} else {
    gSideSx.Width = tx;
    if((!is_sx) && (!bubble_out)) {
        gSideDx.SetPosition(px, py);
	gSideSx.SetPosition(gSideDx.X - tx, py);
	gBubbleText.SetPosition(gSideSx.X,  py);			
    } else {
	gSideSx.SetPosition(px, py);
	gSideDx.SetPosition((px + tx), py);
	gBubbleText.SetPosition(px,  py);	
    }
}
gSideSx.Visible = true;
if(is_centre) { gSideCentre.Visible = true; }
gSideDx.Visible = true;
gBubbleText.Visible = true;


Guis that have in their name "dim" are all resizable in width from code when necessary.
Some Gui have rounded corners and also "designs" that deforms by changing the size (are Guis without "dim").
[edit] This is a mistake, in fact, the GUI does not deform but rather it is cut by SetSize ()
The code works well and fast, it does not seem that requires excessive resources but I am happy to receive any suggestions to improve my work.

Khris

Could you post a screenshot that shows the finished product?
Because I'm pretty sure you can reach the same goal by drawing it dynamically.

valter

Quote from: Khris on Sun 08/11/2015 21:56:38
Could you post a screenshot that shows the finished product?

Of course.
I tried to use directly Think() with Custom Gui but the result does not satisfy me.

If the character is everywhere on the screen but not too close to the Top, Left and right:

   

if it's too close to the edge of the left or right:

   

if it is too close to the top I use bubble left or right. (If the character is in the first or second half of the screen)

   

In conclusion is possible to create bubbles with maximum width of 450px and maximum height of 4 rows.
I know that I'm using a lot of time for these details.
But this allows me to study well AGS.
Now I was thinking maybe I could use a single rectangular GUI resizable both in length and height and use simple sprite for the rounded corners and the tip of the bubble.
In this way I could avoid the size limitation.
Any suggestion and feedback is welcome.

Snarky

If you already have it working, I don't think there's any really good reason to change it, but yes, that would be the normal way to do it.

Note also that if you search the forums for "speech bubble", you'll find a lot of threads about this question. There's also a module that provides speech bubble functionality: http://adventuregamestudio.fr-bb.com/t1212-phylactere

valter

In fact I took inspiration from several posts found! ;)

For Phylactere, I just downloaded it, at first glance the module does not check the position of the character nor the font size and the bubble leaves the screen and also text, with large fonts, leaves the bubble. Also the tail is always central.
Thanks anyway for the tip, I can get important information by examining the code.

ollj

A GUI is an instance of a pretty complex struct.
the ags editor visualizes and edits it nicely.

you could try to make your own similar struct, it doesnt need to have all features of GUI, just the ones you need.
that one you then instance yourself, and you could make an editor for it in ags that writes you a txt file.

Monsieur OUXX

You cannot give them string names, however with a bit of work you can give them numbers. Provided you know what these numbers means, then it's as if you gave them a name.

If we imagine that you continue on your original design choice of having one hand-made Gui for each size requirement (instead of a dynamically resized gui -- I'm not judging, sometimes over-scripting things complicates things) then you can get inspiraiton from this:


Code: ags


//The 4 bubbles are 70,90,110 and 130.
#define NB_BUBBLES 4

int bubbleSizes[NB_BUBBLES]; //in this array we store the size of each bubble
GUI* bubbleGuis_Sx[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Sx)
GUI* bubbleGuis_Dx[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Dx)
GUI* bubbleGuis_Centre[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Center)
GUI* bubbleGuis_OS_Sx[NB_BUBBLES]; // (OS Sx)

enum BubbleCustomSizes {
  eBubble70 = 0, //these are just arbitrary names. We give them zero-based values so that they can be used as indices in arrays. But just add "1" and it becomes the exact same thing as your "increment" variable.
  eBubble90 = 1, 
  eBubble110 = 2, 
  eBubble130 = 3
};



bool initOK;
void InitValues()
{
  if (!initOK) //we do all this only once, of course!
  {
    //We set all these values once and for all.
    //i.e. Everything that is arbitrary (and subject to change!) is centralized in this function
    bubbleSizes[eBubble70] = 70; 
    bubbleSizes[eBubble90] = 90; 
    bubbleSizes[eBubble110] = 110; 
    bubbleSizes[eBubble130] = 130; 
    
    bubbleGuis_Sx[eBubble70] = gBubble_dim_sx_70; 
    bubbleGuis_Sx[eBubble90] = gBubble_dim_sx_90; 
    bubbleGuis_Sx[eBubble110] = gBubble_dim_sx_110; 
    bubbleGuis_Sx[eBubble130] = gBubble_dim_sx_130; 
    
    bubbleGuis_Dx[eBubble70] = gBubble_dim_dx_70; 
    bubbleGuis_Dx[eBubble90] = gBubble_dim_dx_90; 
    bubbleGuis_Dx[eBubble110] = gBubble_dim_dx_110; 
    bubbleGuis_Dx[eBubble130] = gBubble_dim_dx_130; 
    
    bubbleGuis_Centre[eBubble70] = gBubble_centre_70; 
    bubbleGuis_Centre[eBubble90] =gBubble_centre_90; 
    bubbleGuis_Centre[eBubble110] = gBubble_centre_110; 
    bubbleGuis_Centre[eBubble130] = gBubble_centre_130; 

    bubbleGuis_OS_Sx[eBubble70] = gBubbleOS_sx_70; 
    bubbleGuis_OS_Sx[eBubble90] =gBubbleOS_sx_90; 
    bubbleGuis_OS_Sx[eBubble110] = gBubbleOS_sx_110; 
    bubbleGuis_OS_Sx[eBubble130] = gBubbleOS_sx_130; 
    
    initOK=true;
  }
}

//
//  [ ... ]
//
//  Now, in your function : 
//

InitValues(); //don't firget to call this!

short bubbleHeight;
short lblBubbleHeight;

BubbleCustomSizes size = increment-1; //size starts from 0, increment starts from 1

//Reminder: bubbleSizes[eBubble70] is 70, etc.
py = py - GetViewportY()-15-bubbleSizes[size];
bubbleHeight = bubbleSizes[size];
lblBubbleHeight = bubbleSizes[size]-50;


bool bubble_out = (py <= 30);
 
// three GUIs are declared in the global variables
GUI *gSideSx;
GUI *gSideDx;
GUI *gSideCentre;

 
if(is_centre
   gSideSx = bubbleGuis_Sx[size]; gSideDx = bubbleGuis_Dx[size]; gSideCentre = bubbleGuis_Centre[size];

else if(is_sx) {
    if(bubble_out) {
            gSideSx = bubbleGuis_OS_Sx[size]; gSideDx = bubbleGuis_Dx[size];

//    [ ... ]
 

Crimson Wizard

Monsieur OUXX, is there a reason you chose to do 5 separate arrays instead of declaring a struct to group these custom GUI parameters?

Monsieur OUXX

Quote from: Crimson Wizard on Mon 07/12/2015 15:13:22
Monsieur OUXX, is there a reason you chose to do 5 separate arrays instead of declaring a struct to group these custom GUI parameters?

Nope. Just old habits I keep from these times when one had to be paranoid about what CAN be array'ed or struct'ed and what cannot.
 

SMF spam blocked by CleanTalk