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/overlay.h"
17 #include "ac/common.h"
18 #include "ac/view.h"
19 #include "ac/characterextras.h"
20 #include "ac/draw.h"
21 #include "ac/gamesetupstruct.h"
22 #include "ac/gamestate.h"
23 #include "ac/global_overlay.h"
24 #include "ac/global_translation.h"
25 #include "ac/runtime_defines.h"
26 #include "ac/screenoverlay.h"
27 #include "ac/string.h"
28 #include "gfx/graphicsdriver.h"
29 #include "gfx/bitmap.h"
30 #include "script/runtimescriptvalue.h"
31
32 using namespace AGS::Common;
33 using namespace AGS::Engine;
34
35 extern GameSetupStruct game;
36 extern int offsetx, offsety;
37 extern int displayed_room;
38 extern int spritewidth[MAX_SPRITES],spriteheight[MAX_SPRITES];
39 extern int face_talking;
40 extern ViewStruct*views;
41 extern CharacterExtras *charextra;
42 extern IGraphicsDriver *gfxDriver;
43
44
45
46 ScreenOverlay screenover[MAX_SCREEN_OVERLAYS];
47 int numscreenover=0;
48 int is_complete_overlay=0,is_text_overlay=0;
49 int crovr_id=2; // whether using SetTextOverlay or CreateTextOvelay
50
Overlay_Remove(ScriptOverlay * sco)51 void Overlay_Remove(ScriptOverlay *sco) {
52 sco->Remove();
53 }
54
Overlay_SetText(ScriptOverlay * scover,int wii,int fontid,int clr,const char * text)55 void Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int clr, const char*text) {
56 int ovri=find_overlay_of_type(scover->overlayId);
57 if (ovri<0)
58 quit("!Overlay.SetText: invalid overlay ID specified");
59 int xx = divide_down_coordinate(screenover[ovri].x) - scover->borderWidth;
60 int yy = divide_down_coordinate(screenover[ovri].y) - scover->borderHeight;
61
62 RemoveOverlay(scover->overlayId);
63 crovr_id = scover->overlayId;
64
65 if (CreateTextOverlay(xx,yy,wii,fontid,clr,get_translation(text)) != scover->overlayId)
66 quit("SetTextOverlay internal error: inconsistent type ids");
67 }
68
Overlay_GetX(ScriptOverlay * scover)69 int Overlay_GetX(ScriptOverlay *scover) {
70 int ovri = find_overlay_of_type(scover->overlayId);
71 if (ovri < 0)
72 quit("!invalid overlay ID specified");
73
74 int tdxp, tdyp;
75 get_overlay_position(ovri, &tdxp, &tdyp);
76
77 return divide_down_coordinate(tdxp);
78 }
79
Overlay_SetX(ScriptOverlay * scover,int newx)80 void Overlay_SetX(ScriptOverlay *scover, int newx) {
81 int ovri = find_overlay_of_type(scover->overlayId);
82 if (ovri < 0)
83 quit("!invalid overlay ID specified");
84
85 screenover[ovri].x = multiply_up_coordinate(newx);
86 }
87
Overlay_GetY(ScriptOverlay * scover)88 int Overlay_GetY(ScriptOverlay *scover) {
89 int ovri = find_overlay_of_type(scover->overlayId);
90 if (ovri < 0)
91 quit("!invalid overlay ID specified");
92
93 int tdxp, tdyp;
94 get_overlay_position(ovri, &tdxp, &tdyp);
95
96 return divide_down_coordinate(tdyp);
97 }
98
Overlay_SetY(ScriptOverlay * scover,int newy)99 void Overlay_SetY(ScriptOverlay *scover, int newy) {
100 int ovri = find_overlay_of_type(scover->overlayId);
101 if (ovri < 0)
102 quit("!invalid overlay ID specified");
103
104 screenover[ovri].y = multiply_up_coordinate(newy);
105 }
106
Overlay_GetValid(ScriptOverlay * scover)107 int Overlay_GetValid(ScriptOverlay *scover) {
108 if (scover->overlayId == -1)
109 return 0;
110
111 if (!IsOverlayValid(scover->overlayId)) {
112 scover->overlayId = -1;
113 return 0;
114 }
115
116 return 1;
117 }
118
Overlay_CreateGraphical(int x,int y,int slot,int transparent)119 ScriptOverlay* Overlay_CreateGraphical(int x, int y, int slot, int transparent) {
120 ScriptOverlay *sco = new ScriptOverlay();
121 sco->overlayId = CreateGraphicOverlay(x, y, slot, transparent);
122 sco->borderHeight = 0;
123 sco->borderWidth = 0;
124 sco->isBackgroundSpeech = 0;
125
126 ccRegisterManagedObject(sco, sco);
127 return sco;
128 }
129
Overlay_CreateTextual(int x,int y,int width,int font,int colour,const char * text)130 ScriptOverlay* Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char* text) {
131 ScriptOverlay *sco = new ScriptOverlay();
132
133 multiply_up_coordinates(&x, &y);
134 width = multiply_up_coordinate(width);
135
136 sco->overlayId = CreateTextOverlayCore(x, y, width, font, colour, text, 0);
137
138 int ovri = find_overlay_of_type(sco->overlayId);
139 sco->borderWidth = divide_down_coordinate(screenover[ovri].x - x);
140 sco->borderHeight = divide_down_coordinate(screenover[ovri].y - y);
141 sco->isBackgroundSpeech = 0;
142
143 ccRegisterManagedObject(sco, sco);
144 return sco;
145 }
146
147 //=============================================================================
148
remove_screen_overlay_index(int cc)149 void remove_screen_overlay_index(int cc) {
150 int dd;
151 delete screenover[cc].pic;
152 screenover[cc].pic=NULL;
153
154 if (screenover[cc].bmp != NULL)
155 gfxDriver->DestroyDDB(screenover[cc].bmp);
156 screenover[cc].bmp = NULL;
157
158 if (screenover[cc].type==OVER_COMPLETE) is_complete_overlay--;
159 if (screenover[cc].type==OVER_TEXTMSG) is_text_overlay--;
160
161 // if the script didn't actually use the Overlay* return
162 // value, dispose of the pointer
163 if (screenover[cc].associatedOverlayHandle)
164 ccAttemptDisposeObject(screenover[cc].associatedOverlayHandle);
165
166 numscreenover--;
167 for (dd = cc; dd < numscreenover; dd++)
168 screenover[dd] = screenover[dd+1];
169
170 // if an overlay before the sierra-style speech one is removed,
171 // update the index
172 if (face_talking > cc)
173 face_talking--;
174 }
175
remove_screen_overlay(int type)176 void remove_screen_overlay(int type) {
177 int cc;
178 for (cc=0;cc<numscreenover;cc++) {
179 if (screenover[cc].type==type) ;
180 else if (type==-1) ;
181 else continue;
182 remove_screen_overlay_index(cc);
183 cc--;
184 }
185 }
186
find_overlay_of_type(int typ)187 int find_overlay_of_type(int typ) {
188 int ww;
189 for (ww=0;ww<numscreenover;ww++) {
190 if (screenover[ww].type == typ) return ww;
191 }
192 return -1;
193 }
194
add_screen_overlay(int x,int y,int type,Bitmap * piccy,bool alphaChannel)195 int add_screen_overlay(int x,int y,int type,Bitmap *piccy, bool alphaChannel) {
196 if (numscreenover>=MAX_SCREEN_OVERLAYS)
197 quit("too many screen overlays created");
198 if (type==OVER_COMPLETE) is_complete_overlay++;
199 if (type==OVER_TEXTMSG) is_text_overlay++;
200 if (type==OVER_CUSTOM) {
201 int uu; // find an unused custom ID
202 for (uu=OVER_CUSTOM+1;uu<OVER_CUSTOM+100;uu++) {
203 if (find_overlay_of_type(uu) == -1) { type=uu; break; }
204 }
205 }
206 screenover[numscreenover].pic=piccy;
207 screenover[numscreenover].bmp = gfxDriver->CreateDDBFromBitmap(piccy, alphaChannel);
208 screenover[numscreenover].x=x;
209 screenover[numscreenover].y=y;
210 screenover[numscreenover].type=type;
211 screenover[numscreenover].timeout=0;
212 screenover[numscreenover].bgSpeechForChar = -1;
213 screenover[numscreenover].associatedOverlayHandle = 0;
214 screenover[numscreenover].hasAlphaChannel = alphaChannel;
215 screenover[numscreenover].positionRelativeToScreen = true;
216 numscreenover++;
217 return numscreenover-1;
218 }
219
220
221
get_overlay_position(int overlayidx,int * x,int * y)222 void get_overlay_position(int overlayidx, int *x, int *y) {
223 int tdxp, tdyp;
224
225 if (screenover[overlayidx].x == OVR_AUTOPLACE) {
226 // auto place on character
227 int charid = screenover[overlayidx].y;
228 int charpic = views[game.chars[charid].view].loops[game.chars[charid].loop].frames[0].pic;
229
230 tdyp = multiply_up_coordinate(game.chars[charid].get_effective_y()) - offsety - 5;
231 if (charextra[charid].height<1)
232 tdyp -= spriteheight[charpic];
233 else
234 tdyp -= charextra[charid].height;
235
236 tdyp -= screenover[overlayidx].pic->GetHeight();
237 if (tdyp < 5) tdyp=5;
238 tdxp = (multiply_up_coordinate(game.chars[charid].x) - screenover[overlayidx].pic->GetWidth()/2) - offsetx;
239 if (tdxp < 0) tdxp=0;
240
241 if ((tdxp + screenover[overlayidx].pic->GetWidth()) >= play.viewport.GetWidth())
242 tdxp = (play.viewport.GetWidth() - screenover[overlayidx].pic->GetWidth()) - 1;
243 if (game.chars[charid].room != displayed_room) {
244 tdxp = play.viewport.GetWidth()/2 - screenover[overlayidx].pic->GetWidth()/2;
245 tdyp = play.viewport.GetHeight()/2 - screenover[overlayidx].pic->GetHeight()/2;
246 }
247 }
248 else {
249 tdxp = screenover[overlayidx].x;
250 tdyp = screenover[overlayidx].y;
251
252 if (!screenover[overlayidx].positionRelativeToScreen)
253 {
254 tdxp -= offsetx;
255 tdyp -= offsety;
256 }
257 }
258 *x = tdxp;
259 *y = tdyp;
260 }
261
recreate_overlay_ddbs()262 void recreate_overlay_ddbs()
263 {
264 for (int i = 0; i < numscreenover; ++i)
265 {
266 if (screenover[i].bmp)
267 gfxDriver->DestroyDDB(screenover[i].bmp);
268 if (screenover[i].pic)
269 screenover[i].bmp = gfxDriver->CreateDDBFromBitmap(screenover[i].pic, false);
270 else
271 screenover[i].bmp = NULL;
272 }
273 }
274
275 //=============================================================================
276 //
277 // Script API Functions
278 //
279 //=============================================================================
280
281 #include "debug/out.h"
282 #include "script/script_api.h"
283 #include "script/script_runtime.h"
284
285 // ScriptOverlay* (int x, int y, int slot, int transparent)
Sc_Overlay_CreateGraphical(const RuntimeScriptValue * params,int32_t param_count)286 RuntimeScriptValue Sc_Overlay_CreateGraphical(const RuntimeScriptValue *params, int32_t param_count)
287 {
288 API_SCALL_OBJAUTO_PINT4(ScriptOverlay, Overlay_CreateGraphical);
289 }
290
291 // ScriptOverlay* (int x, int y, int width, int font, int colour, const char* text, ...)
Sc_Overlay_CreateTextual(const RuntimeScriptValue * params,int32_t param_count)292 RuntimeScriptValue Sc_Overlay_CreateTextual(const RuntimeScriptValue *params, int32_t param_count)
293 {
294 API_SCALL_SCRIPT_SPRINTF(Overlay_CreateTextual, 6);
295 ScriptOverlay *overlay = Overlay_CreateTextual(params[0].IValue, params[1].IValue, params[2].IValue,
296 params[3].IValue, params[4].IValue, scsf_buffer);
297 return RuntimeScriptValue().SetDynamicObject(overlay, overlay);
298 }
299
300 // void (ScriptOverlay *scover, int wii, int fontid, int clr, char*texx, ...)
Sc_Overlay_SetText(void * self,const RuntimeScriptValue * params,int32_t param_count)301 RuntimeScriptValue Sc_Overlay_SetText(void *self, const RuntimeScriptValue *params, int32_t param_count)
302 {
303 API_OBJCALL_SCRIPT_SPRINTF(Overlay_SetText, 4);
304 Overlay_SetText((ScriptOverlay*)self, params[0].IValue, params[1].IValue, params[2].IValue, scsf_buffer);
305 return RuntimeScriptValue((int32_t)0);
306 }
307
308 // void (ScriptOverlay *sco)
Sc_Overlay_Remove(void * self,const RuntimeScriptValue * params,int32_t param_count)309 RuntimeScriptValue Sc_Overlay_Remove(void *self, const RuntimeScriptValue *params, int32_t param_count)
310 {
311 API_OBJCALL_VOID(ScriptOverlay, Overlay_Remove);
312 }
313
314 // int (ScriptOverlay *scover)
Sc_Overlay_GetValid(void * self,const RuntimeScriptValue * params,int32_t param_count)315 RuntimeScriptValue Sc_Overlay_GetValid(void *self, const RuntimeScriptValue *params, int32_t param_count)
316 {
317 API_OBJCALL_INT(ScriptOverlay, Overlay_GetValid);
318 }
319
320 // int (ScriptOverlay *scover)
Sc_Overlay_GetX(void * self,const RuntimeScriptValue * params,int32_t param_count)321 RuntimeScriptValue Sc_Overlay_GetX(void *self, const RuntimeScriptValue *params, int32_t param_count)
322 {
323 API_OBJCALL_INT(ScriptOverlay, Overlay_GetX);
324 }
325
326 // void (ScriptOverlay *scover, int newx)
Sc_Overlay_SetX(void * self,const RuntimeScriptValue * params,int32_t param_count)327 RuntimeScriptValue Sc_Overlay_SetX(void *self, const RuntimeScriptValue *params, int32_t param_count)
328 {
329 API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetX);
330 }
331
332 // int (ScriptOverlay *scover)
Sc_Overlay_GetY(void * self,const RuntimeScriptValue * params,int32_t param_count)333 RuntimeScriptValue Sc_Overlay_GetY(void *self, const RuntimeScriptValue *params, int32_t param_count)
334 {
335 API_OBJCALL_INT(ScriptOverlay, Overlay_GetY);
336 }
337
338 // void (ScriptOverlay *scover, int newy)
Sc_Overlay_SetY(void * self,const RuntimeScriptValue * params,int32_t param_count)339 RuntimeScriptValue Sc_Overlay_SetY(void *self, const RuntimeScriptValue *params, int32_t param_count)
340 {
341 API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetY);
342 }
343
344 //=============================================================================
345 //
346 // Exclusive API for Plugins
347 //
348 //=============================================================================
349
350 // ScriptOverlay* (int x, int y, int width, int font, int colour, const char* text, ...)
ScPl_Overlay_CreateTextual(int x,int y,int width,int font,int colour,const char * text,...)351 ScriptOverlay* ScPl_Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char *text, ...)
352 {
353 API_PLUGIN_SCRIPT_SPRINTF(text);
354 return Overlay_CreateTextual(x, y, width, font, colour, scsf_buffer);
355 }
356
357 // void (ScriptOverlay *scover, int wii, int fontid, int clr, char*texx, ...)
ScPl_Overlay_SetText(ScriptOverlay * scover,int wii,int fontid,int clr,char * texx,...)358 void ScPl_Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int clr, char *texx, ...)
359 {
360 API_PLUGIN_SCRIPT_SPRINTF(texx);
361 Overlay_SetText(scover, wii, fontid, clr, scsf_buffer);
362 }
363
364
RegisterOverlayAPI()365 void RegisterOverlayAPI()
366 {
367 ccAddExternalStaticFunction("Overlay::CreateGraphical^4", Sc_Overlay_CreateGraphical);
368 ccAddExternalStaticFunction("Overlay::CreateTextual^106", Sc_Overlay_CreateTextual);
369 ccAddExternalObjectFunction("Overlay::SetText^104", Sc_Overlay_SetText);
370 ccAddExternalObjectFunction("Overlay::Remove^0", Sc_Overlay_Remove);
371 ccAddExternalObjectFunction("Overlay::get_Valid", Sc_Overlay_GetValid);
372 ccAddExternalObjectFunction("Overlay::get_X", Sc_Overlay_GetX);
373 ccAddExternalObjectFunction("Overlay::set_X", Sc_Overlay_SetX);
374 ccAddExternalObjectFunction("Overlay::get_Y", Sc_Overlay_GetY);
375 ccAddExternalObjectFunction("Overlay::set_Y", Sc_Overlay_SetY);
376
377 /* ----------------------- Registering unsafe exports for plugins -----------------------*/
378
379 ccAddExternalFunctionForPlugin("Overlay::CreateGraphical^4", (void*)Overlay_CreateGraphical);
380 ccAddExternalFunctionForPlugin("Overlay::CreateTextual^106", (void*)ScPl_Overlay_CreateTextual);
381 ccAddExternalFunctionForPlugin("Overlay::SetText^104", (void*)ScPl_Overlay_SetText);
382 ccAddExternalFunctionForPlugin("Overlay::Remove^0", (void*)Overlay_Remove);
383 ccAddExternalFunctionForPlugin("Overlay::get_Valid", (void*)Overlay_GetValid);
384 ccAddExternalFunctionForPlugin("Overlay::get_X", (void*)Overlay_GetX);
385 ccAddExternalFunctionForPlugin("Overlay::set_X", (void*)Overlay_SetX);
386 ccAddExternalFunctionForPlugin("Overlay::get_Y", (void*)Overlay_GetY);
387 ccAddExternalFunctionForPlugin("Overlay::set_Y", (void*)Overlay_SetY);
388 }
389