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 "ac/button.h"
16 #include "ac/common.h"
17 #include "ac/gui.h"
18 #include "ac/view.h"
19 #include "ac/gamesetupstruct.h"
20 #include "ac/global_translation.h"
21 #include "ac/string.h"
22 #include "ac/viewframe.h"
23 #include "debug/debug_log.h"
24 #include "gui/animatingguibutton.h"
25 #include "gui/guimain.h"
26
27 extern GameSetupStruct game;
28 extern ViewStruct*views;
29 extern int spritewidth[MAX_SPRITES],spriteheight[MAX_SPRITES];
30
31 // *** BUTTON FUNCTIONS
32
33 AnimatingGUIButton animbuts[MAX_ANIMATING_BUTTONS];
34 int numAnimButs;
35
Button_Animate(GUIButton * butt,int view,int loop,int speed,int repeat)36 void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat) {
37 int guin = butt->guin;
38 int objn = butt->objn;
39
40 if ((view < 1) || (view > game.numviews))
41 quit("!AnimateButton: invalid view specified");
42 view--;
43
44 if ((loop < 0) || (loop >= views[view].numLoops))
45 quit("!AnimateButton: invalid loop specified for view");
46
47 // if it's already animating, stop it
48 FindAndRemoveButtonAnimation(guin, objn);
49
50 if (numAnimButs >= MAX_ANIMATING_BUTTONS)
51 quit("!AnimateButton: too many animating GUI buttons at once");
52
53 int buttonId = guis[guin].CtrlRefs[objn] & 0x000ffff;
54
55 guibuts[buttonId].pushedpic = 0;
56 guibuts[buttonId].overpic = 0;
57
58 animbuts[numAnimButs].ongui = guin;
59 animbuts[numAnimButs].onguibut = objn;
60 animbuts[numAnimButs].buttonid = buttonId;
61 animbuts[numAnimButs].view = view;
62 animbuts[numAnimButs].loop = loop;
63 animbuts[numAnimButs].speed = speed;
64 animbuts[numAnimButs].repeat = repeat;
65 animbuts[numAnimButs].frame = -1;
66 animbuts[numAnimButs].wait = 0;
67 numAnimButs++;
68 // launch into the first frame
69 if (UpdateAnimatingButton(numAnimButs - 1))
70 quit("!AnimateButton: no frames to animate");
71 }
72
Button_GetText_New(GUIButton * butt)73 const char* Button_GetText_New(GUIButton *butt) {
74 return CreateNewScriptString(butt->text);
75 }
76
Button_GetText(GUIButton * butt,char * buffer)77 void Button_GetText(GUIButton *butt, char *buffer) {
78 strcpy(buffer, butt->text);
79 }
80
Button_SetText(GUIButton * butt,const char * newtx)81 void Button_SetText(GUIButton *butt, const char *newtx) {
82 newtx = get_translation(newtx);
83 if (strlen(newtx) > 49) quit("!SetButtonText: text too long, button has 50 chars max");
84
85 if (strcmp(butt->text, newtx)) {
86 guis_need_update = 1;
87 strcpy(butt->text,newtx);
88 }
89 }
90
Button_SetFont(GUIButton * butt,int newFont)91 void Button_SetFont(GUIButton *butt, int newFont) {
92 if ((newFont < 0) || (newFont >= game.numfonts))
93 quit("!Button.Font: invalid font number.");
94
95 if (butt->font != newFont) {
96 butt->font = newFont;
97 guis_need_update = 1;
98 }
99 }
100
Button_GetFont(GUIButton * butt)101 int Button_GetFont(GUIButton *butt) {
102 return butt->font;
103 }
104
Button_GetClipImage(GUIButton * butt)105 int Button_GetClipImage(GUIButton *butt) {
106 if (butt->flags & GUIF_CLIP)
107 return 1;
108 return 0;
109 }
110
Button_SetClipImage(GUIButton * butt,int newval)111 void Button_SetClipImage(GUIButton *butt, int newval) {
112 butt->flags &= ~GUIF_CLIP;
113 if (newval)
114 butt->flags |= GUIF_CLIP;
115
116 guis_need_update = 1;
117 }
118
Button_GetGraphic(GUIButton * butt)119 int Button_GetGraphic(GUIButton *butt) {
120 // return currently displayed pic
121 if (butt->usepic < 0)
122 return butt->pic;
123 return butt->usepic;
124 }
125
Button_GetMouseOverGraphic(GUIButton * butt)126 int Button_GetMouseOverGraphic(GUIButton *butt) {
127 return butt->overpic;
128 }
129
Button_SetMouseOverGraphic(GUIButton * guil,int slotn)130 void Button_SetMouseOverGraphic(GUIButton *guil, int slotn) {
131 debug_script_log("GUI %d Button %d mouseover set to slot %d", guil->guin, guil->objn, slotn);
132
133 if ((guil->isover != 0) && (guil->ispushed == 0))
134 guil->usepic = slotn;
135 guil->overpic = slotn;
136
137 guis_need_update = 1;
138 FindAndRemoveButtonAnimation(guil->guin, guil->objn);
139 }
140
Button_GetNormalGraphic(GUIButton * butt)141 int Button_GetNormalGraphic(GUIButton *butt) {
142 return butt->pic;
143 }
144
Button_SetNormalGraphic(GUIButton * guil,int slotn)145 void Button_SetNormalGraphic(GUIButton *guil, int slotn) {
146 debug_script_log("GUI %d Button %d normal set to slot %d", guil->guin, guil->objn, slotn);
147 // normal pic - update if mouse is not over, or if there's no overpic
148 if (((guil->isover == 0) || (guil->overpic < 1)) && (guil->ispushed == 0))
149 guil->usepic = slotn;
150 guil->pic = slotn;
151 // update the clickable area to the same size as the graphic
152 guil->wid = spritewidth[slotn];
153 guil->hit = spriteheight[slotn];
154
155 guis_need_update = 1;
156 FindAndRemoveButtonAnimation(guil->guin, guil->objn);
157 }
158
Button_GetPushedGraphic(GUIButton * butt)159 int Button_GetPushedGraphic(GUIButton *butt) {
160 return butt->pushedpic;
161 }
162
Button_SetPushedGraphic(GUIButton * guil,int slotn)163 void Button_SetPushedGraphic(GUIButton *guil, int slotn) {
164 debug_script_log("GUI %d Button %d pushed set to slot %d", guil->guin, guil->objn, slotn);
165
166 if (guil->ispushed)
167 guil->usepic = slotn;
168 guil->pushedpic = slotn;
169
170 guis_need_update = 1;
171 FindAndRemoveButtonAnimation(guil->guin, guil->objn);
172 }
173
Button_GetTextColor(GUIButton * butt)174 int Button_GetTextColor(GUIButton *butt) {
175 return butt->textcol;
176 }
177
Button_SetTextColor(GUIButton * butt,int newcol)178 void Button_SetTextColor(GUIButton *butt, int newcol) {
179 if (butt->textcol != newcol) {
180 butt->textcol = newcol;
181 guis_need_update = 1;
182 }
183 }
184
185 extern AnimatingGUIButton animbuts[MAX_ANIMATING_BUTTONS];
186 extern int numAnimButs;
187
188 // ** start animating buttons code
189
190 // returns 1 if animation finished
UpdateAnimatingButton(int bu)191 int UpdateAnimatingButton(int bu) {
192 if (animbuts[bu].wait > 0) {
193 animbuts[bu].wait--;
194 return 0;
195 }
196 ViewStruct *tview = &views[animbuts[bu].view];
197
198 animbuts[bu].frame++;
199
200 if (animbuts[bu].frame >= tview->loops[animbuts[bu].loop].numFrames)
201 {
202 if (tview->loops[animbuts[bu].loop].RunNextLoop()) {
203 // go to next loop
204 animbuts[bu].loop++;
205 animbuts[bu].frame = 0;
206 }
207 else if (animbuts[bu].repeat) {
208 animbuts[bu].frame = 0;
209 // multi-loop anim, go back
210 while ((animbuts[bu].loop > 0) &&
211 (tview->loops[animbuts[bu].loop - 1].RunNextLoop()))
212 animbuts[bu].loop--;
213 }
214 else
215 return 1;
216 }
217
218 CheckViewFrame(animbuts[bu].view, animbuts[bu].loop, animbuts[bu].frame);
219
220 // update the button's image
221 guibuts[animbuts[bu].buttonid].pic = tview->loops[animbuts[bu].loop].frames[animbuts[bu].frame].pic;
222 guibuts[animbuts[bu].buttonid].usepic = guibuts[animbuts[bu].buttonid].pic;
223 guibuts[animbuts[bu].buttonid].pushedpic = 0;
224 guibuts[animbuts[bu].buttonid].overpic = 0;
225 guis_need_update = 1;
226
227 animbuts[bu].wait = animbuts[bu].speed + tview->loops[animbuts[bu].loop].frames[animbuts[bu].frame].speed;
228 return 0;
229 }
230
StopButtonAnimation(int idxn)231 void StopButtonAnimation(int idxn) {
232 numAnimButs--;
233 for (int aa = idxn; aa < numAnimButs; aa++) {
234 animbuts[aa] = animbuts[aa + 1];
235 }
236 }
237
238 // Returns the index of the AnimatingGUIButton object corresponding to the
239 // given button ID; returns -1 if no such animation exists
FindAnimatedButton(int guin,int objn)240 int FindAnimatedButton(int guin, int objn)
241 {
242 for (int i = 0; i < numAnimButs; ++i)
243 {
244 if (animbuts[i].ongui == guin && animbuts[i].onguibut == objn)
245 return i;
246 }
247 return -1;
248 }
249
FindAndRemoveButtonAnimation(int guin,int objn)250 void FindAndRemoveButtonAnimation(int guin, int objn)
251 {
252 int idx = FindAnimatedButton(guin, objn);
253 if (idx >= 0)
254 StopButtonAnimation(idx);
255 }
256 // ** end animating buttons code
257
Button_Click(GUIButton * butt,int mbut)258 void Button_Click(GUIButton *butt, int mbut)
259 {
260 process_interface_click(butt->guin, butt->objn, mbut);
261 }
262
Button_IsAnimating(GUIButton * butt)263 bool Button_IsAnimating(GUIButton *butt)
264 {
265 return FindAnimatedButton(butt->guin, butt->objn) >= 0;
266 }
267
268 // NOTE: in correspondance to similar functions for Character & Object,
269 // GetView returns (view index + 1), while GetLoop and GetFrame return
270 // zero-based index and 0 in case of no animation.
Button_GetAnimView(GUIButton * butt)271 int Button_GetAnimView(GUIButton *butt)
272 {
273 int idx = FindAnimatedButton(butt->guin, butt->objn);
274 return idx >= 0 ? animbuts[idx].view + 1 : 0;
275 }
276
Button_GetAnimLoop(GUIButton * butt)277 int Button_GetAnimLoop(GUIButton *butt)
278 {
279 int idx = FindAnimatedButton(butt->guin, butt->objn);
280 return idx >= 0 ? animbuts[idx].loop : 0;
281 }
282
Button_GetAnimFrame(GUIButton * butt)283 int Button_GetAnimFrame(GUIButton *butt)
284 {
285 int idx = FindAnimatedButton(butt->guin, butt->objn);
286 return idx >= 0 ? animbuts[idx].frame : 0;
287 }
288
289 //=============================================================================
290 //
291 // Script API Functions
292 //
293 //=============================================================================
294
295 #include "debug/out.h"
296 #include "script/script_api.h"
297 #include "script/script_runtime.h"
298 #include "ac/dynobj/scriptstring.h"
299
300 extern ScriptString myScriptStringImpl;
301
302 // void | GUIButton *butt, int view, int loop, int speed, int repeat
Sc_Button_Animate(void * self,const RuntimeScriptValue * params,int32_t param_count)303 RuntimeScriptValue Sc_Button_Animate(void *self, const RuntimeScriptValue *params, int32_t param_count)
304 {
305 API_OBJCALL_VOID_PINT4(GUIButton, Button_Animate);
306 }
307
308 // const char* | GUIButton *butt
Sc_Button_GetText_New(void * self,const RuntimeScriptValue * params,int32_t param_count)309 RuntimeScriptValue Sc_Button_GetText_New(void *self, const RuntimeScriptValue *params, int32_t param_count)
310 {
311 API_OBJCALL_OBJ(GUIButton, const char, myScriptStringImpl, Button_GetText_New);
312 }
313
314 // void | GUIButton *butt, char *buffer
Sc_Button_GetText(void * self,const RuntimeScriptValue * params,int32_t param_count)315 RuntimeScriptValue Sc_Button_GetText(void *self, const RuntimeScriptValue *params, int32_t param_count)
316 {
317 API_OBJCALL_VOID_POBJ(GUIButton, Button_GetText, char);
318 }
319
320 // void | GUIButton *butt, const char *newtx
Sc_Button_SetText(void * self,const RuntimeScriptValue * params,int32_t param_count)321 RuntimeScriptValue Sc_Button_SetText(void *self, const RuntimeScriptValue *params, int32_t param_count)
322 {
323 API_OBJCALL_VOID_POBJ(GUIButton, Button_SetText, const char);
324 }
325
326 // void | GUIButton *butt, int newFont
Sc_Button_SetFont(void * self,const RuntimeScriptValue * params,int32_t param_count)327 RuntimeScriptValue Sc_Button_SetFont(void *self, const RuntimeScriptValue *params, int32_t param_count)
328 {
329 API_OBJCALL_VOID_PINT(GUIButton, Button_SetFont);
330 }
331
332 // int | GUIButton *butt
Sc_Button_GetFont(void * self,const RuntimeScriptValue * params,int32_t param_count)333 RuntimeScriptValue Sc_Button_GetFont(void *self, const RuntimeScriptValue *params, int32_t param_count)
334 {
335 API_OBJCALL_INT(GUIButton, Button_GetFont);
336 }
337
338 // int | GUIButton *butt
Sc_Button_GetClipImage(void * self,const RuntimeScriptValue * params,int32_t param_count)339 RuntimeScriptValue Sc_Button_GetClipImage(void *self, const RuntimeScriptValue *params, int32_t param_count)
340 {
341 API_OBJCALL_INT(GUIButton, Button_GetClipImage);
342 }
343
344 // void | GUIButton *butt, int newval
Sc_Button_SetClipImage(void * self,const RuntimeScriptValue * params,int32_t param_count)345 RuntimeScriptValue Sc_Button_SetClipImage(void *self, const RuntimeScriptValue *params, int32_t param_count)
346 {
347 API_OBJCALL_VOID_PINT(GUIButton, Button_SetClipImage);
348 }
349
350 // int | GUIButton *butt
Sc_Button_GetGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)351 RuntimeScriptValue Sc_Button_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
352 {
353 API_OBJCALL_INT(GUIButton, Button_GetGraphic);
354 }
355
356 // int | GUIButton *butt
Sc_Button_GetMouseOverGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)357 RuntimeScriptValue Sc_Button_GetMouseOverGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
358 {
359 API_OBJCALL_INT(GUIButton, Button_GetMouseOverGraphic);
360 }
361
362 // void | GUIButton *guil, int slotn
Sc_Button_SetMouseOverGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)363 RuntimeScriptValue Sc_Button_SetMouseOverGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
364 {
365 API_OBJCALL_VOID_PINT(GUIButton, Button_SetMouseOverGraphic);
366 }
367
368 // int | GUIButton *butt
Sc_Button_GetNormalGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)369 RuntimeScriptValue Sc_Button_GetNormalGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
370 {
371 API_OBJCALL_INT(GUIButton, Button_GetNormalGraphic);
372 }
373
374 // void | GUIButton *guil, int slotn
Sc_Button_SetNormalGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)375 RuntimeScriptValue Sc_Button_SetNormalGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
376 {
377 API_OBJCALL_VOID_PINT(GUIButton, Button_SetNormalGraphic);
378 }
379
380 // int | GUIButton *butt
Sc_Button_GetPushedGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)381 RuntimeScriptValue Sc_Button_GetPushedGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
382 {
383 API_OBJCALL_INT(GUIButton, Button_GetPushedGraphic);
384 }
385
386 // void | GUIButton *guil, int slotn
Sc_Button_SetPushedGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)387 RuntimeScriptValue Sc_Button_SetPushedGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count)
388 {
389 API_OBJCALL_VOID_PINT(GUIButton, Button_SetPushedGraphic);
390 }
391
392 // int | GUIButton *butt
Sc_Button_GetTextColor(void * self,const RuntimeScriptValue * params,int32_t param_count)393 RuntimeScriptValue Sc_Button_GetTextColor(void *self, const RuntimeScriptValue *params, int32_t param_count)
394 {
395 API_OBJCALL_INT(GUIButton, Button_GetTextColor);
396 }
397
398 // void | GUIButton *butt, int newcol
Sc_Button_SetTextColor(void * self,const RuntimeScriptValue * params,int32_t param_count)399 RuntimeScriptValue Sc_Button_SetTextColor(void *self, const RuntimeScriptValue *params, int32_t param_count)
400 {
401 API_OBJCALL_VOID_PINT(GUIButton, Button_SetTextColor);
402 }
403
Sc_Button_Click(void * self,const RuntimeScriptValue * params,int32_t param_count)404 RuntimeScriptValue Sc_Button_Click(void *self, const RuntimeScriptValue *params, int32_t param_count)
405 {
406 API_OBJCALL_VOID_PINT(GUIButton, Button_Click);
407 }
408
Sc_Button_GetAnimating(void * self,const RuntimeScriptValue * params,int32_t param_count)409 RuntimeScriptValue Sc_Button_GetAnimating(void *self, const RuntimeScriptValue *params, int32_t param_count)
410 {
411 API_OBJCALL_BOOL(GUIButton, Button_IsAnimating);
412 }
413
Sc_Button_GetFrame(void * self,const RuntimeScriptValue * params,int32_t param_count)414 RuntimeScriptValue Sc_Button_GetFrame(void *self, const RuntimeScriptValue *params, int32_t param_count)
415 {
416 API_OBJCALL_INT(GUIButton, Button_GetAnimFrame);
417 }
418
Sc_Button_GetLoop(void * self,const RuntimeScriptValue * params,int32_t param_count)419 RuntimeScriptValue Sc_Button_GetLoop(void *self, const RuntimeScriptValue *params, int32_t param_count)
420 {
421 API_OBJCALL_INT(GUIButton, Button_GetAnimLoop);
422 }
423
Sc_Button_GetView(void * self,const RuntimeScriptValue * params,int32_t param_count)424 RuntimeScriptValue Sc_Button_GetView(void *self, const RuntimeScriptValue *params, int32_t param_count)
425 {
426 API_OBJCALL_INT(GUIButton, Button_GetAnimView);
427 }
428
RegisterButtonAPI()429 void RegisterButtonAPI()
430 {
431 ccAddExternalObjectFunction("Button::Animate^4", Sc_Button_Animate);
432 ccAddExternalObjectFunction("Button::Click^1", Sc_Button_Click);
433 ccAddExternalObjectFunction("Button::GetText^1", Sc_Button_GetText);
434 ccAddExternalObjectFunction("Button::SetText^1", Sc_Button_SetText);
435 ccAddExternalObjectFunction("Button::get_Animating", Sc_Button_GetAnimating);
436 ccAddExternalObjectFunction("Button::get_ClipImage", Sc_Button_GetClipImage);
437 ccAddExternalObjectFunction("Button::set_ClipImage", Sc_Button_SetClipImage);
438 ccAddExternalObjectFunction("Button::get_Font", Sc_Button_GetFont);
439 ccAddExternalObjectFunction("Button::set_Font", Sc_Button_SetFont);
440 ccAddExternalObjectFunction("Button::get_Frame", Sc_Button_GetFrame);
441 ccAddExternalObjectFunction("Button::get_Graphic", Sc_Button_GetGraphic);
442 ccAddExternalObjectFunction("Button::get_Loop", Sc_Button_GetLoop);
443 ccAddExternalObjectFunction("Button::get_MouseOverGraphic", Sc_Button_GetMouseOverGraphic);
444 ccAddExternalObjectFunction("Button::set_MouseOverGraphic", Sc_Button_SetMouseOverGraphic);
445 ccAddExternalObjectFunction("Button::get_NormalGraphic", Sc_Button_GetNormalGraphic);
446 ccAddExternalObjectFunction("Button::set_NormalGraphic", Sc_Button_SetNormalGraphic);
447 ccAddExternalObjectFunction("Button::get_PushedGraphic", Sc_Button_GetPushedGraphic);
448 ccAddExternalObjectFunction("Button::set_PushedGraphic", Sc_Button_SetPushedGraphic);
449 ccAddExternalObjectFunction("Button::get_Text", Sc_Button_GetText_New);
450 ccAddExternalObjectFunction("Button::set_Text", Sc_Button_SetText);
451 ccAddExternalObjectFunction("Button::get_TextColor", Sc_Button_GetTextColor);
452 ccAddExternalObjectFunction("Button::set_TextColor", Sc_Button_SetTextColor);
453 ccAddExternalObjectFunction("Button::get_View", Sc_Button_GetView);
454
455 /* ----------------------- Registering unsafe exports for plugins -----------------------*/
456
457 ccAddExternalFunctionForPlugin("Button::Animate^4", (void*)Button_Animate);
458 ccAddExternalFunctionForPlugin("Button::GetText^1", (void*)Button_GetText);
459 ccAddExternalFunctionForPlugin("Button::SetText^1", (void*)Button_SetText);
460 ccAddExternalFunctionForPlugin("Button::get_ClipImage", (void*)Button_GetClipImage);
461 ccAddExternalFunctionForPlugin("Button::set_ClipImage", (void*)Button_SetClipImage);
462 ccAddExternalFunctionForPlugin("Button::get_Font", (void*)Button_GetFont);
463 ccAddExternalFunctionForPlugin("Button::set_Font", (void*)Button_SetFont);
464 ccAddExternalFunctionForPlugin("Button::get_Graphic", (void*)Button_GetGraphic);
465 ccAddExternalFunctionForPlugin("Button::get_MouseOverGraphic", (void*)Button_GetMouseOverGraphic);
466 ccAddExternalFunctionForPlugin("Button::set_MouseOverGraphic", (void*)Button_SetMouseOverGraphic);
467 ccAddExternalFunctionForPlugin("Button::get_NormalGraphic", (void*)Button_GetNormalGraphic);
468 ccAddExternalFunctionForPlugin("Button::set_NormalGraphic", (void*)Button_SetNormalGraphic);
469 ccAddExternalFunctionForPlugin("Button::get_PushedGraphic", (void*)Button_GetPushedGraphic);
470 ccAddExternalFunctionForPlugin("Button::set_PushedGraphic", (void*)Button_SetPushedGraphic);
471 ccAddExternalFunctionForPlugin("Button::get_Text", (void*)Button_GetText_New);
472 ccAddExternalFunctionForPlugin("Button::set_Text", (void*)Button_SetText);
473 ccAddExternalFunctionForPlugin("Button::get_TextColor", (void*)Button_GetTextColor);
474 ccAddExternalFunctionForPlugin("Button::set_TextColor", (void*)Button_SetTextColor);
475 }
476