1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14
15 #include <stdio.h>
16 #include "ac/gui.h"
17 #include "ac/common.h"
18 #include "ac/draw.h"
19 #include "ac/event.h"
20 #include "ac/gamesetup.h"
21 #include "ac/gamesetupstruct.h"
22 #include "ac/global_character.h"
23 #include "ac/global_game.h"
24 #include "ac/global_gui.h"
25 #include "ac/global_inventoryitem.h"
26 #include "ac/global_screen.h"
27 #include "ac/guicontrol.h"
28 #include "ac/interfacebutton.h"
29 #include "ac/invwindow.h"
30 #include "ac/mouse.h"
31 #include "ac/roomstruct.h"
32 #include "ac/runtime_defines.h"
33 #include "ac/system.h"
34 #include "ac/dynobj/cc_guiobject.h"
35 #include "ac/dynobj/scriptgui.h"
36 #include "script/cc_instance.h"
37 #include "debug/debug_log.h"
38 #include "device/mousew32.h"
39 #include "gfx/gfxfilter.h"
40 #include "gui/guibutton.h"
41 #include "gui/guimain.h"
42 #include "script/script.h"
43 #include "script/script_runtime.h"
44 #include "gfx/graphicsdriver.h"
45 #include "gfx/bitmap.h"
46 #include "ac/dynobj/cc_gui.h"
47 #include "ac/dynobj/cc_guiobject.h"
48 #include "script/runtimescriptvalue.h"
49
50 using namespace AGS::Common;
51 using namespace AGS::Engine;
52
53
54 extern GameSetup usetup;
55 extern roomstruct thisroom;
56 extern int cur_mode,cur_cursor;
57 extern ccInstance *gameinst;
58 extern ScriptGUI *scrGui;
59 extern GameSetupStruct game;
60 extern CCGUIObject ccDynamicGUIObject;
61 extern Bitmap **guibg;
62 extern IDriverDependantBitmap **guibgbmp;
63 extern IGraphicsDriver *gfxDriver;
64
65 extern CCGUI ccDynamicGUI;
66 extern CCGUIObject ccDynamicGUIObject;
67
68
69 int ifacepopped=-1; // currently displayed pop-up GUI (-1 if none)
70 int mouse_on_iface=-1; // mouse cursor is over this interface
71 int mouse_on_iface_button=-1;
72 int mouse_pushed_iface=-1; // this BUTTON on interface MOUSE_ON_IFACE is pushed
73 int mouse_ifacebut_xoffs=-1,mouse_ifacebut_yoffs=-1;
74
75 int eip_guinum, eip_guiobj;
76
77
GUI_SetVisible(ScriptGUI * tehgui,int isvisible)78 void GUI_SetVisible(ScriptGUI *tehgui, int isvisible) {
79 if (isvisible)
80 InterfaceOn(tehgui->id);
81 else
82 InterfaceOff(tehgui->id);
83 }
84
GUI_GetVisible(ScriptGUI * tehgui)85 int GUI_GetVisible(ScriptGUI *tehgui) {
86 // GUI_GetVisible is slightly different from IsGUIOn, because
87 // with a mouse ypos gui it returns 1 if the GUI is enabled,
88 // whereas IsGUIOn actually checks if it is displayed
89 if (!guis[tehgui->id].IsOff())
90 return 1;
91 return 0;
92 }
93
GUI_GetX(ScriptGUI * tehgui)94 int GUI_GetX(ScriptGUI *tehgui) {
95 return divide_down_coordinate(guis[tehgui->id].X);
96 }
97
GUI_SetX(ScriptGUI * tehgui,int xx)98 void GUI_SetX(ScriptGUI *tehgui, int xx) {
99 guis[tehgui->id].X = multiply_up_coordinate(xx);
100 }
101
GUI_GetY(ScriptGUI * tehgui)102 int GUI_GetY(ScriptGUI *tehgui) {
103 return divide_down_coordinate(guis[tehgui->id].Y);
104 }
105
GUI_SetY(ScriptGUI * tehgui,int yy)106 void GUI_SetY(ScriptGUI *tehgui, int yy) {
107 guis[tehgui->id].Y = multiply_up_coordinate(yy);
108 }
109
GUI_SetPosition(ScriptGUI * tehgui,int xx,int yy)110 void GUI_SetPosition(ScriptGUI *tehgui, int xx, int yy) {
111 GUI_SetX(tehgui, xx);
112 GUI_SetY(tehgui, yy);
113 }
114
GUI_SetSize(ScriptGUI * sgui,int widd,int hitt)115 void GUI_SetSize(ScriptGUI *sgui, int widd, int hitt) {
116 if ((widd < 1) || (hitt < 1))
117 quitprintf("!SetGUISize: invalid dimensions (tried to set to %d x %d)", widd, hitt);
118
119 GUIMain *tehgui = &guis[sgui->id];
120 multiply_up_coordinates(&widd, &hitt);
121
122 if ((tehgui->Width == widd) && (tehgui->Height == hitt))
123 return;
124
125 tehgui->Width = widd;
126 tehgui->Height = hitt;
127
128 recreate_guibg_image(tehgui);
129
130 guis_need_update = 1;
131 }
132
GUI_GetWidth(ScriptGUI * sgui)133 int GUI_GetWidth(ScriptGUI *sgui) {
134 return divide_down_coordinate(guis[sgui->id].Width);
135 }
136
GUI_GetHeight(ScriptGUI * sgui)137 int GUI_GetHeight(ScriptGUI *sgui) {
138 return divide_down_coordinate(guis[sgui->id].Height);
139 }
140
GUI_SetWidth(ScriptGUI * sgui,int newwid)141 void GUI_SetWidth(ScriptGUI *sgui, int newwid) {
142 GUI_SetSize(sgui, newwid, GUI_GetHeight(sgui));
143 }
144
GUI_SetHeight(ScriptGUI * sgui,int newhit)145 void GUI_SetHeight(ScriptGUI *sgui, int newhit) {
146 GUI_SetSize(sgui, GUI_GetWidth(sgui), newhit);
147 }
148
GUI_SetZOrder(ScriptGUI * tehgui,int z)149 void GUI_SetZOrder(ScriptGUI *tehgui, int z) {
150 guis[tehgui->id].ZOrder = z;
151 update_gui_zorder();
152 }
153
GUI_GetZOrder(ScriptGUI * tehgui)154 int GUI_GetZOrder(ScriptGUI *tehgui) {
155 return guis[tehgui->id].ZOrder;
156 }
157
GUI_SetClickable(ScriptGUI * tehgui,int clickable)158 void GUI_SetClickable(ScriptGUI *tehgui, int clickable) {
159 guis[tehgui->id].Flags &= ~kGUIMain_NoClick;
160 if (clickable == 0)
161 guis[tehgui->id].Flags |= kGUIMain_NoClick;
162 }
163
GUI_GetClickable(ScriptGUI * tehgui)164 int GUI_GetClickable(ScriptGUI *tehgui) {
165 if (guis[tehgui->id].Flags & kGUIMain_NoClick)
166 return 0;
167 return 1;
168 }
169
GUI_GetID(ScriptGUI * tehgui)170 int GUI_GetID(ScriptGUI *tehgui) {
171 return tehgui->id;
172 }
173
GUI_GetiControls(ScriptGUI * tehgui,int idx)174 GUIObject* GUI_GetiControls(ScriptGUI *tehgui, int idx) {
175 if ((idx < 0) || (idx >= guis[tehgui->id].ControlCount))
176 return NULL;
177 return guis[tehgui->id].Controls[idx];
178 }
179
GUI_GetControlCount(ScriptGUI * tehgui)180 int GUI_GetControlCount(ScriptGUI *tehgui) {
181 return guis[tehgui->id].ControlCount;
182 }
183
GUI_SetTransparency(ScriptGUI * tehgui,int trans)184 void GUI_SetTransparency(ScriptGUI *tehgui, int trans) {
185 if ((trans < 0) | (trans > 100))
186 quit("!SetGUITransparency: transparency value must be between 0 and 100");
187
188 guis[tehgui->id].SetTransparencyAsPercentage(trans);
189 }
190
GUI_GetTransparency(ScriptGUI * tehgui)191 int GUI_GetTransparency(ScriptGUI *tehgui) {
192 if (guis[tehgui->id].Transparency == 0)
193 return 0;
194 if (guis[tehgui->id].Transparency == 255)
195 return 100;
196
197 return 100 - ((guis[tehgui->id].Transparency * 10) / 25);
198 }
199
GUI_Centre(ScriptGUI * sgui)200 void GUI_Centre(ScriptGUI *sgui) {
201 GUIMain *tehgui = &guis[sgui->id];
202 tehgui->X = play.viewport.GetWidth() / 2 - tehgui->Width / 2;
203 tehgui->Y = play.viewport.GetHeight() / 2 - tehgui->Height / 2;
204 }
205
GUI_SetBackgroundGraphic(ScriptGUI * tehgui,int slotn)206 void GUI_SetBackgroundGraphic(ScriptGUI *tehgui, int slotn) {
207 if (guis[tehgui->id].BgImage != slotn) {
208 guis[tehgui->id].BgImage = slotn;
209 guis_need_update = 1;
210 }
211 }
212
GUI_GetBackgroundGraphic(ScriptGUI * tehgui)213 int GUI_GetBackgroundGraphic(ScriptGUI *tehgui) {
214 if (guis[tehgui->id].BgImage < 1)
215 return 0;
216 return guis[tehgui->id].BgImage;
217 }
218
GetGUIAtLocation(int xx,int yy)219 ScriptGUI *GetGUIAtLocation(int xx, int yy) {
220 int guiid = GetGUIAt(xx, yy);
221 if (guiid < 0)
222 return NULL;
223 return &scrGui[guiid];
224 }
225
GUI_Click(ScriptGUI * scgui,int mbut)226 void GUI_Click(ScriptGUI *scgui, int mbut)
227 {
228 process_interface_click(scgui->id, -1, mbut);
229 }
230
GUI_ProcessClick(int x,int y,int mbut)231 void GUI_ProcessClick(int x, int y, int mbut)
232 {
233 int guiid = gui_get_interactable(x, y);
234 if (guiid >= 0)
235 {
236 const int real_mousex = mousex;
237 const int real_mousey = mousey;
238 mousex = x;
239 mousey = y;
240 guis[guiid].Poll();
241 gui_on_mouse_down(guiid, mbut);
242 gui_on_mouse_up(guiid, mbut);
243 mousex = real_mousex;
244 mousey = real_mousey;
245 }
246 }
247
248 //=============================================================================
249
remove_popup_interface(int ifacenum)250 void remove_popup_interface(int ifacenum) {
251 if (ifacepopped != ifacenum) return;
252 ifacepopped=-1; UnPauseGame();
253 guis[ifacenum].SetVisibility(kGUIVisibility_Off);
254 if (mousey<=guis[ifacenum].PopupAtMouseY)
255 Mouse::SetPosition(Point(mousex, guis[ifacenum].PopupAtMouseY+2));
256 if ((!IsInterfaceEnabled()) && (cur_cursor == cur_mode))
257 // Only change the mouse cursor if it hasn't been specifically changed first
258 set_mouse_cursor(CURS_WAIT);
259 else if (IsInterfaceEnabled())
260 set_default_cursor();
261
262 if (ifacenum==mouse_on_iface) mouse_on_iface=-1;
263 guis_need_update = 1;
264 }
265
process_interface_click(int ifce,int btn,int mbut)266 void process_interface_click(int ifce, int btn, int mbut) {
267 if (btn < 0) {
268 // click on GUI background
269 QueueScriptFunction(kScInstGame, guis[ifce].OnClickHandler, 2,
270 RuntimeScriptValue().SetDynamicObject(&scrGui[ifce], &ccDynamicGUI),
271 RuntimeScriptValue().SetInt32(mbut));
272 return;
273 }
274
275 int btype=(guis[ifce].CtrlRefs[btn] >> 16) & 0x000ffff;
276 int rtype=0,rdata;
277 if (btype==kGUIButton) {
278 GUIButton*gbuto=(GUIButton*)guis[ifce].Controls[btn];
279 rtype=gbuto->leftclick;
280 rdata=gbuto->lclickdata;
281 }
282 else if ((btype==kGUISlider) || (btype == kGUITextBox) || (btype == kGUIListBox))
283 rtype = IBACT_SCRIPT;
284 else quit("unknown GUI object triggered process_interface");
285
286 if (rtype==0) ;
287 else if (rtype==IBACT_SETMODE)
288 set_cursor_mode(rdata);
289 else if (rtype==IBACT_SCRIPT) {
290 GUIObject *theObj = guis[ifce].Controls[btn];
291 // if the object has a special handler script then run it;
292 // otherwise, run interface_click
293 if ((theObj->GetNumEvents() > 0) &&
294 (!theObj->eventHandlers[0].IsEmpty()) &&
295 (!gameinst->GetSymbolAddress(theObj->eventHandlers[0]).IsNull())) {
296 // control-specific event handler
297 if (strchr(theObj->GetEventArgs(0), ',') != NULL)
298 QueueScriptFunction(kScInstGame, theObj->eventHandlers[0], 2,
299 RuntimeScriptValue().SetDynamicObject(theObj, &ccDynamicGUIObject),
300 RuntimeScriptValue().SetInt32(mbut));
301 else
302 QueueScriptFunction(kScInstGame, theObj->eventHandlers[0], 1,
303 RuntimeScriptValue().SetDynamicObject(theObj, &ccDynamicGUIObject));
304 }
305 else
306 QueueScriptFunction(kScInstGame, "interface_click", 2,
307 RuntimeScriptValue().SetInt32(ifce),
308 RuntimeScriptValue().SetInt32(btn));
309 }
310 }
311
312
replace_macro_tokens(const char * statusbarformat,char * cur_stb_text)313 void replace_macro_tokens(const char*statusbarformat,char*cur_stb_text) {
314 const char*curptr=&statusbarformat[0];
315 char tmpm[3];
316 const char*endat = curptr + strlen(statusbarformat);
317 cur_stb_text[0]=0;
318 char tempo[STD_BUFFER_SIZE];
319
320 while (1) {
321 if (curptr[0]==0) break;
322 if (curptr>=endat) break;
323 if (curptr[0]=='@') {
324 const char *curptrWasAt = curptr;
325 char macroname[21]; int idd=0; curptr++;
326 for (idd=0;idd<20;idd++) {
327 if (curptr[0]=='@') {
328 macroname[idd]=0;
329 curptr++;
330 break;
331 }
332 // unterminated macro (eg. "@SCORETEXT"), so abort
333 if (curptr[0] == 0)
334 break;
335 macroname[idd]=curptr[0];
336 curptr++;
337 }
338 macroname[idd]=0;
339 tempo[0]=0;
340 if (stricmp(macroname,"score")==0)
341 sprintf(tempo,"%d",play.score);
342 else if (stricmp(macroname,"totalscore")==0)
343 sprintf(tempo,"%d",MAXSCORE);
344 else if (stricmp(macroname,"scoretext")==0)
345 sprintf(tempo,"%d of %d",play.score,MAXSCORE);
346 else if (stricmp(macroname,"gamename")==0)
347 strcpy(tempo, play.game_name);
348 else if (stricmp(macroname,"overhotspot")==0) {
349 // While game is in Wait mode, no overhotspot text
350 if (!IsInterfaceEnabled())
351 tempo[0] = 0;
352 else
353 GetLocationName(divide_down_coordinate(mousex), divide_down_coordinate(mousey), tempo);
354 }
355 else { // not a macro, there's just a @ in the message
356 curptr = curptrWasAt + 1;
357 strcpy(tempo, "@");
358 }
359
360 strcat(cur_stb_text,tempo);
361 }
362 else {
363 tmpm[0]=curptr[0]; tmpm[1]=0;
364 strcat(cur_stb_text,tmpm);
365 curptr++;
366 }
367 }
368 }
369
370
update_gui_zorder()371 void update_gui_zorder() {
372 int numdone = 0, b;
373
374 // for each GUI
375 for (int a = 0; a < game.numgui; a++) {
376 // find the right place in the draw order array
377 int insertAt = numdone;
378 for (b = 0; b < numdone; b++) {
379 if (guis[a].ZOrder < guis[play.gui_draw_order[b]].ZOrder) {
380 insertAt = b;
381 break;
382 }
383 }
384 // insert the new item
385 for (b = numdone - 1; b >= insertAt; b--)
386 play.gui_draw_order[b + 1] = play.gui_draw_order[b];
387 play.gui_draw_order[insertAt] = a;
388 numdone++;
389 }
390
391 }
392
393
export_gui_controls(int ee)394 void export_gui_controls(int ee) {
395
396 for (int ff = 0; ff < guis[ee].ControlCount; ff++) {
397 if (!guis[ee].Controls[ff]->scriptName.IsEmpty())
398 ccAddExternalDynamicObject(guis[ee].Controls[ff]->scriptName, guis[ee].Controls[ff], &ccDynamicGUIObject);
399
400 ccRegisterManagedObject(guis[ee].Controls[ff], &ccDynamicGUIObject);
401 }
402 }
403
unexport_gui_controls(int ee)404 void unexport_gui_controls(int ee) {
405
406 for (int ff = 0; ff < guis[ee].ControlCount; ff++) {
407 if (!guis[ee].Controls[ff]->scriptName.IsEmpty())
408 ccRemoveExternalSymbol(guis[ee].Controls[ff]->scriptName);
409
410 if (!ccUnRegisterManagedObject(guis[ee].Controls[ff]))
411 quit("unable to unregister guicontrol object");
412 }
413 }
414
convert_gui_disabled_style(int oldStyle)415 int convert_gui_disabled_style(int oldStyle) {
416 int toret = GUIDIS_GREYOUT;
417
418 // if GUIs Turn Off is selected, don't grey out buttons for
419 // any Persistent GUIs which remain
420 // set to 0x80 so that it is still non-zero, but has no effect
421 if (oldStyle == 3)
422 toret = GUIDIS_GUIOFF;
423 // GUIs Go Black
424 else if (oldStyle == 1)
425 toret = GUIDIS_BLACKOUT;
426 // GUIs unchanged
427 else if (oldStyle == 2)
428 toret = GUIDIS_UNCHANGED;
429
430 return toret;
431 }
432
update_gui_disabled_status()433 void update_gui_disabled_status() {
434 // update GUI display status (perhaps we've gone into
435 // an interface disabled state)
436 int all_buttons_was = all_buttons_disabled;
437 all_buttons_disabled = 0;
438
439 if (!IsInterfaceEnabled()) {
440 all_buttons_disabled = gui_disabled_style;
441 }
442
443 if (all_buttons_was != all_buttons_disabled) {
444 // GUIs might have been removed/added
445 for (int aa = 0; aa < game.numgui; aa++) {
446 guis[aa].OnControlPositionChanged();
447 }
448 guis_need_update = 1;
449 invalidate_screen();
450 }
451 }
452
453
adjust_x_for_guis(int xx,int yy)454 int adjust_x_for_guis (int xx, int yy) {
455 if ((game.options[OPT_DISABLEOFF]==3) && (all_buttons_disabled > 0))
456 return xx;
457 // If it's covered by a GUI, move it right a bit
458 for (int aa=0;aa < game.numgui; aa++) {
459 if (!guis[aa].IsVisible())
460 continue;
461 if ((guis[aa].X > xx) || (guis[aa].Y > yy) || (guis[aa].Y + guis[aa].Height < yy))
462 continue;
463 // totally transparent GUI, ignore
464 if ((guis[aa].BgColor == 0) && (guis[aa].BgImage < 1))
465 continue;
466
467 // try to deal with full-width GUIs across the top
468 if (guis[aa].X + guis[aa].Width >= get_fixed_pixel_size(280))
469 continue;
470
471 if (xx < guis[aa].X + guis[aa].Width)
472 xx = guis[aa].X + guis[aa].Width + 2;
473 }
474 return xx;
475 }
476
adjust_y_for_guis(int yy)477 int adjust_y_for_guis ( int yy) {
478 if ((game.options[OPT_DISABLEOFF]==3) && (all_buttons_disabled > 0))
479 return yy;
480 // If it's covered by a GUI, move it down a bit
481 for (int aa=0;aa < game.numgui; aa++) {
482 if (!guis[aa].IsVisible())
483 continue;
484 if (guis[aa].Y > yy)
485 continue;
486 // totally transparent GUI, ignore
487 if ((guis[aa].BgColor == 0) && (guis[aa].BgImage < 1))
488 continue;
489
490 // try to deal with full-height GUIs down the left or right
491 if (guis[aa].Height > get_fixed_pixel_size(50))
492 continue;
493
494 if (yy < guis[aa].Y + guis[aa].Height)
495 yy = guis[aa].Y + guis[aa].Height + 2;
496 }
497 return yy;
498 }
499
recreate_guibg_image(GUIMain * tehgui)500 void recreate_guibg_image(GUIMain *tehgui)
501 {
502 int ifn = tehgui->Id;
503 delete guibg[ifn];
504 guibg[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, game.GetColorDepth());
505 if (guibg[ifn] == NULL)
506 quit("SetGUISize: internal error: unable to reallocate gui cache");
507 guibg[ifn] = ReplaceBitmapWithSupportedFormat(guibg[ifn]);
508
509 if (guibgbmp[ifn] != NULL)
510 {
511 gfxDriver->DestroyDDB(guibgbmp[ifn]);
512 guibgbmp[ifn] = NULL;
513 }
514 }
515
516 extern int is_complete_overlay;
517
gui_get_interactable(int x,int y)518 int gui_get_interactable(int x,int y)
519 {
520 if ((game.options[OPT_DISABLEOFF]==3) && (all_buttons_disabled > 0))
521 return -1;
522 return GetGUIAt(x, y);
523 }
524
gui_on_mouse_move()525 int gui_on_mouse_move()
526 {
527 int mouse_over_gui = -1;
528 // If all GUIs are off, skip the loop
529 if ((game.options[OPT_DISABLEOFF]==3) && (all_buttons_disabled > 0)) ;
530 else {
531 // Scan for mouse-y-pos GUIs, and pop one up if appropriate
532 // Also work out the mouse-over GUI while we're at it
533 int ll;
534 for (ll = 0; ll < game.numgui;ll++) {
535 const int guin = play.gui_draw_order[ll];
536 if (guis[guin].IsInteractableAt(mousex, mousey)) mouse_over_gui=guin;
537
538 if (guis[guin].PopupStyle!=kGUIPopupMouseY) continue;
539 if (is_complete_overlay>0) break; // interfaces disabled
540 // if (play.disabled_user_interface>0) break;
541 if (ifacepopped==guin) continue;
542 if (guis[guin].IsConcealed()) continue;
543 // Don't allow it to be popped up while skipping cutscene
544 if (play.fast_forward) continue;
545
546 if (mousey < guis[guin].PopupAtMouseY) {
547 set_mouse_cursor(CURS_ARROW);
548 guis[guin].SetVisibility(kGUIVisibility_On); guis_need_update = 1;
549 ifacepopped=guin; PauseGame();
550 break;
551 }
552 }
553 }
554 return mouse_over_gui;
555 }
556
gui_on_mouse_hold(const int wasongui,const int wasbutdown)557 void gui_on_mouse_hold(const int wasongui, const int wasbutdown)
558 {
559 for (int i=0;i<guis[wasongui].ControlCount;i++) {
560 if (guis[wasongui].Controls[i]->activated<1) continue;
561 if (guis[wasongui].GetControlType(i)!=kGUISlider) continue;
562 // GUI Slider repeatedly activates while being dragged
563 guis[wasongui].Controls[i]->activated=0;
564 force_event(EV_IFACECLICK, wasongui, i, wasbutdown);
565 break;
566 }
567 }
568
gui_on_mouse_up(const int wasongui,const int wasbutdown)569 void gui_on_mouse_up(const int wasongui, const int wasbutdown)
570 {
571 guis[wasongui].OnMouseButtonUp();
572
573 for (int i=0;i<guis[wasongui].ControlCount;i++) {
574 if (guis[wasongui].Controls[i]->activated<1) continue;
575 guis[wasongui].Controls[i]->activated=0;
576 if (!IsInterfaceEnabled()) break;
577
578 int cttype=guis[wasongui].GetControlType(i);
579 if ((cttype == kGUIButton) || (cttype == kGUISlider) || (cttype == kGUIListBox)) {
580 force_event(EV_IFACECLICK, wasongui, i, wasbutdown);
581 }
582 else if (cttype == kGUIInvWindow) {
583 mouse_ifacebut_xoffs=mousex-(guis[wasongui].Controls[i]->x)-guis[wasongui].X;
584 mouse_ifacebut_yoffs=mousey-(guis[wasongui].Controls[i]->y)-guis[wasongui].Y;
585 int iit=offset_over_inv((GUIInv*)guis[wasongui].Controls[i]);
586 if (iit>=0) {
587 evblocknum=iit;
588 play.used_inv_on = iit;
589 if (game.options[OPT_HANDLEINVCLICKS]) {
590 // Let the script handle the click
591 // LEFTINV is 5, RIGHTINV is 6
592 force_event(EV_TEXTSCRIPT,TS_MCLICK, wasbutdown + 4);
593 }
594 else if (wasbutdown==2) // right-click is always Look
595 run_event_block_inv(iit, 0);
596 else if (cur_mode == MODE_HAND)
597 SetActiveInventory(iit);
598 else
599 RunInventoryInteraction (iit, cur_mode);
600 evblocknum=-1;
601 }
602 }
603 else quit("clicked on unknown control type");
604 if (guis[wasongui].PopupStyle==kGUIPopupMouseY)
605 remove_popup_interface(wasongui);
606 break;
607 }
608
609 run_on_event(GE_GUI_MOUSEUP, RuntimeScriptValue().SetInt32(wasongui));
610 }
611
gui_on_mouse_down(const int guin,const int mbut)612 void gui_on_mouse_down(const int guin, const int mbut)
613 {
614 debug_script_log("Mouse click over GUI %d", guin);
615 guis[guin].OnMouseButtonDown();
616 // run GUI click handler if not on any control
617 if ((guis[guin].MouseDownCtrl < 0) && (!guis[guin].OnClickHandler.IsEmpty()))
618 force_event(EV_IFACECLICK, guin, -1, mbut);
619
620 run_on_event(GE_GUI_MOUSEDOWN, RuntimeScriptValue().SetInt32(guin));
621 }
622
623 //=============================================================================
624 //
625 // Script API Functions
626 //
627 //=============================================================================
628
629 #include "debug/out.h"
630 #include "script/script_api.h"
631 #include "script/script_runtime.h"
632
633 // void GUI_Centre(ScriptGUI *sgui)
Sc_GUI_Centre(void * self,const RuntimeScriptValue * params,int32_t param_count)634 RuntimeScriptValue Sc_GUI_Centre(void *self, const RuntimeScriptValue *params, int32_t param_count)
635 {
636 API_OBJCALL_VOID(ScriptGUI, GUI_Centre);
637 }
638
639 // ScriptGUI *(int xx, int yy)
Sc_GetGUIAtLocation(const RuntimeScriptValue * params,int32_t param_count)640 RuntimeScriptValue Sc_GetGUIAtLocation(const RuntimeScriptValue *params, int32_t param_count)
641 {
642 API_SCALL_OBJ_PINT2(ScriptGUI, ccDynamicGUI, GetGUIAtLocation);
643 }
644
645 // void (ScriptGUI *tehgui, int xx, int yy)
Sc_GUI_SetPosition(void * self,const RuntimeScriptValue * params,int32_t param_count)646 RuntimeScriptValue Sc_GUI_SetPosition(void *self, const RuntimeScriptValue *params, int32_t param_count)
647 {
648 API_OBJCALL_VOID_PINT2(ScriptGUI, GUI_SetPosition);
649 }
650
651 // void (ScriptGUI *sgui, int widd, int hitt)
Sc_GUI_SetSize(void * self,const RuntimeScriptValue * params,int32_t param_count)652 RuntimeScriptValue Sc_GUI_SetSize(void *self, const RuntimeScriptValue *params, int32_t param_count)
653 {
654 API_OBJCALL_VOID_PINT2(ScriptGUI, GUI_SetSize);
655 }
656
657 // int (ScriptGUI *tehgui)
Sc_GUI_GetBackgroundGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)658 RuntimeScriptValue Sc_GUI_GetBackgroundGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
659 {
660 API_OBJCALL_INT(ScriptGUI, GUI_GetBackgroundGraphic);
661 }
662
663 // void (ScriptGUI *tehgui, int slotn)
Sc_GUI_SetBackgroundGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)664 RuntimeScriptValue Sc_GUI_SetBackgroundGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
665 {
666 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetBackgroundGraphic);
667 }
668
669 // int (ScriptGUI *tehgui)
Sc_GUI_GetClickable(void * self,const RuntimeScriptValue * params,int32_t param_count)670 RuntimeScriptValue Sc_GUI_GetClickable(void *self, const RuntimeScriptValue *params, int32_t param_count)
671 {
672 API_OBJCALL_INT(ScriptGUI, GUI_GetClickable);
673 }
674
675 // void (ScriptGUI *tehgui, int clickable)
Sc_GUI_SetClickable(void * self,const RuntimeScriptValue * params,int32_t param_count)676 RuntimeScriptValue Sc_GUI_SetClickable(void *self, const RuntimeScriptValue *params, int32_t param_count)
677 {
678 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetClickable);
679 }
680
681 // int (ScriptGUI *tehgui)
Sc_GUI_GetControlCount(void * self,const RuntimeScriptValue * params,int32_t param_count)682 RuntimeScriptValue Sc_GUI_GetControlCount(void *self, const RuntimeScriptValue *params, int32_t param_count)
683 {
684 API_OBJCALL_INT(ScriptGUI, GUI_GetControlCount);
685 }
686
687 // GUIObject* (ScriptGUI *tehgui, int idx)
Sc_GUI_GetiControls(void * self,const RuntimeScriptValue * params,int32_t param_count)688 RuntimeScriptValue Sc_GUI_GetiControls(void *self, const RuntimeScriptValue *params, int32_t param_count)
689 {
690 API_OBJCALL_OBJ_PINT(ScriptGUI, GUIObject, ccDynamicGUIObject, GUI_GetiControls);
691 }
692
693 // int (ScriptGUI *sgui)
Sc_GUI_GetHeight(void * self,const RuntimeScriptValue * params,int32_t param_count)694 RuntimeScriptValue Sc_GUI_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count)
695 {
696 API_OBJCALL_INT(ScriptGUI, GUI_GetHeight);
697 }
698
699 // void (ScriptGUI *sgui, int newhit)
Sc_GUI_SetHeight(void * self,const RuntimeScriptValue * params,int32_t param_count)700 RuntimeScriptValue Sc_GUI_SetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count)
701 {
702 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetHeight);
703 }
704
705 // int (ScriptGUI *tehgui)
Sc_GUI_GetID(void * self,const RuntimeScriptValue * params,int32_t param_count)706 RuntimeScriptValue Sc_GUI_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count)
707 {
708 API_OBJCALL_INT(ScriptGUI, GUI_GetID);
709 }
710
711 // int (ScriptGUI *tehgui)
Sc_GUI_GetTransparency(void * self,const RuntimeScriptValue * params,int32_t param_count)712 RuntimeScriptValue Sc_GUI_GetTransparency(void *self, const RuntimeScriptValue *params, int32_t param_count)
713 {
714 API_OBJCALL_INT(ScriptGUI, GUI_GetTransparency);
715 }
716
717 // void (ScriptGUI *tehgui, int trans)
Sc_GUI_SetTransparency(void * self,const RuntimeScriptValue * params,int32_t param_count)718 RuntimeScriptValue Sc_GUI_SetTransparency(void *self, const RuntimeScriptValue *params, int32_t param_count)
719 {
720 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetTransparency);
721 }
722
723 // int (ScriptGUI *tehgui)
Sc_GUI_GetVisible(void * self,const RuntimeScriptValue * params,int32_t param_count)724 RuntimeScriptValue Sc_GUI_GetVisible(void *self, const RuntimeScriptValue *params, int32_t param_count)
725 {
726 API_OBJCALL_INT(ScriptGUI, GUI_GetVisible);
727 }
728
729 // void (ScriptGUI *tehgui, int isvisible)
Sc_GUI_SetVisible(void * self,const RuntimeScriptValue * params,int32_t param_count)730 RuntimeScriptValue Sc_GUI_SetVisible(void *self, const RuntimeScriptValue *params, int32_t param_count)
731 {
732 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetVisible);
733 }
734
735 // int (ScriptGUI *sgui)
Sc_GUI_GetWidth(void * self,const RuntimeScriptValue * params,int32_t param_count)736 RuntimeScriptValue Sc_GUI_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count)
737 {
738 API_OBJCALL_INT(ScriptGUI, GUI_GetWidth);
739 }
740
741 // void (ScriptGUI *sgui, int newwid)
Sc_GUI_SetWidth(void * self,const RuntimeScriptValue * params,int32_t param_count)742 RuntimeScriptValue Sc_GUI_SetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count)
743 {
744 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetWidth);
745 }
746
747 // int (ScriptGUI *tehgui)
Sc_GUI_GetX(void * self,const RuntimeScriptValue * params,int32_t param_count)748 RuntimeScriptValue Sc_GUI_GetX(void *self, const RuntimeScriptValue *params, int32_t param_count)
749 {
750 API_OBJCALL_INT(ScriptGUI, GUI_GetX);
751 }
752
753 // void (ScriptGUI *tehgui, int xx)
Sc_GUI_SetX(void * self,const RuntimeScriptValue * params,int32_t param_count)754 RuntimeScriptValue Sc_GUI_SetX(void *self, const RuntimeScriptValue *params, int32_t param_count)
755 {
756 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetX);
757 }
758
759 // int (ScriptGUI *tehgui)
Sc_GUI_GetY(void * self,const RuntimeScriptValue * params,int32_t param_count)760 RuntimeScriptValue Sc_GUI_GetY(void *self, const RuntimeScriptValue *params, int32_t param_count)
761 {
762 API_OBJCALL_INT(ScriptGUI, GUI_GetY);
763 }
764
765 // void (ScriptGUI *tehgui, int yy)
Sc_GUI_SetY(void * self,const RuntimeScriptValue * params,int32_t param_count)766 RuntimeScriptValue Sc_GUI_SetY(void *self, const RuntimeScriptValue *params, int32_t param_count)
767 {
768 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetY);
769 }
770
771 // int (ScriptGUI *tehgui)
Sc_GUI_GetZOrder(void * self,const RuntimeScriptValue * params,int32_t param_count)772 RuntimeScriptValue Sc_GUI_GetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count)
773 {
774 API_OBJCALL_INT(ScriptGUI, GUI_GetZOrder);
775 }
776
777 // void (ScriptGUI *tehgui, int z)
Sc_GUI_SetZOrder(void * self,const RuntimeScriptValue * params,int32_t param_count)778 RuntimeScriptValue Sc_GUI_SetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count)
779 {
780 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_SetZOrder);
781 }
782
Sc_GUI_Click(void * self,const RuntimeScriptValue * params,int32_t param_count)783 RuntimeScriptValue Sc_GUI_Click(void *self, const RuntimeScriptValue *params, int32_t param_count)
784 {
785 API_OBJCALL_VOID_PINT(ScriptGUI, GUI_Click);
786 }
787
Sc_GUI_ProcessClick(const RuntimeScriptValue * params,int32_t param_count)788 RuntimeScriptValue Sc_GUI_ProcessClick(const RuntimeScriptValue *params, int32_t param_count)
789 {
790 API_SCALL_VOID_PINT3(GUI_ProcessClick);
791 }
792
RegisterGUIAPI()793 void RegisterGUIAPI()
794 {
795 ccAddExternalObjectFunction("GUI::Centre^0", Sc_GUI_Centre);
796 ccAddExternalObjectFunction("GUI::Click^1", Sc_GUI_Click);
797 ccAddExternalStaticFunction("GUI::GetAtScreenXY^2", Sc_GetGUIAtLocation);
798 ccAddExternalStaticFunction("GUI::ProcessClick^3", Sc_GUI_ProcessClick);
799 ccAddExternalObjectFunction("GUI::SetPosition^2", Sc_GUI_SetPosition);
800 ccAddExternalObjectFunction("GUI::SetSize^2", Sc_GUI_SetSize);
801 ccAddExternalObjectFunction("GUI::get_BackgroundGraphic", Sc_GUI_GetBackgroundGraphic);
802 ccAddExternalObjectFunction("GUI::set_BackgroundGraphic", Sc_GUI_SetBackgroundGraphic);
803 ccAddExternalObjectFunction("GUI::get_Clickable", Sc_GUI_GetClickable);
804 ccAddExternalObjectFunction("GUI::set_Clickable", Sc_GUI_SetClickable);
805 ccAddExternalObjectFunction("GUI::get_ControlCount", Sc_GUI_GetControlCount);
806 ccAddExternalObjectFunction("GUI::geti_Controls", Sc_GUI_GetiControls);
807 ccAddExternalObjectFunction("GUI::get_Height", Sc_GUI_GetHeight);
808 ccAddExternalObjectFunction("GUI::set_Height", Sc_GUI_SetHeight);
809 ccAddExternalObjectFunction("GUI::get_ID", Sc_GUI_GetID);
810 ccAddExternalObjectFunction("GUI::get_Transparency", Sc_GUI_GetTransparency);
811 ccAddExternalObjectFunction("GUI::set_Transparency", Sc_GUI_SetTransparency);
812 ccAddExternalObjectFunction("GUI::get_Visible", Sc_GUI_GetVisible);
813 ccAddExternalObjectFunction("GUI::set_Visible", Sc_GUI_SetVisible);
814 ccAddExternalObjectFunction("GUI::get_Width", Sc_GUI_GetWidth);
815 ccAddExternalObjectFunction("GUI::set_Width", Sc_GUI_SetWidth);
816 ccAddExternalObjectFunction("GUI::get_X", Sc_GUI_GetX);
817 ccAddExternalObjectFunction("GUI::set_X", Sc_GUI_SetX);
818 ccAddExternalObjectFunction("GUI::get_Y", Sc_GUI_GetY);
819 ccAddExternalObjectFunction("GUI::set_Y", Sc_GUI_SetY);
820 ccAddExternalObjectFunction("GUI::get_ZOrder", Sc_GUI_GetZOrder);
821 ccAddExternalObjectFunction("GUI::set_ZOrder", Sc_GUI_SetZOrder);
822
823 /* ----------------------- Registering unsafe exports for plugins -----------------------*/
824
825 ccAddExternalFunctionForPlugin("GUI::Centre^0", (void*)GUI_Centre);
826 ccAddExternalFunctionForPlugin("GUI::GetAtScreenXY^2", (void*)GetGUIAtLocation);
827 ccAddExternalFunctionForPlugin("GUI::SetPosition^2", (void*)GUI_SetPosition);
828 ccAddExternalFunctionForPlugin("GUI::SetSize^2", (void*)GUI_SetSize);
829 ccAddExternalFunctionForPlugin("GUI::get_BackgroundGraphic", (void*)GUI_GetBackgroundGraphic);
830 ccAddExternalFunctionForPlugin("GUI::set_BackgroundGraphic", (void*)GUI_SetBackgroundGraphic);
831 ccAddExternalFunctionForPlugin("GUI::get_Clickable", (void*)GUI_GetClickable);
832 ccAddExternalFunctionForPlugin("GUI::set_Clickable", (void*)GUI_SetClickable);
833 ccAddExternalFunctionForPlugin("GUI::get_ControlCount", (void*)GUI_GetControlCount);
834 ccAddExternalFunctionForPlugin("GUI::geti_Controls", (void*)GUI_GetiControls);
835 ccAddExternalFunctionForPlugin("GUI::get_Height", (void*)GUI_GetHeight);
836 ccAddExternalFunctionForPlugin("GUI::set_Height", (void*)GUI_SetHeight);
837 ccAddExternalFunctionForPlugin("GUI::get_ID", (void*)GUI_GetID);
838 ccAddExternalFunctionForPlugin("GUI::get_Transparency", (void*)GUI_GetTransparency);
839 ccAddExternalFunctionForPlugin("GUI::set_Transparency", (void*)GUI_SetTransparency);
840 ccAddExternalFunctionForPlugin("GUI::get_Visible", (void*)GUI_GetVisible);
841 ccAddExternalFunctionForPlugin("GUI::set_Visible", (void*)GUI_SetVisible);
842 ccAddExternalFunctionForPlugin("GUI::get_Width", (void*)GUI_GetWidth);
843 ccAddExternalFunctionForPlugin("GUI::set_Width", (void*)GUI_SetWidth);
844 ccAddExternalFunctionForPlugin("GUI::get_X", (void*)GUI_GetX);
845 ccAddExternalFunctionForPlugin("GUI::set_X", (void*)GUI_SetX);
846 ccAddExternalFunctionForPlugin("GUI::get_Y", (void*)GUI_GetY);
847 ccAddExternalFunctionForPlugin("GUI::set_Y", (void*)GUI_SetY);
848 ccAddExternalFunctionForPlugin("GUI::get_ZOrder", (void*)GUI_GetZOrder);
849 ccAddExternalFunctionForPlugin("GUI::set_ZOrder", (void*)GUI_SetZOrder);
850 }
851