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!
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:
// 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.
Use this instead.
// GlobalScript.asc
function on_mouse_click(MouseButton button) {
//...
if (gMyGUI.Visible && GUI.GetAtScreenXY(mouse.x, mouse.y) != gMyGUI) gMyGUI.Visible = false;
//...
}
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:
// 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;
}
}
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.
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.
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!
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?
Save the location the player clicked on:
// 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.
// interaction button
function bInteract_OnClick(...) {
ProcessClick(click_x, click_y, eModeInteract);
}
Alright i tried what you reccommended but its saying undefined token on click_x
//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?
Like I said,
int click_x, click_y;
has to go above on_mouse_click, i.e. outside the function body:
...
int click_x, click_y;
function on_mouse_click(...) {
...
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 if(gINT.Visible == true && GUIControl.GetAtScreenXY(<x240, <y38));
or somthing of the like.
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:
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:
DisplayInteractionGUI(click_x, click_y);
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.
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:
// 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);
}
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
// 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 if (IsGamePaused() == 1) {
// Game is paused, so do nothing (ie. don't allow mouse click)