1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ags/lib/std/math.h"
24 #include "ags/engine/ac/dynamic_sprite.h"
25 #include "ags/shared/ac/common.h"
26 #include "ags/engine/ac/character_cache.h"
27 #include "ags/engine/ac/draw.h"
28 #include "ags/engine/ac/game.h"
29 #include "ags/shared/ac/game_setup_struct.h"
30 #include "ags/engine/ac/game_state.h"
31 #include "ags/engine/ac/global_dynamic_sprite.h"
32 #include "ags/engine/ac/global_game.h"
33 #include "ags/engine/ac/math.h"    // M_PI
34 #include "ags/engine/ac/object_cache.h"
35 #include "ags/engine/ac/path_helper.h"
36 #include "ags/engine/ac/room_object.h"
37 #include "ags/engine/ac/room_status.h"
38 #include "ags/engine/ac/system.h"
39 #include "ags/engine/debugging/debug_log.h"
40 #include "ags/shared/game/room_struct.h"
41 #include "ags/shared/gui/gui_button.h"
42 #include "ags/shared/ac/sprite_cache.h"
43 #include "ags/engine/gfx/graphics_driver.h"
44 #include "ags/engine/script/runtime_script_value.h"
45 #include "ags/shared/debugging/out.h"
46 #include "ags/engine/script/script_api.h"
47 #include "ags/engine/script/script_runtime.h"
48 #include "ags/globals.h"
49 
50 namespace AGS3 {
51 
52 using namespace Shared;
53 using namespace Engine;
54 
55 // ** SCRIPT DYNAMIC SPRITE
56 
DynamicSprite_Delete(ScriptDynamicSprite * sds)57 void DynamicSprite_Delete(ScriptDynamicSprite *sds) {
58 	if (sds->slot) {
59 		free_dynamic_sprite(sds->slot);
60 		sds->slot = 0;
61 	}
62 }
63 
DynamicSprite_GetDrawingSurface(ScriptDynamicSprite * dss)64 ScriptDrawingSurface *DynamicSprite_GetDrawingSurface(ScriptDynamicSprite *dss) {
65 	ScriptDrawingSurface *surface = new ScriptDrawingSurface();
66 	surface->dynamicSpriteNumber = dss->slot;
67 
68 	if ((_GP(game).SpriteInfos[dss->slot].Flags & SPF_ALPHACHANNEL) != 0)
69 		surface->hasAlphaChannel = true;
70 
71 	ccRegisterManagedObject(surface, surface);
72 	return surface;
73 }
74 
DynamicSprite_GetGraphic(ScriptDynamicSprite * sds)75 int DynamicSprite_GetGraphic(ScriptDynamicSprite *sds) {
76 	if (sds->slot == 0)
77 		quit("!DynamicSprite.Graphic: Cannot get graphic, sprite has been deleted");
78 	return sds->slot;
79 }
80 
DynamicSprite_GetWidth(ScriptDynamicSprite * sds)81 int DynamicSprite_GetWidth(ScriptDynamicSprite *sds) {
82 	return game_to_data_coord(_GP(game).SpriteInfos[sds->slot].Width);
83 }
84 
DynamicSprite_GetHeight(ScriptDynamicSprite * sds)85 int DynamicSprite_GetHeight(ScriptDynamicSprite *sds) {
86 	return game_to_data_coord(_GP(game).SpriteInfos[sds->slot].Height);
87 }
88 
DynamicSprite_GetColorDepth(ScriptDynamicSprite * sds)89 int DynamicSprite_GetColorDepth(ScriptDynamicSprite *sds) {
90 	int depth = _GP(spriteset)[sds->slot]->GetColorDepth();
91 	if (depth == 15)
92 		depth = 16;
93 	if (depth == 24)
94 		depth = 32;
95 	return depth;
96 }
97 
DynamicSprite_Resize(ScriptDynamicSprite * sds,int width,int height)98 void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height) {
99 	if ((width < 1) || (height < 1))
100 		quit("!DynamicSprite.Resize: width and height must be greater than zero");
101 	if (sds->slot == 0)
102 		quit("!DynamicSprite.Resize: sprite has been deleted");
103 
104 	data_to_game_coords(&width, &height);
105 
106 	if (width * height >= 25000000)
107 		quitprintf("!DynamicSprite.Resize: new size is too large: %d x %d", width, height);
108 
109 	// resize the sprite to the requested size
110 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(spriteset)[sds->slot]->GetColorDepth());
111 	newPic->StretchBlt(_GP(spriteset)[sds->slot],
112 	                   RectWH(0, 0, _GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height),
113 	                   RectWH(0, 0, width, height));
114 
115 	delete _GP(spriteset)[sds->slot];
116 
117 	// replace the bitmap in the sprite set
118 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
119 	game_sprite_updated(sds->slot);
120 }
121 
DynamicSprite_Flip(ScriptDynamicSprite * sds,int direction)122 void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
123 	if ((direction < 1) || (direction > 3))
124 		quit("!DynamicSprite.Flip: invalid direction");
125 	if (sds->slot == 0)
126 		quit("!DynamicSprite.Flip: sprite has been deleted");
127 
128 	// resize the sprite to the requested size
129 	Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height, _GP(spriteset)[sds->slot]->GetColorDepth());
130 
131 	if (direction == 1)
132 		newPic->FlipBlt(_GP(spriteset)[sds->slot], 0, 0, Shared::kBitmap_HFlip);
133 	else if (direction == 2)
134 		newPic->FlipBlt(_GP(spriteset)[sds->slot], 0, 0, Shared::kBitmap_VFlip);
135 	else if (direction == 3)
136 		newPic->FlipBlt(_GP(spriteset)[sds->slot], 0, 0, Shared::kBitmap_HVFlip);
137 
138 	delete _GP(spriteset)[sds->slot];
139 
140 	// replace the bitmap in the sprite set
141 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
142 	game_sprite_updated(sds->slot);
143 }
144 
DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite * sds,int sourceSprite)145 void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) {
146 	if (sds->slot == 0)
147 		quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted");
148 
149 	if ((_GP(game).SpriteInfos[sds->slot].Width != _GP(game).SpriteInfos[sourceSprite].Width) ||
150 	        (_GP(game).SpriteInfos[sds->slot].Height != _GP(game).SpriteInfos[sourceSprite].Height)) {
151 		quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size");
152 	}
153 
154 	Bitmap *target = _GP(spriteset)[sds->slot];
155 	Bitmap *source = _GP(spriteset)[sourceSprite];
156 
157 	if (target->GetColorDepth() != source->GetColorDepth()) {
158 		quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same colour depth");
159 	}
160 
161 	// set the target's alpha channel depending on the source
162 	bool dst_has_alpha = (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0;
163 	bool src_has_alpha = (_GP(game).SpriteInfos[sourceSprite].Flags & SPF_ALPHACHANNEL) != 0;
164 	_GP(game).SpriteInfos[sds->slot].Flags &= ~SPF_ALPHACHANNEL;
165 	if (src_has_alpha) {
166 		_GP(game).SpriteInfos[sds->slot].Flags |= SPF_ALPHACHANNEL;
167 	}
168 
169 	BitmapHelper::CopyTransparency(target, source, dst_has_alpha, src_has_alpha);
170 	game_sprite_updated(sds->slot);
171 }
172 
DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite * sds,int width,int height,int x,int y)173 void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int height, int x, int y) {
174 	if (sds->slot == 0)
175 		quit("!DynamicSprite.ChangeCanvasSize: sprite has been deleted");
176 	if ((width < 1) || (height < 1))
177 		quit("!DynamicSprite.ChangeCanvasSize: new size is too small");
178 
179 	data_to_game_coords(&x, &y);
180 	data_to_game_coords(&width, &height);
181 
182 	Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(width, height, _GP(spriteset)[sds->slot]->GetColorDepth());
183 	// blit it into the enlarged image
184 	newPic->Blit(_GP(spriteset)[sds->slot], 0, 0, x, y, _GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height);
185 
186 	delete _GP(spriteset)[sds->slot];
187 
188 	// replace the bitmap in the sprite set
189 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
190 	game_sprite_updated(sds->slot);
191 }
192 
DynamicSprite_Crop(ScriptDynamicSprite * sds,int x1,int y1,int width,int height)193 void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x1, int y1, int width, int height) {
194 	if ((width < 1) || (height < 1))
195 		quit("!DynamicSprite.Crop: co-ordinates do not make sense");
196 	if (sds->slot == 0)
197 		quit("!DynamicSprite.Crop: sprite has been deleted");
198 
199 	data_to_game_coords(&x1, &y1);
200 	data_to_game_coords(&width, &height);
201 
202 	if ((width > _GP(game).SpriteInfos[sds->slot].Width) || (height > _GP(game).SpriteInfos[sds->slot].Height))
203 		quit("!DynamicSprite.Crop: requested to crop an area larger than the source");
204 
205 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(spriteset)[sds->slot]->GetColorDepth());
206 	// blit it cropped
207 	newPic->Blit(_GP(spriteset)[sds->slot], x1, y1, 0, 0, newPic->GetWidth(), newPic->GetHeight());
208 
209 	delete _GP(spriteset)[sds->slot];
210 
211 	// replace the bitmap in the sprite set
212 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
213 	game_sprite_updated(sds->slot);
214 }
215 
DynamicSprite_Rotate(ScriptDynamicSprite * sds,int angle,int width,int height)216 void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height) {
217 	if ((angle < 1) || (angle > 359))
218 		quit("!DynamicSprite.Rotate: invalid angle (must be 1-359)");
219 	if (sds->slot == 0)
220 		quit("!DynamicSprite.Rotate: sprite has been deleted");
221 
222 	if ((width == SCR_NO_VALUE) || (height == SCR_NO_VALUE)) {
223 		// calculate the new image size automatically
224 		// 1 degree = 181 degrees in terms of x/y size, so % 180
225 		int useAngle = angle % 180;
226 		// and 0..90 is the same as 180..90
227 		if (useAngle > 90)
228 			useAngle = 180 - useAngle;
229 		// useAngle is now between 0 and 90 (otherwise the sin/cos stuff doesn't work)
230 		double angleInRadians = (double)useAngle * (M_PI / 180.0);
231 		double sinVal = sin(angleInRadians);
232 		double cosVal = cos(angleInRadians);
233 
234 		width = (cosVal * (double)_GP(game).SpriteInfos[sds->slot].Width + sinVal * (double)_GP(game).SpriteInfos[sds->slot].Height);
235 		height = (sinVal * (double)_GP(game).SpriteInfos[sds->slot].Width + cosVal * (double)_GP(game).SpriteInfos[sds->slot].Height);
236 	} else {
237 		data_to_game_coords(&width, &height);
238 	}
239 
240 	// convert to allegro angle
241 	angle = (angle * 256) / 360;
242 
243 	// resize the sprite to the requested size
244 	Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(width, height, _GP(spriteset)[sds->slot]->GetColorDepth());
245 
246 	// rotate the sprite about its centre
247 	// (+ width%2 fixes one pixel offset problem)
248 	newPic->RotateBlt(_GP(spriteset)[sds->slot], width / 2 + width % 2, height / 2,
249 	                  _GP(game).SpriteInfos[sds->slot].Width / 2, _GP(game).SpriteInfos[sds->slot].Height / 2, itofix(angle));
250 
251 	delete _GP(spriteset)[sds->slot];
252 
253 	// replace the bitmap in the sprite set
254 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
255 	game_sprite_updated(sds->slot);
256 }
257 
DynamicSprite_Tint(ScriptDynamicSprite * sds,int red,int green,int blue,int saturation,int luminance)258 void DynamicSprite_Tint(ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance) {
259 	Bitmap *source = _GP(spriteset)[sds->slot];
260 	Bitmap *newPic = BitmapHelper::CreateBitmap(source->GetWidth(), source->GetHeight(), source->GetColorDepth());
261 
262 	tint_image(newPic, source, red, green, blue, saturation, (luminance * 25) / 10);
263 
264 	delete source;
265 	// replace the bitmap in the sprite set
266 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
267 	game_sprite_updated(sds->slot);
268 }
269 
DynamicSprite_SaveToFile(ScriptDynamicSprite * sds,const char * namm)270 int DynamicSprite_SaveToFile(ScriptDynamicSprite *sds, const char *namm) {
271 	if (sds->slot == 0)
272 		quit("!DynamicSprite.SaveToFile: sprite has been deleted");
273 
274 	auto filename = String(namm);
275 	if (filename.FindChar('.') == (size_t)-1)
276 		filename.Append(".bmp");
277 
278 	ResolvedPath rp;
279 	if (!ResolveWritePathAndCreateDirs(filename, rp))
280 		return 0;
281 	return _GP(spriteset)[sds->slot]->SaveToFile(rp.FullPath, _G(palette)) ? 1 : 0;
282 }
283 
DynamicSprite_CreateFromSaveGame(int sgslot,int width,int height)284 ScriptDynamicSprite *DynamicSprite_CreateFromSaveGame(int sgslot, int width, int height) {
285 	int slotnum = LoadSaveSlotScreenshot(sgslot, width, height);
286 	if (slotnum) {
287 		ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(slotnum);
288 		return new_spr;
289 	}
290 	return nullptr;
291 }
292 
DynamicSprite_CreateFromFile(const char * filename)293 ScriptDynamicSprite *DynamicSprite_CreateFromFile(const char *filename) {
294 	int slotnum = LoadImageFile(filename);
295 	if (slotnum) {
296 		ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(slotnum);
297 		return new_spr;
298 	}
299 	return nullptr;
300 }
301 
DynamicSprite_CreateFromScreenShot(int width,int height)302 ScriptDynamicSprite *DynamicSprite_CreateFromScreenShot(int width, int height) {
303 
304 	// TODO: refactor and merge with create_savegame_screenshot()
305 
306 	int gotSlot = _GP(spriteset).GetFreeIndex();
307 	if (gotSlot <= 0)
308 		return nullptr;
309 
310 	const Rect &viewport = _GP(play).GetMainViewport();
311 	if (width <= 0)
312 		width = viewport.GetWidth();
313 	else
314 		width = data_to_game_coord(width);
315 
316 	if (height <= 0)
317 		height = viewport.GetHeight();
318 	else
319 		height = data_to_game_coord(height);
320 
321 	Bitmap *newPic = CopyScreenIntoBitmap(width, height);
322 
323 	update_polled_stuff_if_runtime();
324 
325 	// replace the bitmap in the sprite set
326 	add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic));
327 	ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
328 	return new_spr;
329 }
330 
DynamicSprite_CreateFromExistingSprite(int slot,int preserveAlphaChannel)331 ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite(int slot, int preserveAlphaChannel) {
332 
333 	int gotSlot = _GP(spriteset).GetFreeIndex();
334 	if (gotSlot <= 0)
335 		return nullptr;
336 
337 	if (!_GP(spriteset).DoesSpriteExist(slot))
338 		quitprintf("DynamicSprite.CreateFromExistingSprite: sprite %d does not exist", slot);
339 
340 	// create a new sprite as a copy of the existing one
341 	Bitmap *newPic = BitmapHelper::CreateBitmapCopy(_GP(spriteset)[slot]);
342 	if (newPic == nullptr)
343 		return nullptr;
344 
345 	bool hasAlpha = (preserveAlphaChannel) && ((_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
346 
347 	// replace the bitmap in the sprite set
348 	add_dynamic_sprite(gotSlot, newPic, hasAlpha);
349 	ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
350 	return new_spr;
351 }
352 
DynamicSprite_CreateFromDrawingSurface(ScriptDrawingSurface * sds,int x,int y,int width,int height)353 ScriptDynamicSprite *DynamicSprite_CreateFromDrawingSurface(ScriptDrawingSurface *sds, int x, int y, int width, int height) {
354 	int gotSlot = _GP(spriteset).GetFreeIndex();
355 	if (gotSlot <= 0)
356 		return nullptr;
357 
358 	// use DrawingSurface resolution
359 	sds->PointToGameResolution(&x, &y);
360 	sds->SizeToGameResolution(&width, &height);
361 
362 	Bitmap *ds = sds->StartDrawing();
363 
364 	if ((x < 0) || (y < 0) || (x + width > ds->GetWidth()) || (y + height > ds->GetHeight()))
365 		quit("!DynamicSprite.CreateFromDrawingSurface: requested area is outside the surface");
366 
367 	int colDepth = ds->GetColorDepth();
368 
369 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, colDepth);
370 	if (newPic == nullptr)
371 		return nullptr;
372 
373 	newPic->Blit(ds, x, y, 0, 0, width, height);
374 
375 	sds->FinishedDrawingReadOnly();
376 
377 	add_dynamic_sprite(gotSlot, newPic, (sds->hasAlphaChannel != 0));
378 	ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
379 	return new_spr;
380 }
381 
DynamicSprite_Create(int width,int height,int alphaChannel)382 ScriptDynamicSprite *DynamicSprite_Create(int width, int height, int alphaChannel) {
383 	data_to_game_coords(&width, &height);
384 
385 	int gotSlot = _GP(spriteset).GetFreeIndex();
386 	if (gotSlot <= 0)
387 		return nullptr;
388 
389 	Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(width, height, _GP(game).GetColorDepth());
390 	if (newPic == nullptr)
391 		return nullptr;
392 
393 	if ((alphaChannel) && (_GP(game).GetColorDepth() < 32))
394 		alphaChannel = false;
395 
396 	add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic), alphaChannel != 0);
397 	ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
398 	return new_spr;
399 }
400 
DynamicSprite_CreateFromExistingSprite_Old(int slot)401 ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite_Old(int slot) {
402 	return DynamicSprite_CreateFromExistingSprite(slot, 0);
403 }
404 
DynamicSprite_CreateFromBackground(int frame,int x1,int y1,int width,int height)405 ScriptDynamicSprite *DynamicSprite_CreateFromBackground(int frame, int x1, int y1, int width, int height) {
406 
407 	if (frame == SCR_NO_VALUE) {
408 		frame = _GP(play).bg_frame;
409 	} else if ((frame < 0) || ((size_t)frame >= _GP(thisroom).BgFrameCount))
410 		quit("!DynamicSprite.CreateFromBackground: invalid frame specified");
411 
412 	if (x1 == SCR_NO_VALUE) {
413 		x1 = 0;
414 		y1 = 0;
415 		width = _GP(play).room_width;
416 		height = _GP(play).room_height;
417 	} else if ((x1 < 0) || (y1 < 0) || (width < 1) || (height < 1) ||
418 	           (x1 + width > _GP(play).room_width) || (y1 + height > _GP(play).room_height))
419 		quit("!DynamicSprite.CreateFromBackground: invalid co-ordinates specified");
420 
421 	data_to_game_coords(&x1, &y1);
422 	data_to_game_coords(&width, &height);
423 
424 	int gotSlot = _GP(spriteset).GetFreeIndex();
425 	if (gotSlot <= 0)
426 		return nullptr;
427 
428 	// create a new sprite as a copy of the existing one
429 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(thisroom).BgFrames[frame].Graphic->GetColorDepth());
430 	if (newPic == nullptr)
431 		return nullptr;
432 
433 	newPic->Blit(_GP(thisroom).BgFrames[frame].Graphic.get(), x1, y1, 0, 0, width, height);
434 
435 	// replace the bitmap in the sprite set
436 	add_dynamic_sprite(gotSlot, newPic);
437 	ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
438 	return new_spr;
439 }
440 
441 //=============================================================================
442 
add_dynamic_sprite(int gotSlot,Bitmap * redin,bool hasAlpha)443 void add_dynamic_sprite(int gotSlot, Bitmap *redin, bool hasAlpha) {
444 
445 	_GP(spriteset).SetSprite(gotSlot, redin);
446 
447 	_GP(game).SpriteInfos[gotSlot].Flags = SPF_DYNAMICALLOC;
448 
449 	if (redin->GetColorDepth() > 8)
450 		_GP(game).SpriteInfos[gotSlot].Flags |= SPF_HICOLOR;
451 	if (redin->GetColorDepth() > 16)
452 		_GP(game).SpriteInfos[gotSlot].Flags |= SPF_TRUECOLOR;
453 	if (hasAlpha)
454 		_GP(game).SpriteInfos[gotSlot].Flags |= SPF_ALPHACHANNEL;
455 
456 	_GP(game).SpriteInfos[gotSlot].Width = redin->GetWidth();
457 	_GP(game).SpriteInfos[gotSlot].Height = redin->GetHeight();
458 }
459 
free_dynamic_sprite(int gotSlot)460 void free_dynamic_sprite(int gotSlot) {
461 
462 	if ((gotSlot < 0) || ((size_t)gotSlot >= _GP(spriteset).GetSpriteSlotCount()))
463 		quit("!FreeDynamicSprite: invalid slot number");
464 
465 	if ((_GP(game).SpriteInfos[gotSlot].Flags & SPF_DYNAMICALLOC) == 0)
466 		quitprintf("!DeleteSprite: Attempted to free static sprite %d that was not loaded by the script", gotSlot);
467 
468 	_GP(spriteset).RemoveSprite(gotSlot, true);
469 
470 	_GP(game).SpriteInfos[gotSlot].Flags = 0;
471 	_GP(game).SpriteInfos[gotSlot].Width = 0;
472 	_GP(game).SpriteInfos[gotSlot].Height = 0;
473 
474 	game_sprite_deleted(gotSlot);
475 }
476 
477 //=============================================================================
478 //
479 // Script API Functions
480 //
481 //=============================================================================
482 
483 // void (ScriptDynamicSprite *sds, int width, int height, int x, int y)
Sc_DynamicSprite_ChangeCanvasSize(void * self,const RuntimeScriptValue * params,int32_t param_count)484 RuntimeScriptValue Sc_DynamicSprite_ChangeCanvasSize(void *self, const RuntimeScriptValue *params, int32_t param_count) {
485 	API_OBJCALL_VOID_PINT4(ScriptDynamicSprite, DynamicSprite_ChangeCanvasSize);
486 }
487 
488 // void (ScriptDynamicSprite *sds, int sourceSprite)
Sc_DynamicSprite_CopyTransparencyMask(void * self,const RuntimeScriptValue * params,int32_t param_count)489 RuntimeScriptValue Sc_DynamicSprite_CopyTransparencyMask(void *self, const RuntimeScriptValue *params, int32_t param_count) {
490 	API_OBJCALL_VOID_PINT(ScriptDynamicSprite, DynamicSprite_CopyTransparencyMask);
491 }
492 
493 // void (ScriptDynamicSprite *sds, int x1, int y1, int width, int height)
Sc_DynamicSprite_Crop(void * self,const RuntimeScriptValue * params,int32_t param_count)494 RuntimeScriptValue Sc_DynamicSprite_Crop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
495 	API_OBJCALL_VOID_PINT4(ScriptDynamicSprite, DynamicSprite_Crop);
496 }
497 
498 // void (ScriptDynamicSprite *sds)
Sc_DynamicSprite_Delete(void * self,const RuntimeScriptValue * params,int32_t param_count)499 RuntimeScriptValue Sc_DynamicSprite_Delete(void *self, const RuntimeScriptValue *params, int32_t param_count) {
500 	API_OBJCALL_VOID(ScriptDynamicSprite, DynamicSprite_Delete);
501 }
502 
503 // void (ScriptDynamicSprite *sds, int direction)
Sc_DynamicSprite_Flip(void * self,const RuntimeScriptValue * params,int32_t param_count)504 RuntimeScriptValue Sc_DynamicSprite_Flip(void *self, const RuntimeScriptValue *params, int32_t param_count) {
505 	API_OBJCALL_VOID_PINT(ScriptDynamicSprite, DynamicSprite_Flip);
506 }
507 
508 // ScriptDrawingSurface* (ScriptDynamicSprite *dss)
Sc_DynamicSprite_GetDrawingSurface(void * self,const RuntimeScriptValue * params,int32_t param_count)509 RuntimeScriptValue Sc_DynamicSprite_GetDrawingSurface(void *self, const RuntimeScriptValue *params, int32_t param_count) {
510 	API_OBJCALL_OBJAUTO(ScriptDynamicSprite, ScriptDrawingSurface, DynamicSprite_GetDrawingSurface);
511 }
512 
513 // void (ScriptDynamicSprite *sds, int width, int height)
Sc_DynamicSprite_Resize(void * self,const RuntimeScriptValue * params,int32_t param_count)514 RuntimeScriptValue Sc_DynamicSprite_Resize(void *self, const RuntimeScriptValue *params, int32_t param_count) {
515 	API_OBJCALL_VOID_PINT2(ScriptDynamicSprite, DynamicSprite_Resize);
516 }
517 
518 // void (ScriptDynamicSprite *sds, int angle, int width, int height)
Sc_DynamicSprite_Rotate(void * self,const RuntimeScriptValue * params,int32_t param_count)519 RuntimeScriptValue Sc_DynamicSprite_Rotate(void *self, const RuntimeScriptValue *params, int32_t param_count) {
520 	API_OBJCALL_VOID_PINT3(ScriptDynamicSprite, DynamicSprite_Rotate);
521 }
522 
523 // int (ScriptDynamicSprite *sds, const char* namm)
Sc_DynamicSprite_SaveToFile(void * self,const RuntimeScriptValue * params,int32_t param_count)524 RuntimeScriptValue Sc_DynamicSprite_SaveToFile(void *self, const RuntimeScriptValue *params, int32_t param_count) {
525 	API_OBJCALL_INT_POBJ(ScriptDynamicSprite, DynamicSprite_SaveToFile, const char);
526 }
527 
528 // void (ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance)
Sc_DynamicSprite_Tint(void * self,const RuntimeScriptValue * params,int32_t param_count)529 RuntimeScriptValue Sc_DynamicSprite_Tint(void *self, const RuntimeScriptValue *params, int32_t param_count) {
530 	API_OBJCALL_VOID_PINT5(ScriptDynamicSprite, DynamicSprite_Tint);
531 }
532 
533 // int (ScriptDynamicSprite *sds)
Sc_DynamicSprite_GetColorDepth(void * self,const RuntimeScriptValue * params,int32_t param_count)534 RuntimeScriptValue Sc_DynamicSprite_GetColorDepth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
535 	API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetColorDepth);
536 }
537 
538 // int (ScriptDynamicSprite *sds)
Sc_DynamicSprite_GetGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)539 RuntimeScriptValue Sc_DynamicSprite_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
540 	API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetGraphic);
541 }
542 
543 // int (ScriptDynamicSprite *sds)
Sc_DynamicSprite_GetHeight(void * self,const RuntimeScriptValue * params,int32_t param_count)544 RuntimeScriptValue Sc_DynamicSprite_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
545 	API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetHeight);
546 }
547 
548 // int (ScriptDynamicSprite *sds)
Sc_DynamicSprite_GetWidth(void * self,const RuntimeScriptValue * params,int32_t param_count)549 RuntimeScriptValue Sc_DynamicSprite_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
550 	API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetWidth);
551 }
552 
553 // ScriptDynamicSprite* (int width, int height, int alphaChannel)
Sc_DynamicSprite_Create(const RuntimeScriptValue * params,int32_t param_count)554 RuntimeScriptValue Sc_DynamicSprite_Create(const RuntimeScriptValue *params, int32_t param_count) {
555 	API_SCALL_OBJAUTO_PINT3(ScriptDynamicSprite, DynamicSprite_Create);
556 }
557 
558 // ScriptDynamicSprite* (int frame, int x1, int y1, int width, int height)
Sc_DynamicSprite_CreateFromBackground(const RuntimeScriptValue * params,int32_t param_count)559 RuntimeScriptValue Sc_DynamicSprite_CreateFromBackground(const RuntimeScriptValue *params, int32_t param_count) {
560 	API_SCALL_OBJAUTO_PINT5(ScriptDynamicSprite, DynamicSprite_CreateFromBackground);
561 }
562 
563 // ScriptDynamicSprite* (ScriptDrawingSurface *sds, int x, int y, int width, int height)
Sc_DynamicSprite_CreateFromDrawingSurface(const RuntimeScriptValue * params,int32_t param_count)564 RuntimeScriptValue Sc_DynamicSprite_CreateFromDrawingSurface(const RuntimeScriptValue *params, int32_t param_count) {
565 	API_SCALL_OBJAUTO_POBJ_PINT4(ScriptDynamicSprite, DynamicSprite_CreateFromDrawingSurface, ScriptDrawingSurface);
566 }
567 
568 // ScriptDynamicSprite* (int slot)
Sc_DynamicSprite_CreateFromExistingSprite_Old(const RuntimeScriptValue * params,int32_t param_count)569 RuntimeScriptValue Sc_DynamicSprite_CreateFromExistingSprite_Old(const RuntimeScriptValue *params, int32_t param_count) {
570 	API_SCALL_OBJAUTO_PINT(ScriptDynamicSprite, DynamicSprite_CreateFromExistingSprite_Old);
571 }
572 
573 // ScriptDynamicSprite* (int slot, int preserveAlphaChannel)
Sc_DynamicSprite_CreateFromExistingSprite(const RuntimeScriptValue * params,int32_t param_count)574 RuntimeScriptValue Sc_DynamicSprite_CreateFromExistingSprite(const RuntimeScriptValue *params, int32_t param_count) {
575 	API_SCALL_OBJAUTO_PINT2(ScriptDynamicSprite, DynamicSprite_CreateFromExistingSprite);
576 }
577 
578 // ScriptDynamicSprite* (const char *filename)
Sc_DynamicSprite_CreateFromFile(const RuntimeScriptValue * params,int32_t param_count)579 RuntimeScriptValue Sc_DynamicSprite_CreateFromFile(const RuntimeScriptValue *params, int32_t param_count) {
580 	API_SCALL_OBJAUTO_POBJ(ScriptDynamicSprite, DynamicSprite_CreateFromFile, const char);
581 }
582 
583 // ScriptDynamicSprite* (int sgslot, int width, int height)
Sc_DynamicSprite_CreateFromSaveGame(const RuntimeScriptValue * params,int32_t param_count)584 RuntimeScriptValue Sc_DynamicSprite_CreateFromSaveGame(const RuntimeScriptValue *params, int32_t param_count) {
585 	API_SCALL_OBJAUTO_PINT3(ScriptDynamicSprite, DynamicSprite_CreateFromSaveGame);
586 }
587 
588 // ScriptDynamicSprite* (int width, int height)
Sc_DynamicSprite_CreateFromScreenShot(const RuntimeScriptValue * params,int32_t param_count)589 RuntimeScriptValue Sc_DynamicSprite_CreateFromScreenShot(const RuntimeScriptValue *params, int32_t param_count) {
590 	API_SCALL_OBJAUTO_PINT2(ScriptDynamicSprite, DynamicSprite_CreateFromScreenShot);
591 }
592 
593 
RegisterDynamicSpriteAPI()594 void RegisterDynamicSpriteAPI() {
595 	ccAddExternalObjectFunction("DynamicSprite::ChangeCanvasSize^4", Sc_DynamicSprite_ChangeCanvasSize);
596 	ccAddExternalObjectFunction("DynamicSprite::CopyTransparencyMask^1", Sc_DynamicSprite_CopyTransparencyMask);
597 	ccAddExternalObjectFunction("DynamicSprite::Crop^4", Sc_DynamicSprite_Crop);
598 	ccAddExternalObjectFunction("DynamicSprite::Delete", Sc_DynamicSprite_Delete);
599 	ccAddExternalObjectFunction("DynamicSprite::Flip^1", Sc_DynamicSprite_Flip);
600 	ccAddExternalObjectFunction("DynamicSprite::GetDrawingSurface^0", Sc_DynamicSprite_GetDrawingSurface);
601 	ccAddExternalObjectFunction("DynamicSprite::Resize^2", Sc_DynamicSprite_Resize);
602 	ccAddExternalObjectFunction("DynamicSprite::Rotate^3", Sc_DynamicSprite_Rotate);
603 	ccAddExternalObjectFunction("DynamicSprite::SaveToFile^1", Sc_DynamicSprite_SaveToFile);
604 	ccAddExternalObjectFunction("DynamicSprite::Tint^5", Sc_DynamicSprite_Tint);
605 	ccAddExternalObjectFunction("DynamicSprite::get_ColorDepth", Sc_DynamicSprite_GetColorDepth);
606 	ccAddExternalObjectFunction("DynamicSprite::get_Graphic", Sc_DynamicSprite_GetGraphic);
607 	ccAddExternalObjectFunction("DynamicSprite::get_Height", Sc_DynamicSprite_GetHeight);
608 	ccAddExternalObjectFunction("DynamicSprite::get_Width", Sc_DynamicSprite_GetWidth);
609 	ccAddExternalStaticFunction("DynamicSprite::Create^3", Sc_DynamicSprite_Create);
610 	ccAddExternalStaticFunction("DynamicSprite::CreateFromBackground", Sc_DynamicSprite_CreateFromBackground);
611 	ccAddExternalStaticFunction("DynamicSprite::CreateFromDrawingSurface^5", Sc_DynamicSprite_CreateFromDrawingSurface);
612 	ccAddExternalStaticFunction("DynamicSprite::CreateFromExistingSprite^1", Sc_DynamicSprite_CreateFromExistingSprite_Old);
613 	ccAddExternalStaticFunction("DynamicSprite::CreateFromExistingSprite^2", Sc_DynamicSprite_CreateFromExistingSprite);
614 	ccAddExternalStaticFunction("DynamicSprite::CreateFromFile", Sc_DynamicSprite_CreateFromFile);
615 	ccAddExternalStaticFunction("DynamicSprite::CreateFromSaveGame", Sc_DynamicSprite_CreateFromSaveGame);
616 	ccAddExternalStaticFunction("DynamicSprite::CreateFromScreenShot", Sc_DynamicSprite_CreateFromScreenShot);
617 }
618 
619 } // namespace AGS3
620