Dialog GUI Customizations

Started by imagazelle, 14 Dec 2021, 06:24

« previous - next »

imagazelle

Hi, folks.

Well I'm now venturing into dialog territory, and I wanted to set up a system akin to the CMI style - a transparent background overlay, different text colors than AGS' defaults, arrows for scrolling copious dialog options, etc.

I quickly gathered that I couldn't have all of these things with the built-in system, so naturally I turned toward using a custom GUI (not a text window GUI either, because I wish to control the placement of the GUI and don't want a border), but now I've hit a few roadblocks. I read through several older posts about similar matters, but am not sure if some things that were previously considered impossible now have workarounds. I also went through the 'custom dialog options rendering' article in the manual and tried implementing some of the functions, but it wasn't quite working out for me (not sure if it's not applicable for what I'm trying to do or if I was just doing it wrong).

Here's what I'm after but haven't been able to figure out:

1. The default color for dialog options. I believe this is normally tied to the player character's speech color, but (if possible) I'd like to be able to adjust this.

2. The highlight color for dialog options when hovered over with the mouse. I know this can be done with a text window GUI, but again I'm not using that here (for the reasons given above), and I saw that someone in an older thread was able to figure out how to change this for Sierra style dialog, but at the time it seemed like it wasn't possible to do so with the method I'm using. I'm hoping this has changed or that one of you clever wizards can come up with something.

3. How would I implement arrows (using custom graphics, no less) for scrolling through excess options? Is it anything like how it's done for inventory pages?

4. This one's just a minor niggle: Is there any way to constrain the act of highlighting an option to hovering over only the actual text of each option, rather than the entire width of the GUI for each line?


Any assistance with these is much appreciated.

Khris

AFAIK, the  dialog_options_render(DialogOptionsRenderingInfo *info)  function allows you to completely customize the appearance, including the color used for highlighting or how exactly the text is highlighted (because you're drawing everything yourself).

If you've tried code and it doesn't work, it's always a good idea to include it in the question ;)

imagazelle

#2
OK, I missed one small (but integral) detail on my first run through of the 'custom dialog options rendering' manual entry - the bit that says, "you need to do the following:" and that BOTH the dialog_options_get_dimensions and dialog_options_render functions are mandatory. On my first attempt, I tried using only one of the functions, which is why nothing was happening. So I've got it working now...

...partially...

I've got the text colors, placement, and sizing all how I want them, but am still unsure as to how to implement page arrows for overflow options.

Also, I would still like to limit the highlighting action to when you hover over only the actual text of each option, instead of the full width of the drawing surface. I imagine this might be achieved with a GetTextWidth command, similar to the GetTextHeight bits already being used in the code, but am not sure quite how to write that out, and in which part(s) of the script to place it.

Here's my current code, copied and adapted from one of the examples given in the manual article:

Code: ags

int dlg_opt_acolor = 13;
int dlg_opt_ncolor = 4;

function dialog_options_get_dimensions(DialogOptionsRenderingInfo *info)
{
  // Create a 400x200 dialog options area at (50,100)
  info.X = 50;
  info.Y = 100;
  info.Width = 400;
  info.Height = 200;
  // Enable alpha channel for the drawing surface
  info.HasAlphaChannel = true;
}

function dialog_options_render(DialogOptionsRenderingInfo *info)
{
  int ypos = 0;
 
  for (int i = 1; i <= info.DialogToRender.OptionCount; i++)
  {
    if (info.DialogToRender.GetOptionState(i) == eOptionOn)
    {
      if (info.ActiveOptionID == i)
        info.Surface.DrawingColor = dlg_opt_acolor;
      else
        info.Surface.DrawingColor = dlg_opt_ncolor;

      info.Surface.DrawStringWrapped(5, ypos, info.Width - 10,
              eFontFont0, eAlignLeft, info.DialogToRender.GetOptionText(i));
      ypos += GetTextHeight(info.DialogToRender.GetOptionText(i), eFontFont0, info.Width - 10);
    }
  }
}

function dialog_options_repexec(DialogOptionsRenderingInfo *info)
{
  info.ActiveOptionID = 0;
  if (mouse.y < info.Y || mouse.y >= info.Y + info.Height ||
      mouse.x < info.X || mouse.x >= info.X + info.Width)
  {
    return; // return if the mouse is outside UI bounds
  }

  int ypos = 0;
  // Find the option that corresponds to where the mouse cursor is
  for (int i = 1; i <= info.DialogToRender.OptionCount; i++)
  {
    if (info.DialogToRender.GetOptionState(i) == eOptionOn)
    {
      ypos += GetTextHeight(info.DialogToRender.GetOptionText(i), eFontFont0, info.Width - 10);
      if ((mouse.y - info.Y) < ypos)
      {
        info.ActiveOptionID = i;
        return;
      }
    }
  }
}

function dialog_options_mouse_click(DialogOptionsRenderingInfo *info, MouseButton button)
{
  if (button == eMouseLeft) {
    if (info.ActiveOptionID > 0)
    info.RunActiveOption();
  }
}

imagazelle

So I've almost gotten the text width-constrained highlighting to work. It waits until you are actually over the text on the x-axis before highlighting, but there is a side-effect where, if you mouse above a line of text, parallel to its x-axis but not on its y-axis, it will still highlight it.

Here's the relevant part of the script, with my addition starting at the "&&" on line 8:

Code: ags

int ypos = 0;
// Find the option that corresponds to where the mouse cursor is
for (int i = 1; i <= info.DialogToRender.OptionCount; i++)
{
  if (info.DialogToRender.GetOptionState(i) == eOptionOn)
  {
    ypos += GetTextHeight(info.DialogToRender.GetOptionText(i), eFontFont0, info.Width - 10);
    if ((mouse.y - info.Y) < ypos && (mouse.x < GetTextWidth(info.DialogToRender.GetOptionText(i), eFontFont0)))
    {
      info.ActiveOptionID = i;
      return;
    }
  }
}


Any ideas?

Here's the complete code from the global script, if anyone would like to test it on their end:

Code: ags

int dlg_opt_acolor = 13;
int dlg_opt_ncolor = 4;

function dialog_options_get_dimensions(DialogOptionsRenderingInfo *info)
{
  // Create a 400x200 dialog options area at (50,100)
  info.X = 50;
  info.Y = 100;
  info.Width = 400;
  info.Height = 200;
  // Enable alpha channel for the drawing surface
  info.HasAlphaChannel = true;
}

function dialog_options_render(DialogOptionsRenderingInfo *info)
{
  int ypos = 0;
 
  for (int i = 1; i <= info.DialogToRender.OptionCount; i++)
  {
    if (info.DialogToRender.GetOptionState(i) == eOptionOn)
    {
      if (info.ActiveOptionID == i)
        info.Surface.DrawingColor = dlg_opt_acolor;
      else
        info.Surface.DrawingColor = dlg_opt_ncolor;

      info.Surface.DrawStringWrapped(5, ypos, info.Width - 10,
              eFontFont0, eAlignLeft, info.DialogToRender.GetOptionText(i));
      ypos += GetTextHeight(info.DialogToRender.GetOptionText(i), eFontFont0, info.Width - 10);
    }
  }
}

function dialog_options_repexec(DialogOptionsRenderingInfo *info)
{
  info.ActiveOptionID = 0;
  if (mouse.y < info.Y || mouse.y >= info.Y + info.Height ||
      mouse.x < info.X || mouse.x >= info.X + info.Width)
  {
    return; // return if the mouse is outside UI bounds
  }

  int ypos = 0;
  // Find the option that corresponds to where the mouse cursor is
  for (int i = 1; i <= info.DialogToRender.OptionCount; i++)
  {
    if (info.DialogToRender.GetOptionState(i) == eOptionOn)
    {
      ypos += GetTextHeight(info.DialogToRender.GetOptionText(i), eFontFont0, info.Width - 10);
      if ((mouse.y - info.Y) < ypos && (mouse.x < GetTextWidth(info.DialogToRender.GetOptionText(i), eFontFont0)))
      {
        info.ActiveOptionID = i;
        return;
      }
    }
  }
}

function dialog_options_mouse_click(DialogOptionsRenderingInfo *info, MouseButton button)
{
  if (button == eMouseLeft) {
    if (info.ActiveOptionID > 0)
    info.RunActiveOption();
  }
}

SMF spam blocked by CleanTalk