Complex problem with custom icon-based GUI (small update)

Started by TheMagician, Sat 11/06/2005 11:27:44

Previous topic - Next topic

TheMagician

Hi everybody.
Here's what I'm trying to script:
- at least I think it is complex  ;) -

Imagine a GUI consisting only of 8 small buttons, all of the same size one after one in a row. That's the GUI.
Every button has the same attributes which I defined in a custom scruct, for example:

button1.StartTopicNumber
button1.SetGraphicSlot
button1.Description
button1.Enabled

button2.StartTopicNumber
button2.SetGraphicSlot
button2.Description
button2.Enabled

....and so on (I think I could use an array for that but I have not much experience with them).

As you might have noticed by now: the whole thing tries to be an icon-based dialog GUI.

And here is the problem:
most of the time not ALL 8 buttons are used but only 4 or 5 (or even only 2).
I already scripted that the GUI always pops up centered under the player character independent from the number of buttons currently displayed.

However, let's assume there are 4 icons(=buttons) currently active.
Now let's say the player clicks on button 2 -> topic number "button2.StartTopicNumber" is started and the conversation is displayed.
After it has finished, the icon-GUI reappears BUT, now that the topic of number 2 is exhausted I want the button to be no longer displayed.
But I also don't want to have gap where the button once was.

So button 3 and 4 (with all their functionality!!) have to be "shifted to the left" which means loading their attributes into buttons 2 and 3) to close the gap.
Even more: Now that 3 and 4 are shifted to 2 and 3, button 4 is empty and therefore has to be deactivated.
And the whole thing should, of course, be dynamic, so that it not only works for button 2 but also for every other button.

Thanks for reading!
I hope you understand my problem and can help me to find an approach to its solution!
Many thanks in advance,

Stefan

GarageGothic

#1
Why don't you just move them physically? It seems a hell of a lot easier to have a function to call everytime you switch one on or off.

Edit: Oh yeah, this uses an array for the buttons to shorten the code, but you could script it all out if you wanted to.

sort of:


function organize_buttons {
Ã, 
Ã,  short buttonx = 0; //where the leftmost button will be on the gui.
Ã, 
Ã,  short numofbuttons = 8;
Ã,  short buttonnum = 1;

Ã,  whileÃ,  buttonnum < numofbuttons {
Ã,  Ã,  Ã, if button[buttonnum].Enabled = true {
Ã,  Ã,  Ã,  Ã, button[buttonnum].X = buttonx;
Ã,  Ã,  Ã,  Ã, buttonx = buttonx + button[buttonnum].width;
Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  Ã, buttonnum++
Ã,  Ã, }

buttongui.Width = buttonx;
buttongui.X = player.X - (buttonx/2); //to center it under the player

}



Or something like that ;)

TheMagician

Thank you very much GarageGothic!

I just spend 15 minutes studying your code (because I'm really new to the concept of arrays) but I think I got it ... and I must say I love it!
I'll now try to implement it into my own code and see what further problems arise  ;)

Things to do include: resetting the buttons after a conversation with a character is finished (but I think your script gives a good starting point for that, as well) and of course loading the icons with the appropriate graphics, topics, descriptions, every time the player talks to a NPC.

I'm still hoping that I can somehow create a link between my script module including the custom functions and the AGS dialog editor, because I see no possibility to keep track of hunderts of conversation-topics (+ subtopics) within a custom function.
BUT the dialog editor of course works with options which are displayed on screen as text where the player can click on ...  and that's exactly what the icon-based Dialog GUI wants to avoid ....  :P

So share your opinions and ideas!




ilSilente

Quote from: GarageGothic on Sat 11/06/2005 11:41:34
short buttonx = 0; //where the leftmost button will be on the gui.
short numofbuttons = 8;
short buttonnum = 1;

Again, use int instead of short: there is no reason to use short unless for large arrays (like short myarray[TYPE_A_HUGE_NUMBER_HERE])

TheMagician

Ok, ilSilente, i changed the shorts to ints.

here is my trancsription of the code so far.

Code: ags

function OrganizeIcons() {
  int IconPositionX = 0; //where the leftmost icon (button) will be on the gui.
  int IconNumber = 0;
  GUIControl *control = gDialog.Controls[8];

  while  (IconNumber < NumberOfIcons) { // NumberOfIcons was defined at the top of the script
    if (Icon[IconNumber].Activated == true) {
	Icon[IconNumber].X  = IconPositionX;                             < ==== !!!!!      
	IconPositionX = (IconPositionX + IconWidth + 1);
	}
	IconNumber++;
     }
}


< ==== !!!!!     
This line is the problem: I don't know how to properly access the correct button on the GUI and change its X position.

Right now it sais something like:  Parse Error near "Icon".

If I do:

control[IconNumber].X = IconPositionX;

I get the error: control is not an array   (however, I thought I declared it an array at the beginning of the function?
Could you help me again, please?
Stefan

ilSilente

#5
AGS doesn't support pointers to pointers, nor arrays of pointers.

Try this, instead:

Code: ags

function OrganizeIcons() {
  int NumberOfIcons = 3; // <-- IMPORTANT: Insert here the number of icons you use
  // Don't touch variables below!
  int IconPositionX = 0;
  int IconNumber = 0;
  GUIControl *Icon;

  while  (IconNumber < NumberOfIcons) // NumberOfIcons was defined at the top of the script
    { 
      Icon = gButtons.Controls[IconNumber];
      if (Icon.Visible == true)
        {
          Icon.X  = IconPositionX;                                
          IconPositionX = (IconPositionX + Icon.Width);
        }
      IconNumber++;
    }
  gButtons.X = (system.screen_width - IconPositionX - Icon.Width) / 2; // Center the GUI
}


This code assume that:
- Your icons are placed in a GUI called BUTTONS (gButtons in script)
- gButtons only contain your icons
- Icons have to be centered in screen

... also works with buttons having different length

strazer

Quote from: ilSilente on Sat 11/06/2005 15:30:37
AGS doesn't support pointers to pointers, nor arrays of pointers.

Arrays of pointers are possible:

Code: ags

  Character *thechars[3];
  thechars[1] = cEgo;
  thechars[1].Say("Hello!");

ilSilente

Quote from: strazer on Sat 11/06/2005 15:42:29
Arrays of pointers are possible:

Thanks :) I was trying to use java syntax and getting always error (shame :P)

Anyway AGS won't let me this:
Code: ags
GUIControl *Icons[4] = gButtons.Controls;

Is it an AGS limit?

strazer

gButtons.Controls is an array. To access an element, you have to provide a number:

  GUIControl *Icons[4];
  Icons[2] = gButtons.Controls[7];

I haven't really looked at GarageGothic's code. What are you trying to do?

ilSilente

Yes, Controls is an array (perhaps a GUIControl* array)
Icons is a GUIControl* array, too.

This...
  GUIControl *Ico[4];
  Ico = gButtons.Controls;
...is impossible in AGS (it is possible in Java, maybe in C++). A pointer to pointer would do the job:
  GuiControl **Ico;
  Ico = gButtons.Controls;
  Ico[1].blablabla....

Anyway this isn't the point, it is not very necessary :)


TheMagician

Thank you very much ilSilente for the help with the code!
I adjusted it to my own script and now the repositioning of the buttons works wonderful!  :D
I definitely learned something.

btw, I changed my buttons/icons to an array.

At the moment I'm just thinking about the next problem:
(i think this whole icon-based stuff is one big problem)
If the player clicks for the first time on a NPC to start a conversation, I need a custom function to

- define the number of icons used at the beginning of the conversation (easy)
- Set the graphics for the different buttons (realtively easy)
- Set a one-word topic description for the buttons (might be useful later)
- Give the buttons the information which topic they should start (easy)
- Set a variable for each button which holds the progress of this one topic

The last point means: if you click on the button for the first time, the dialog about that topic is started. However, often in games you find that the conversation is interrupted, you get the choice of icons again, but you can click on the same icon AGAIN to continue the conversation where you left it.
Thats what the "TopicProgress" variable is for.

Grrr ... that all seems so complicated ...

One general question:
if I import a custom function from the script header, I write "import function SetupDialog(int, int, int);"

However, if I call that function somewhere in the script later and type SetupDialog(
a window pops up saying (int, int).
That's not very informing.
Is there a way to change that pop up to look like (int NumberOfTopics, int TopicProgress)?

Thanks again,
Stefan


strazer

Sure, just do

  import function SetupDialog(int NumberOfTopics, int TopicProgress);

TheMagician

#12
Ok strazer, that was easy.  :-\
Thanks!

But while we're at it ... i just realized that adding the graphics to the buttons using a custom function isn't so easy, as well.

Because if there are 3 topics in a conversation I only need 3 buttons with graphics, if there are 5 topics I need 5 buttons with graphics, so I can't just write:

function SetupDialog (int NumberOfIcons, int GfxButton_I, int GfxButton_II, int GfxButton_III,...) {
btnDialogIcon01.SetGraphics = GfxButton_I;
btnDialogIcon02.SetGraphics = GfxButton_II;
btnDialogIcon03.SetGraphics = GfxButton_III;
btnDialogIcon04.SetGraphics = GfxButton_IV;
...
}
and I just realize that this custom functions arguments would be way to big ...

Oh I think this is too big for me  :'(
I'd really love to have a custom icon dialog GUI but I think I'm to inexperienced with this type of programming.


------- EDIT -------

Ok, I tried to create an import function for the graphics:
There are 8 buttons on the GUI maximum.

Code: ags

function SetupDialog(SetupNumIcons, Gfx[8]) {

  //Setup of button 0
  if (BtnDialogIcon0.ID >= SetupNumIcons) {
    BtnDialogIcon0.Visible = false;
  }
  else {
    BtnDialogIcon0.Graphic = Gfx[0];
  } 

  //Setup of button 1
  if (BtnDialogIcon1.ID >= SetupNumIcons) {
    BtnDialogIcon1.Visible = false;
  } 
  else {
    BtnDialogIcon1.Graphic = Gfx[1];
  } 

  //Setup of button 2
  if (BtnDialogIcon2.ID >= SetupNumIcons) {
    BtnDialogIcon2.Visible = false;
  }
  else {
    BtnDialogIcon2.Graphic = Gfx[2];
  } 

  //Setup of button 3
  if (BtnDialogIcon3.ID >= SetupNumIcons) {
    BtnDialogIcon3.Visible = false;
  }
  else {
    BtnDialogIcon0.Graphic = Gfx[3];
  }

  //Setup of button 4
  if (BtnDialogIcon4.ID >= SetupNumIcons) {
    BtnDialogIcon4.Visible = false;
  } 
  else {
    BtnDialogIcon0.Graphic = Gfx[4];
  }

  //Setup of button 5
  if (BtnDialogIcon5.ID >= SetupNumIcons) {
    BtnDialogIcon5.Visible = false;
  } 
  else {
    BtnDialogIcon0.Graphic = Gfx[5];
  }

  //Setup of button 6
  if (BtnDialogIcon6.ID >= SetupNumIcons) {
    BtnDialogIcon6.Visible = false;
  } 
  else {
    BtnDialogIcon0.Graphic = Gfx[6];
  }

  //Setup of button 7
  if (BtnDialogIcon7.ID >= SetupNumIcons) {
    BtnDialogIcon7.Visible = false;
  } 
  else {
    BtnDialogIcon0.Graphic = Gfx[7];
  } 

  //Setup
    NumberOfIcons = SetupNumIcons;
    OrganizeIcons();  

}


- BtnDialogIcon are the names of the buttons in the Dialog GUI.
- SetupNumIcons is the variable which stores how many icons are used at the beginning of the conversation
- Gfx[8] is supposed to be an array which stores the sprite slots of the icons.

I have not tested this function yet. Is it possible to use an array in a functions argument, at all?
If so, can you help me with how to fill this array with the sprite slots?

I'm not giving up ... at least not today!

ilSilente

Use a function SetupButton(GUIControl *button, int gfx, string description, int topictostart, .......)
and setup every button individually.

SMF spam blocked by CleanTalk