(Solved)Help with my Custom GUI Interface

Started by Diath, Fri 08/04/2011 21:14:15

Previous topic - Next topic

Diath

Help! Im trying to get my custom interface I created to disappear if any mouse click is not on the GUI whenever it is visible. This seems like a really simple task but I cannot figure out how to word it on the script or where at. Any help is appreciated!



monkey0506

You want it to disappear when it's not clicked on? ..it seems somewhat straightforward, but then I'm also somewhat questioning how the user could ever click on it in the first place..:-/

The basic idea would be something like this:

Code: ags
// GlobalScript.asc

function repeatedly_execute()
{
  if (gMygui.Visible)
  {
    if (!mouse.IsButtonDown(eMouseLeft)) gMygui.Visible = false;
  }
}


That, in and of itself, could be simplified, but I wrote it the way I did so you can include whatever additional logic you need to make this actually work properly.

ddq

Use this instead.
Code: ags

// GlobalScript.asc
function on_mouse_click(MouseButton button) {
//...
    if (gMyGUI.Visible && GUI.GetAtScreenXY(mouse.x, mouse.y) != gMyGUI) gMyGUI.Visible = false;
//...
}

monkey0506

Rereading the original post, I now understand it better, but ddq you've overlooked the fact that on_mouse_click is never fired for clicks on a GUI (with the exception of clicks on an InventoryItem which is technically displayed in an InvWindow, a type of GUIControl). So you'd need to use two separate functions to detect a mouse click while the GUI is shown and ensure that it was not on the specified GUI:

Code: ags
// GlobalScript.asc

function on_mouse_click(MouseButton button)
{
  if (gMygui.Visible) gMygui.Visible = false; // this function is never called for GUI clicks
}

function on_event(EventType event, int data)
{
  if (event == eEventGUIMouseDown) // consider eEventGUIMouseUp instead
  {
    if ((gMygui.Visible) && (data != gMygui.ID)) gMygui.Visible = false;
  }
}

ddq

From what I understand, the desire is to close the GUI when the mouse is clicked outside it. I copied that code from my game and it works when you click on not a GUI but I think it might not when clicking on a different GUI besides the one you want to close. If you only have that one GUI visible, the code works, otherwise you might need the extra stuff to handle clicks on other GUIs.

monkey0506

Well checking GUI.GetAtScreenXY from inside on_mouse_click is essentially pointless since on_mouse_click is never called for GUI clicks. That was my point. As ddq pointed out, if you have more than one GUI visible at any given time, then you'd need the code in on_event for it to work.

Diath

Thanks you guys! I originally had something similar to ddq's code only I put it in the on click script on that specific GUI to no avail. But in this case I used ddq's code and it works like a charm, thanks again!



Diath

Alright guys I have a new question that semi relates to my last one. What i want to achieve in the end is basically a custom interface as seen in 6 days a sacrifice.

So with that said. I am not exactly sure how to program my custom made hand button to interact with any of the hotspots I have in my game. Which goes for the look interaction ect ect. I am thinking I have to use the run interaction command for said hotspot(s) (whichever one i clicked on to get my GUI visible). Any suggestions on how to go about this?



Khris

Save the location the player clicked on:

Code: ags
// above on_mouse_click
int click_x, click_y;

// inside on_mouse_click (eMouseLeft):

    // only open interaction GUI if player clicked on something:
    if (GetLocationType(mouse.x, mouse.y) != eLocationNothing) {
      click_x = mouse.x;
      click_y = mouse.y;
      DisplayInteractionGUI(click_x, click_y);
    }
    // else close GUI
    else gInteraction.Visible = false;


DisplayInteraction() is a custom function that positions and displays the interaction GUI. The important thing though is that the coordinates I last clicked on are stored in the two click_x/y variables.

Code: ags
// interaction button
function bInteract_OnClick(...) {

  ProcessClick(click_x, click_y, eModeInteract);
}

Diath

Alright i tried what you reccommended but its saying undefined token on click_x

Code: ags


//on on_mouse_click(MouseButton button) gINT= my custom interface

 if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
    int click_x, click_y;
    
    if (gINT.Visible && GUI.GetAtScreenXY(mouse.x, mouse.y) != gINT) gINT.Visible = false;
    UnPauseGame();

// on else if (button == eMouseRight || button == eMouseWheelSouth){
    if (GetLocationType(mouse.x, mouse.y) != eLocationNothing){ 
      click_x = mouse.x;
      click_y = mouse.y;
      gINT.Visible = true;
      gINT.SetPosition(mouse.x, mouse.y);
      Interpause(); //this is a custom function i made to pause the game if my interface GUI is on


should i put most of this code into a custom function to A: not have so much clutter and B:possibly fix my token problem?



Khris

Like I said,

Code: ags
int click_x, click_y;


has to go above on_mouse_click, i.e. outside the function body:

Code: ags
...

int click_x, click_y;

function on_mouse_click(...) {
  ...

Diath

I apologize in advance since I have so many questions concerning this GUI interface.  But my new problem Is I have the gui appear at whatever hotspot I clicked. But obviously that isnt going to work because it will cause my GUI to go off screen some times.

Now My Interface is  80 by 38 so my GUI cant show up right if its <240x  nor  > 80x. As well as < 162y or > 38.  I am trying to make a function that will check these conditions and make the GUI Set itself up accordingly but the question is ..I guess how?

I am thinking its something among the lines of
Code: ags
 if(gINT.Visible == true && GUIControl.GetAtScreenXY(<x240, <y38)); 
  or somthing of the like.



Khris

First of all you mixed up > and < in your explanation. Secondly, GUIs are positioned by the top-left corner, so valid x/y values are 0-240 and 0-162.

What you must do is confine x and y to the allowed range, then display the GUI there. The code line you posted is, I'm sorry to say, horribly wrong; you must check (and if necessary, change) the coordinates before the GUI is moved there, not when it's already on the screen. Also, GUIControl.GetAtScreenXY returns the GUIControl at specific coordinates, you can't feed it a range like that.

I'm aware that you just wanted to illustrate your question, but you must learn how to address coding problems, otherwise you'll never get anything done on your own.

I'll go with the function from my other code:

Code: ags
void DisplayInteractionGUI(int x, int y) {

  GUI*g = gINT;
  int w = g.Width;
  int h = g.Height;
  int sw = System.ViewportWidth;
  int sh = System.ViewportHeight;

  // uncomment this to center the GUI at the clicked spot
  // x = x - w/2;
  // y = y - h/2;

  // bind x, y to their allowed range
  if (x < 0) x = 0;
  else if (x + w > sw) x = sw - w;
  if (y < 0) y = 0;
  else if (y + h > sh) y = sh - h;

  g.SetPosition(x, y);
  g.Visible = true;
}


Put this above(!) your on_mouse_click and you should be set if you use the line from my code to call it:
Code: ags
DisplayInteractionGUI(click_x, click_y);

Diath

Thanks Khris

QuoteThe code line you posted is, I'm sorry to say, horribly wrong
Yeah I realized about a half an hour later of
messing around with it that I had to of been wrong. Setting up equations and controlling some of AGS game functions are still pretty foreign to me so I appreciate your patience. Your code worked like a charm


Edit: Alright so now im having issues with the inventory side of my custom interface. Now I am not necessarily asking for a coded solution to this problem but rather what I should do mindset wise to figure out how to solve it. I know I need to somehow have it figure out what inventory item I am clicking on(and which mouse button) and if its viable, use the click_x, click_y cordinates with the inventory item.



Khris

First of all tell AGS that you want to handle inventory clicks yourself, in General settings / Inventory, set "Override built-in inventory window click handling" to True.

Now what happens is if the player clicks on an inventory item, AGS calls on_mouse_click with button being eMouseLeftInv/eMouseRightInv.
To find out which item was clicked on you can use game.inv_activated:

Code: ags
// inside on_mouse_click

  else if (button == eMouseLeftInv) {  // use inv item
    player.ActiveInventory = inventory[game.inv_activated];
    ProcessClick(click_x, click_y, eModeUseinv);
  }
  else if (button == eMouseRightInv) {  // look at item
    inventory[game.inv_activated].RunInteraction(eModeLookat);
  }

Diath

GAH!! I feel like I am sooo close..

I have my GUI set to pause the game when its visible. So in the script you gave me I have it so
Code: ags
  // inside on_mouse_click

  else if (button == eMouseLeftInv) {  // use inv item
    player.ActiveInventory = inventory[game.inv_activated];
    ProcessClick(click_x, click_y, eModeUseinv);
    gINT.Visible = false;
  }
  else if (button == eMouseRightInv) {  // look at item
    inventory[game.inv_activated].RunInteraction(eModeLookat);
    gINT.visible = false;
  }


but for some reason its causing the interface to stay there and not process the inventory item. I also tried disabling the pause when gui is visible option and put in pause commands. This causes me to have to click on inventory items a couple of times before they process though :/ Ill mess with it more after I get home from work.

Edit 4/16/2011: I have also discovered that when i click on an inventory item or anywhere on the inventory box it un-pauses the game. Doing some research, it appears that I may have to mess with the On_Event function. But I am not completely sure, so any help is more than welcome!

Edit of the edit 4/17/2011: I finally figured it out. I needed to put all the inventory scripting above
Code: ags
 if (IsGamePaused() == 1) { 
    // Game is paused, so do nothing (ie. don't allow mouse click) 





SMF spam blocked by CleanTalk