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/shared/ac/game_setup_struct.h"
24 #include "ags/engine/ac/view_frame.h"
25 #include "ags/engine/debugging/debug_log.h"
26 #include "ags/shared/ac/sprite_cache.h"
27 #include "ags/shared/gfx/bitmap.h"
28 #include "ags/engine/script/runtime_script_value.h"
29 #include "ags/engine/ac/dynobj/cc_audio_clip.h"
30 #include "ags/engine/ac/draw.h"
31 #include "ags/shared/ac/game_version.h"
32 #include "ags/engine/media/audio/audio_system.h"
33 #include "ags/shared/debugging/out.h"
34 #include "ags/engine/script/script_api.h"
35 #include "ags/engine/script/script_runtime.h"
36 #include "ags/globals.h"
37 
38 namespace AGS3 {
39 
40 using AGS::Shared::Bitmap;
41 using AGS::Shared::Graphics;
42 
43 
44 
45 
46 
47 
48 
ViewFrame_GetFlipped(ScriptViewFrame * svf)49 int ViewFrame_GetFlipped(ScriptViewFrame *svf) {
50 	if (_G(views)[svf->view].loops[svf->loop].frames[svf->frame].flags & VFLG_FLIPSPRITE)
51 		return 1;
52 	return 0;
53 }
54 
ViewFrame_GetGraphic(ScriptViewFrame * svf)55 int ViewFrame_GetGraphic(ScriptViewFrame *svf) {
56 	return _G(views)[svf->view].loops[svf->loop].frames[svf->frame].pic;
57 }
58 
ViewFrame_SetGraphic(ScriptViewFrame * svf,int newPic)59 void ViewFrame_SetGraphic(ScriptViewFrame *svf, int newPic) {
60 	_G(views)[svf->view].loops[svf->loop].frames[svf->frame].pic = newPic;
61 }
62 
ViewFrame_GetLinkedAudio(ScriptViewFrame * svf)63 ScriptAudioClip *ViewFrame_GetLinkedAudio(ScriptViewFrame *svf) {
64 	int soundIndex = _G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound;
65 	if (soundIndex < 0)
66 		return nullptr;
67 
68 	return &_GP(game).audioClips[soundIndex];
69 }
70 
ViewFrame_SetLinkedAudio(ScriptViewFrame * svf,ScriptAudioClip * clip)71 void ViewFrame_SetLinkedAudio(ScriptViewFrame *svf, ScriptAudioClip *clip) {
72 	int newSoundIndex = -1;
73 	if (clip != nullptr)
74 		newSoundIndex = clip->id;
75 
76 	_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound = newSoundIndex;
77 }
78 
ViewFrame_GetSound(ScriptViewFrame * svf)79 int ViewFrame_GetSound(ScriptViewFrame *svf) {
80 	// convert audio clip to old-style sound number
81 	return get_old_style_number_for_sound(_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound);
82 }
83 
ViewFrame_SetSound(ScriptViewFrame * svf,int newSound)84 void ViewFrame_SetSound(ScriptViewFrame *svf, int newSound) {
85 	if (newSound < 1) {
86 		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].audioclip = -1;
87 	} else {
88 		// convert sound number to audio clip
89 		ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(_GP(game), false, newSound);
90 		if (clip == nullptr)
91 			quitprintf("!SetFrameSound: audio clip aSound%d not found", newSound);
92 
93 		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound =
94 			_GP(game).IsLegacyAudioSystem() ? newSound : clip->id;
95 		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].audioclip = clip->id;
96 	}
97 }
98 
ViewFrame_GetSpeed(ScriptViewFrame * svf)99 int ViewFrame_GetSpeed(ScriptViewFrame *svf) {
100 	return _G(views)[svf->view].loops[svf->loop].frames[svf->frame].speed;
101 }
102 
ViewFrame_GetView(ScriptViewFrame * svf)103 int ViewFrame_GetView(ScriptViewFrame *svf) {
104 	return svf->view + 1;
105 }
106 
ViewFrame_GetLoop(ScriptViewFrame * svf)107 int ViewFrame_GetLoop(ScriptViewFrame *svf) {
108 	return svf->loop;
109 }
110 
ViewFrame_GetFrame(ScriptViewFrame * svf)111 int ViewFrame_GetFrame(ScriptViewFrame *svf) {
112 	return svf->frame;
113 }
114 
115 //=============================================================================
116 
precache_view(int view)117 void precache_view(int view) {
118 	if (view < 0)
119 		return;
120 
121 	for (int i = 0; i < _G(views)[view].numLoops; i++) {
122 		for (int j = 0; j < _G(views)[view].loops[i].numFrames; j++)
123 			_GP(spriteset).Precache(_G(views)[view].loops[i].frames[j].pic);
124 	}
125 }
126 
127 // the specified frame has just appeared, see if we need
128 // to play a sound or whatever
CheckViewFrame(int view,int loop,int frame,int sound_volume)129 void CheckViewFrame(int view, int loop, int frame, int sound_volume) {
130 	ScriptAudioChannel *channel = nullptr;
131 	if (_GP(game).IsLegacyAudioSystem()) {
132 		// sound field contains legacy sound num, so we also need an actual clip index
133 		const int sound = _G(views)[view].loops[loop].frames[frame].sound;
134 		int &clip_id = _G(views)[view].loops[loop].frames[frame].audioclip;
135 		if (sound > 0) {
136 			if (clip_id < 0) {
137 				ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(_GP(game), false, sound);
138 				if (!clip)
139 					return;
140 				clip_id = clip->id;
141 			}
142 			channel = play_audio_clip_by_index(clip_id);
143 		}
144 	} else {
145 		if (_G(views)[view].loops[loop].frames[frame].sound >= 0) {
146 			// play this sound (eg. footstep)
147 			channel = play_audio_clip_by_index(_G(views)[view].loops[loop].frames[frame].sound);
148 		}
149 	}
150 	if (sound_volume != SCR_NO_VALUE && channel != nullptr) {
151 		AudioChannelsLock lock;
152 		auto *ch = lock.GetChannel(channel->id);
153 		if (ch)
154 			ch->set_volume_percent(ch->get_volume() * sound_volume / 100);
155 	}
156 }
157 
158 // draws a view frame, flipped if appropriate
DrawViewFrame(Bitmap * ds,const ViewFrame * vframe,int x,int y,bool alpha_blend)159 void DrawViewFrame(Bitmap *ds, const ViewFrame *vframe, int x, int y, bool alpha_blend) {
160 	// NOTE: DrawViewFrame supports alpha blending only since OPT_SPRITEALPHA;
161 	// this is why there's no sense in blending if it's not set (will do no good anyway).
162 	if (alpha_blend && _GP(game).options[OPT_SPRITEALPHA] == kSpriteAlphaRender_Proper) {
163 		Bitmap *vf_bmp = _GP(spriteset)[vframe->pic];
164 		Bitmap *src = vf_bmp;
165 		if (vframe->flags & VFLG_FLIPSPRITE) {
166 			src = new Bitmap(vf_bmp->GetWidth(), vf_bmp->GetHeight(), vf_bmp->GetColorDepth());
167 			src->FlipBlt(vf_bmp, 0, 0, Shared::kBitmap_HFlip);
168 		}
169 		draw_sprite_support_alpha(ds, true, x, y, src, (_GP(game).SpriteInfos[vframe->pic].Flags & SPF_ALPHACHANNEL) != 0);
170 		if (src != vf_bmp)
171 			delete src;
172 	} else {
173 		if (vframe->flags & VFLG_FLIPSPRITE)
174 			ds->FlipBlt(_GP(spriteset)[vframe->pic], x, y, Shared::kBitmap_HFlip);
175 		else
176 			ds->Blit(_GP(spriteset)[vframe->pic], x, y, Shared::kBitmap_Transparency);
177 	}
178 }
179 
180 //=============================================================================
181 //
182 // Script API Functions
183 //
184 //=============================================================================
185 
186 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetFlipped(void * self,const RuntimeScriptValue * params,int32_t param_count)187 RuntimeScriptValue Sc_ViewFrame_GetFlipped(void *self, const RuntimeScriptValue *params, int32_t param_count) {
188 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetFlipped);
189 }
190 
191 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetFrame(void * self,const RuntimeScriptValue * params,int32_t param_count)192 RuntimeScriptValue Sc_ViewFrame_GetFrame(void *self, const RuntimeScriptValue *params, int32_t param_count) {
193 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetFrame);
194 }
195 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)196 RuntimeScriptValue Sc_ViewFrame_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
197 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetGraphic);
198 }
199 
200 // void (ScriptViewFrame *svf, int newPic)
Sc_ViewFrame_SetGraphic(void * self,const RuntimeScriptValue * params,int32_t param_count)201 RuntimeScriptValue Sc_ViewFrame_SetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
202 	API_OBJCALL_VOID_PINT(ScriptViewFrame, ViewFrame_SetGraphic);
203 }
204 
205 // ScriptAudioClip* (ScriptViewFrame *svf)
Sc_ViewFrame_GetLinkedAudio(void * self,const RuntimeScriptValue * params,int32_t param_count)206 RuntimeScriptValue Sc_ViewFrame_GetLinkedAudio(void *self, const RuntimeScriptValue *params, int32_t param_count) {
207 	API_OBJCALL_OBJ(ScriptViewFrame, ScriptAudioClip, _GP(ccDynamicAudioClip), ViewFrame_GetLinkedAudio);
208 }
209 
210 // void (ScriptViewFrame *svf, ScriptAudioClip* clip)
Sc_ViewFrame_SetLinkedAudio(void * self,const RuntimeScriptValue * params,int32_t param_count)211 RuntimeScriptValue Sc_ViewFrame_SetLinkedAudio(void *self, const RuntimeScriptValue *params, int32_t param_count) {
212 	API_OBJCALL_VOID_POBJ(ScriptViewFrame, ViewFrame_SetLinkedAudio, ScriptAudioClip);
213 }
214 
215 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetLoop(void * self,const RuntimeScriptValue * params,int32_t param_count)216 RuntimeScriptValue Sc_ViewFrame_GetLoop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
217 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetLoop);
218 }
219 
220 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetSound(void * self,const RuntimeScriptValue * params,int32_t param_count)221 RuntimeScriptValue Sc_ViewFrame_GetSound(void *self, const RuntimeScriptValue *params, int32_t param_count) {
222 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetSound);
223 }
224 
225 // void (ScriptViewFrame *svf, int newSound)
Sc_ViewFrame_SetSound(void * self,const RuntimeScriptValue * params,int32_t param_count)226 RuntimeScriptValue Sc_ViewFrame_SetSound(void *self, const RuntimeScriptValue *params, int32_t param_count) {
227 	API_OBJCALL_VOID_PINT(ScriptViewFrame, ViewFrame_SetSound);
228 }
229 
230 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetSpeed(void * self,const RuntimeScriptValue * params,int32_t param_count)231 RuntimeScriptValue Sc_ViewFrame_GetSpeed(void *self, const RuntimeScriptValue *params, int32_t param_count) {
232 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetSpeed);
233 }
234 
235 // int (ScriptViewFrame *svf)
Sc_ViewFrame_GetView(void * self,const RuntimeScriptValue * params,int32_t param_count)236 RuntimeScriptValue Sc_ViewFrame_GetView(void *self, const RuntimeScriptValue *params, int32_t param_count) {
237 	API_OBJCALL_INT(ScriptViewFrame, ViewFrame_GetView);
238 }
239 
240 
RegisterViewFrameAPI()241 void RegisterViewFrameAPI() {
242 	ccAddExternalObjectFunction("ViewFrame::get_Flipped", Sc_ViewFrame_GetFlipped);
243 	ccAddExternalObjectFunction("ViewFrame::get_Frame", Sc_ViewFrame_GetFrame);
244 	ccAddExternalObjectFunction("ViewFrame::get_Graphic", Sc_ViewFrame_GetGraphic);
245 	ccAddExternalObjectFunction("ViewFrame::set_Graphic", Sc_ViewFrame_SetGraphic);
246 	ccAddExternalObjectFunction("ViewFrame::get_LinkedAudio", Sc_ViewFrame_GetLinkedAudio);
247 	ccAddExternalObjectFunction("ViewFrame::set_LinkedAudio", Sc_ViewFrame_SetLinkedAudio);
248 	ccAddExternalObjectFunction("ViewFrame::get_Loop", Sc_ViewFrame_GetLoop);
249 	ccAddExternalObjectFunction("ViewFrame::get_Sound", Sc_ViewFrame_GetSound);
250 	ccAddExternalObjectFunction("ViewFrame::set_Sound", Sc_ViewFrame_SetSound);
251 	ccAddExternalObjectFunction("ViewFrame::get_Speed", Sc_ViewFrame_GetSpeed);
252 	ccAddExternalObjectFunction("ViewFrame::get_View", Sc_ViewFrame_GetView);
253 }
254 
255 } // namespace AGS3
256