Sierra-Style GUI - Left-click and Cycle won't work

Started by Scorpio82, Sat 23/09/2006 05:30:49

Previous topic - Next topic

Scorpio82

 I'd hate to post another one of these GUI threads due to all the similar ones floating around, but I can't seem to seem to find what I'm looking for and it seems like such a simple problem.

Basically, when I click on my inventory window, I have it set up so it disables WalkTo and TalkTo, and enables Pointer, so the user should be able to use the Look, Hand, and Use cursors I've set up. 

But here's the two problems I'm having:

1. I can get the mouse to the cycle through cursors, but it never cycles through the Pointer.  I can start it on the Pointer, but once I cycle off of it, I can't get it back.

2.  Left-click does nothing to the inventory.  I can't look at or interact with it.  I'm assuming that's because I turned off "Handle Inventory Clicks" but I'm not sure what code to put in to get it to work, or where it goes. 

Here's an edited sample of my global script which includes everything I edited to get this far.


Quote
function show_inventory_window () {

  GUIOn (INVENTORY); 
  mouse.DisableMode(eModeWalkto);
  mouse.DisableMode(eModeTalkto);
  mouse.EnableMode(eModePointer);
  SetCursorMode (MODE_USE);
  SetMouseCursor (6);

}



function on_mouse_click(int button) {
  // called when a mouse button is clicked. button is either LEFT or RIGHT
  if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
  }
  else if (button==LEFT) {
    ProcessClick(mouse.x, mouse.y, GetCursorMode() );
   }
  else if (button==RIGHT) {   // right-click, so cycle cursor
    SetNextCursorMode();
   }
   
   else if (button == eMouseLeftInv) // left click on inventory item
{
   if (mouse.Mode == eModeInteract)
   {
      // select inventory item on eModeInteract:
      player.ActiveInventory = inventory[ game.inv_activated ];
   }
   else if (mouse.Mode == eModeLookat)
   {
      inventory[ game.inv_activated ].RunInteraction( eModeLookat );
   }
}
}

function on_event(int event, int data) {
  //...
 
  if (event == GUI_MDOWN) { // if mouse button pressed when over a GUI
    if (IsButtonDown(RIGHT)) { // if right mouse button pressed
      SetNextCursorMode();
      }
      if (IsButtonDown(LEFT)) { // if right mouse button pressed
      on_mouse_click(LEFT);
      }
}
}

Ashen

1. 'Pointer' is a reserved mode, it can't be accessed by the standard cycling through the modes. (Most modes, you can set whether it's accessable or not with the 'Standard cursor mode' checkbox, but not eModePointer.) If you want to access it, you'll probably need to change the Right-Click code to move through the modes manually, rather than using mouse.SelecttNextMode();, or the equivilant (NOTE: What version are you using? The code seems a hodge-podge of 'old' and 'new' styles).

2. Without 'Handle Inventory clicks in script' checked, AGS' default behaviour is to handle Left-Click Inventory Items as set active inventory, and Right-Click as look at - why make it harder for yourself by trying to code it manually?

Also, I don't quite see what you're trying to achieve. Since the standard Right-Click-cycle-cursor interaction is disabled when a GUI is up, the player should only be able to select modes you give them buttons for (as on the default Inventory GUI).
With the current code, eModePointer is NEVER set as the current mode (it enables eModePointer, but sets the mode to eModeInteract/MODE_USE), so why are you concerned with it?
I know what you're thinking ... Don't think that.

Scorpio82

Quote from: Ashen on Sat 23/09/2006 13:06:55(NOTE: What version are you using? The code seems a hodge-podge of 'old' and 'new' styles).

Probably because I started making this a long time ago, and then got back on it in the last few months with the upgraded version.  Might also be because I've been searching these forums to answer all my other questions and kept getting older posts with older code. 

Either way, I went through my code and upgraded everything, so now I'm back to square one.  Does this look any better?

Quote
function show_inventory_window () {
// This demonstrates both types of inventory window - the first part is how to
  // show the built-in inventory window, the second part uses the custom one.
  // Un-comment one section or the other below.
 
  // ** DEFAULT INVENTORY WINDOW
//  InventoryScreen(); 
  // ** CUSTOM INVENTORY WINDOW

 
  gInventory.Visible = true; 
  gui[1].Visible = false;
  mouse.DisableMode(eModeWalkto);
  mouse.DisableMode(eModeTalkto);
  mouse.EnableMode(eModePointer);
  mouse.Mode = eModePointer;// switch to the Use cursor (to select items with)
  // But, override the appearance to look like the arrow
}

Quote
#sectionstart on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(MouseButton button) {
  // called when a mouse button is clicked. button is either LEFT or RIGHT
  if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
  }
  else if (button == eMouseLeft) {
    ProcessClick(mouse.x, mouse.y, mouse.Mode );
   }
  else if (button == eMouseRight) {   // right-click, so cycle cursor
    mouse.SelectNextMode();
   }
   
   else if (button == eMouseLeftInv) // left click on inventory item
   {
     if (mouse.Mode == eModePointer)
     {
        // select inventory item on eModeInteract:
        player.ActiveInventory = inventory[ game.inv_activated ];
     }
     else if (mouse.Mode == eModeLookat)
     {
        inventory[ game.inv_activated ].RunInteraction( eModeLookat );
      }
      else if (mouse.Mode == eModeInteract)
     {
      inventory[ game.inv_activated ].RunInteraction( eModeInteract );
     }
  }
}

function on_event(int event, int data) {
  //...
 
  if (event == eEventGUIMouseDown) { // if mouse button pressed when over a GUI
    if (IsButtonDown(eMouseRight)) { // if right mouse button pressed
      mouse.SelectNextMode();
      }
      if (IsButtonDown(eMouseLeft)) { // if right mouse button pressed
      on_mouse_click(eMouseLeft);
      }
}
}

#sectionend on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE

Also I switched off "Handle Inventory Clicks."  Now it's letting me interact with the inventory items, but I'm still having the other problems.

QuoteAlso, I don't quite see what you're trying to achieve.

Sorry, I'll try to be specific.

WHAT I WANT:
Basically, I'm just trying to make a standard Sierra inventory interface, like in KQ5 or LB2.  When the Inventory GUI comes up, the cursor should change to SELECT, and be able to cycle through the LOOK AT, INTERACT, and SELECT cursors when I right-click.  Left-click just executes the cursor's function.

WHAT I GOT BUT DON'T WANT:
-Right-clicking over an inventory item both cycles and LOOKS at the items.  I don't want right-click to bring up a LOOK message.  How can I disable this?
-When I bring up the inventory, it switches to the Select cursor, but the Select cursor does not become part of this GUI's cursor cycle.  It just toggles between LOOK and INTERACT.  How can I add it to the cycle?
-At the moment, Interact seems to do all the Select functions.  What script can I use so I can switch it over to regular Interact functions, and keep it seperate from Select? 

Let me know if you need anymore samples of my script.

Ashen

That's certianly more consistant, yes. And thanks for the extra explanation - I had thought you wanted pretty much the exact opposite of what you actually do.

As I said, eModePointer (which I assume is what you mean by "the Select cursor"?) will never be part of the standard cycle, so you'll either need to use one of the other, unused, modes (eModePickup, for example), or code it yourself. I recommend coding it - more in a second.
Also as I said, the default DON'T handle Inventory clicks in script behaviour is that left-clicking (in eModeInteract, anyway) will set the item as Active, and right-clicking runs the Look at interaction. The reason you've got right-click Looking AND cycling the cursor, is you're using the default behaviour (Look), and you've got the on_event code as well (cycle). Left-clicking doesn't do two things because on_event essecntial calls ProcessClick for that - which ignores GUIs.

So, re-check the 'Handle Inventory clicks in script' option. then change on_event to:

Code: ags

function on_event(int event, int data) {
  //...
 
  if (event == eEventGUIMouseDown) { // if mouse button pressed when over a GUI
    if (mouse.IsButtonDown(eMouseRight)) { // if right mouse button pressed
      if (mouse.Mode == eModePointer) mouse.Mode = eModeLookat;
      else if (mouse.Mode == eModeLookat) mouse.Mode = eModeInteract;
      else if (mouse.Mode == eModeInteract) mouse.Mode = eModePointer;
    }
 }
}


This way you don't need to disable the other modes (Walk, Talk), so you can take those lines out of show_inventory_window, and if you haven't already, you'll probably want to add something to make sure eModePointer isn't selected when the GUI is closed. Depending on how exactly you've got it set up, you might need to add a few more checks, to deal with an Active inventory item while the GUI is up, currently that will 'lock' the cursor, unless a button is used to change it - I wasn't sure how you wanted to deal with this so I just ignored it. Hopefully, you can see how you'd fix that for yourself, if needed. You should be OK not having a left-click check in on_event, since that's on_mouse_click is for.

Oh, and the on_mouse_click condition for eMouseLeftInv could probably be condensed to:
Code: ags

else if (button == eMouseLeftInv) // left click on inventory item
   {
     if (mouse.Mode == eModePointer)
     {
        // select inventory item on eModeInteract:
        player.ActiveInventory = inventory[ game.inv_activated ];
     }
     else inventory[ game.inv_activated ].RunInteraction( mouse.Mode );

  }

I know what you're thinking ... Don't think that.

Scorpio82


Cool!  The cycle's actually working now!

The only thing thing that's missing now is that the left-click function still doesn't work.  I can cycle the cursors, but I can't interect with the inventory.  It's probably because I need to throw in a command in the on_event function that reads a left-click over the GUI, but none of the ones I try work. 

Another thing I need while I'm here is a way to temporarily change the mouse cursor to WAIT whenever a text message pops up.  At the moment, it just displays the default cursor.  I know I can use the mouse.Mode command, but I'm not sure where to put it.

Sorry for the constant questions - I made a list of things I need to polish before I continue my game.

Ashen

That's weird ... if you've got 'Handle Inventory clicks in script' checked, then like I said on_mouse_click should deal with that - except that I've tested it, and you're right it doesn't work. Fortunately, I might've figured out why. Is your Inventory GUI 'Popup Modal'? If so, on_mouse_click is 'blocked' from running so the eMouseLeftInv condition is no use. I totally forgot about that. You just need to re-arrange it slightly, like this:
Code: ags

#sectionstart on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(MouseButton button) {
  // called when a mouse button is clicked. button is either LEFT or RIGHT
  if (button == eMouseLeftInv) {
     if (mouse.Mode == eModePointer) {
        // select inventory item on eModeInteract:
        player.ActiveInventory = inventory[game.inv_activated];
     }
     else inventory[game.inv_activated].RunInteraction(mouse.Mode);

  }
  else if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
    // THIS is why it wasn't working.
  }
  else if (button == eMouseLeft) {
    ProcessClick(mouse.x, mouse.y, mouse.Mode );
  }
  else {   // right-click, so cycle cursor
    mouse.SelectNextMode();
  }
}
#sectionend on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE


And for the second question, you could create a function to handle it for you, e.g.:
Code: ags

function wDisplay(String message) {
  mouse.UseModeGraphic(eModeWait);
  Display(message);
  mouse.UseDefaultGraphic();
}


Then instead of using Display("Whatever");, use wDisplay("Whatever");. (Don't forget to import in into the Global Header, if you want to use it in Room scripts.)  You wouldn't be able to use the extended formating things (e.g. Display("%d curses upon you!", myInt), but other than that it works.
I know what you're thinking ... Don't think that.

Scorpio82

 Ha ha!  It works!  Niiiiiice!  The interface is now perfect.  Muchos gracias!

On top of your script, I also added a few lines for better performance.

Quote
function on_event(int event, int data) {
  //...
 
  if (event == eEventGUIMouseDown) { // if mouse button pressed when over a GUI
    if (mouse.IsButtonDown(eMouseRight)) { // if right mouse button pressed
      if (mouse.Mode == eModePointer) mouse.Mode = eModeLookat;
      else if (mouse.Mode == eModeLookat) mouse.Mode = eModeInteract;
      else if ((mouse.Mode == eModeInteract) && (player.ActiveInventory == null)) mouse.Mode = eModePointer;
      else if ((mouse.Mode == eModeInteract) && (player.ActiveInventory != null)) mouse.Mode = eModeUseinv;
      else if (mouse.Mode == eModeUseinv) mouse.Mode = eModeLookat;

      }

  }

Putting these lines enable the cycle to switch over to the inventory instead of the pointer if it's active.

Quote
#sectionstart btnInvSelect_Click  // DO NOT EDIT OR REMOVE THIS LINE
function btnInvSelect_Click(GUIControl *control, MouseButton button) {
 
   mouse.Mode = eModePointer;
   player.ActiveInventory = null;
   
}
#sectionend btnInvSelect_Click  // DO NOT EDIT OR REMOVE THIS LINE

And this simple line removes the active inventory when you select the pointer from the button GUI.  Just in case anyone else happens upon this thread asking the same question.

As for wDisplay, the function works, but I'd like to be able to have more control over the Display function if I need to. 

So, I tried writing this code instead, which should accomodate any scenario, but it doesn't seem to work either.  Is there a similar way to write this so the game understands a text message has been called and reacts to it?

Quote
#sectionstart repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE

function repeatedly_execute() {
  // put anything you want to happen every game cycle here\
 
  if (gTextwindow.Visible == true) {
  mouse.UseModeGraphic(eModeWait);
}
}

#sectionend repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE

SMF spam blocked by CleanTalk