Initial commit
This commit is contained in:
73
engines/ags/engine/ac/asset_helper.h
Normal file
73
engines/ags/engine/ac/asset_helper.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Functions related to finding and opening game assets.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_ASSET_HELPER_H
|
||||
#define AGS_ENGINE_AC_ASSET_HELPER_H
|
||||
|
||||
#include "common/std/memory.h"
|
||||
#include "common/std/utility.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
#include "ags/shared/core/asset_manager.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct PACKFILE;
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
using AGS::Shared::AssetPath;
|
||||
using AGS::Shared::Stream;
|
||||
using AGS::Shared::String;
|
||||
|
||||
// Looks for valid asset library everywhere and returns path, or empty string if failed
|
||||
String find_assetlib(const String &filename);
|
||||
|
||||
// Returns the path to the audio asset, considering the given bundling type
|
||||
AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename);
|
||||
// Returns the path to the voice-over asset
|
||||
AssetPath get_voice_over_assetpath(const String &filename);
|
||||
|
||||
// Custom AGS PACKFILE user object
|
||||
// TODO: it is preferrable to let our Stream define custom readable window instead,
|
||||
// keeping this as simple as possible for now (we may require a stream classes overhaul).
|
||||
struct AGS_PACKFILE_OBJ {
|
||||
std::unique_ptr<Stream> stream;
|
||||
size_t asset_size = 0u;
|
||||
size_t remains = 0u;
|
||||
};
|
||||
// Creates PACKFILE stream from AGS asset.
|
||||
// This function is supposed to be used only when you have to create Allegro
|
||||
// object, passing PACKFILE stream to constructor.
|
||||
PACKFILE *PackfileFromAsset(const AssetPath &path);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
333
engines/ags/engine/ac/audio_channel.cpp
Normal file
333
engines/ags/engine/ac/audio_channel.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/audio_channel.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/engine/ac/global_audio.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int AudioChannel_GetID(ScriptAudioChannel *channel) {
|
||||
return channel->id;
|
||||
}
|
||||
|
||||
int AudioChannel_GetIsPlaying(ScriptAudioChannel *channel) {
|
||||
if (_GP(play).fast_forward) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return AudioChans::ChannelIsPlaying(channel->id) ? 1 : 0;
|
||||
}
|
||||
|
||||
bool AudioChannel_GetIsPaused(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) return ch->is_paused();
|
||||
return false;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPanning(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
return ch->get_panning();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioChannel_SetPanning(ScriptAudioChannel *channel, int newPanning) {
|
||||
if ((newPanning < -100) || (newPanning > 100))
|
||||
quitprintf("!AudioChannel.Panning: panning value must be between -100 and 100 (passed=%d)", newPanning);
|
||||
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
ch->set_panning(newPanning);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptAudioClip *AudioChannel_GetPlayingClip(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch && ch->_sourceClipID >= 0) {
|
||||
return &_GP(game).audioClips[ch->_sourceClipID];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPosition(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
if (_GP(play).fast_forward)
|
||||
return 999999999;
|
||||
|
||||
return ch->get_pos();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPositionMs(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
if (_GP(play).fast_forward)
|
||||
return 999999999;
|
||||
|
||||
return ch->get_pos_ms();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetLengthMs(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
return ch->get_length_ms();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetVolume(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
return ch->get_volume100();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_SetVolume(ScriptAudioChannel *channel, int newVolume) {
|
||||
if ((newVolume < 0) || (newVolume > 100))
|
||||
quitprintf("!AudioChannel.Volume: new value out of range (supplied: %d, range: 0..100)", newVolume);
|
||||
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
ch->set_volume100(newVolume);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetSpeed(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
return ch->get_speed();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioChannel_SetSpeed(ScriptAudioChannel *channel, int new_speed) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
ch->set_speed(new_speed);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioChannel_Stop(ScriptAudioChannel *channel) {
|
||||
if (channel->id == SCHAN_SPEECH && _GP(play).IsNonBlockingVoiceSpeech())
|
||||
stop_voice_nonblocking();
|
||||
else
|
||||
stop_or_fade_out_channel(channel->id, -1, nullptr);
|
||||
}
|
||||
|
||||
void AudioChannel_Pause(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
if (ch) ch->pause();
|
||||
}
|
||||
|
||||
void AudioChannel_Resume(ScriptAudioChannel *channel) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
if (ch) ch->resume();
|
||||
}
|
||||
|
||||
void AudioChannel_Seek(ScriptAudioChannel *channel, int newPosition) {
|
||||
if (newPosition < 0)
|
||||
quitprintf("!AudioChannel.Seek: invalid seek position %d", newPosition);
|
||||
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
if (ch)
|
||||
ch->seek(newPosition);
|
||||
}
|
||||
|
||||
void AudioChannel_SeekMs(ScriptAudioChannel *channel, int newPosition) {
|
||||
if (newPosition < 0)
|
||||
quitprintf("!AudioChannel.SeekMs: invalid seek position %d", newPosition);
|
||||
|
||||
auto* ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
if (ch)
|
||||
ch->seek_ms(newPosition);
|
||||
}
|
||||
|
||||
void AudioChannel_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch) {
|
||||
int maxDist = ((xPos > _GP(thisroom).Width / 2) ? xPos : (_GP(thisroom).Width - xPos)) - AMBIENCE_FULL_DIST;
|
||||
ch->_xSource = (xPos > 0) ? xPos : -1;
|
||||
ch->_ySource = yPos;
|
||||
ch->_maximumPossibleDistanceAway = maxDist;
|
||||
if (xPos > 0) {
|
||||
update_directional_sound_vol();
|
||||
} else {
|
||||
ch->apply_directional_modifier(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetID);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetIsPlaying(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetIsPlaying);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetPanning(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetPanning);
|
||||
}
|
||||
|
||||
// void | ScriptAudioChannel *channel, int newPanning
|
||||
RuntimeScriptValue Sc_AudioChannel_SetPanning(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_SetPanning);
|
||||
}
|
||||
|
||||
// ScriptAudioClip* | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetPlayingClip(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ(ScriptAudioChannel, ScriptAudioClip, _GP(ccDynamicAudioClip), AudioChannel_GetPlayingClip);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetPosition(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetPosition);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetPositionMs(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetPositionMs);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetLengthMs(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetLengthMs);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_GetVolume(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetVolume);
|
||||
}
|
||||
|
||||
// int | ScriptAudioChannel *channel, int newVolume
|
||||
RuntimeScriptValue Sc_AudioChannel_SetVolume(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT_PINT(ScriptAudioChannel, AudioChannel_SetVolume);
|
||||
}
|
||||
|
||||
// void | ScriptAudioChannel *channel
|
||||
RuntimeScriptValue Sc_AudioChannel_Stop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptAudioChannel, AudioChannel_Stop);
|
||||
}
|
||||
|
||||
// void | ScriptAudioChannel *channel, int newPosition
|
||||
RuntimeScriptValue Sc_AudioChannel_Seek(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_Seek);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_SeekMs(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_SeekMs);
|
||||
}
|
||||
|
||||
// void | ScriptAudioChannel *channel, int xPos, int yPos
|
||||
RuntimeScriptValue Sc_AudioChannel_SetRoomLocation(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT2(ScriptAudioChannel, AudioChannel_SetRoomLocation);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_GetSpeed(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetSpeed);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_SetSpeed(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_SetSpeed);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_Pause(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptAudioChannel, AudioChannel_Pause);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_Resume(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptAudioChannel, AudioChannel_Resume);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioChannel_GetIsPaused(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_BOOL(ScriptAudioChannel, AudioChannel_GetIsPaused);
|
||||
}
|
||||
|
||||
void RegisterAudioChannelAPI() {
|
||||
ScFnRegister audiochan_api[] = {
|
||||
{"AudioChannel::Pause^0", API_FN_PAIR(AudioChannel_Pause)},
|
||||
{"AudioChannel::Resume^0", API_FN_PAIR(AudioChannel_Resume)},
|
||||
{"AudioChannel::Seek^1", API_FN_PAIR(AudioChannel_Seek)},
|
||||
{"AudioChannel::SeekMs^1", API_FN_PAIR(AudioChannel_SeekMs)},
|
||||
{"AudioChannel::SetRoomLocation^2", API_FN_PAIR(AudioChannel_SetRoomLocation)},
|
||||
{"AudioChannel::Stop^0", API_FN_PAIR(AudioChannel_Stop)},
|
||||
{"AudioChannel::get_ID", API_FN_PAIR(AudioChannel_GetID)},
|
||||
{"AudioChannel::get_IsPaused", API_FN_PAIR(AudioChannel_GetIsPaused)},
|
||||
{"AudioChannel::get_IsPlaying", API_FN_PAIR(AudioChannel_GetIsPlaying)},
|
||||
{"AudioChannel::get_LengthMs", API_FN_PAIR(AudioChannel_GetLengthMs)},
|
||||
{"AudioChannel::get_Panning", API_FN_PAIR(AudioChannel_GetPanning)},
|
||||
{"AudioChannel::set_Panning", API_FN_PAIR(AudioChannel_SetPanning)},
|
||||
{"AudioChannel::get_PlayingClip", API_FN_PAIR(AudioChannel_GetPlayingClip)},
|
||||
{"AudioChannel::get_Position", API_FN_PAIR(AudioChannel_GetPosition)},
|
||||
{"AudioChannel::get_PositionMs", API_FN_PAIR(AudioChannel_GetPositionMs)},
|
||||
{"AudioChannel::get_Volume", API_FN_PAIR(AudioChannel_GetVolume)},
|
||||
{"AudioChannel::set_Volume", API_FN_PAIR(AudioChannel_SetVolume)},
|
||||
{"AudioChannel::get_Speed", API_FN_PAIR(AudioChannel_GetSpeed)},
|
||||
{"AudioChannel::set_Speed", API_FN_PAIR(AudioChannel_SetSpeed)},
|
||||
// For compatibility with Ahmet Kamil's (aka Gord10) custom engine
|
||||
{"AudioChannel::SetSpeed^1", API_FN_PAIR(AudioChannel_SetSpeed)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(audiochan_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
47
engines/ags/engine/ac/audio_channel.h
Normal file
47
engines/ags/engine/ac/audio_channel.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_AUDIO_CHANNEL_H
|
||||
#define AGS_ENGINE_AC_AUDIO_CHANNEL_H
|
||||
|
||||
#include "ags/shared/ac/dynobj/script_audio_clip.h"
|
||||
#include "ags/engine/ac/dynobj/script_audio_channel.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int AudioChannel_GetID(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetIsPlaying(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetPanning(ScriptAudioChannel *channel);
|
||||
void AudioChannel_SetPanning(ScriptAudioChannel *channel, int newPanning);
|
||||
ScriptAudioClip *AudioChannel_GetPlayingClip(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetPosition(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetPositionMs(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetLengthMs(ScriptAudioChannel *channel);
|
||||
int AudioChannel_GetVolume(ScriptAudioChannel *channel);
|
||||
int AudioChannel_SetVolume(ScriptAudioChannel *channel, int newVolume);
|
||||
void AudioChannel_Stop(ScriptAudioChannel *channel);
|
||||
void AudioChannel_Seek(ScriptAudioChannel *channel, int newPosition);
|
||||
void AudioChannel_SeekMs(ScriptAudioChannel *channel, int newPosition);
|
||||
void AudioChannel_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
173
engines/ags/engine/ac/audio_clip.cpp
Normal file
173
engines/ags/engine/ac/audio_clip.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/engine/ac/asset_helper.h"
|
||||
#include "ags/engine/ac/audio_clip.h"
|
||||
#include "ags/engine/ac/audio_channel.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/string.h"
|
||||
#include "ags/shared/core/asset_manager.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_channel.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
|
||||
#include "ags/engine/ac/dynobj/script_string.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int AudioClip_GetID(ScriptAudioClip *clip) {
|
||||
return clip->id;
|
||||
}
|
||||
|
||||
const char *AudioClip_GetScriptName(ScriptAudioClip *clip) {
|
||||
return CreateNewScriptString(clip->scriptName);
|
||||
}
|
||||
|
||||
int AudioClip_GetFileType(ScriptAudioClip *clip) {
|
||||
return clip->fileType;
|
||||
}
|
||||
|
||||
int AudioClip_GetType(ScriptAudioClip *clip) {
|
||||
return clip->type;
|
||||
}
|
||||
int AudioClip_GetIsAvailable(ScriptAudioClip *clip) {
|
||||
return _GP(AssetMgr)->DoesAssetExist(get_audio_clip_assetpath(clip->bundlingType, clip->fileName)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void AudioClip_Stop(ScriptAudioClip *clip) {
|
||||
for (int i = NUM_SPEECH_CHANS; i < _GP(game).numGameChannels; i++) {
|
||||
auto *ch = AudioChans::GetChannelIfPlaying(i);
|
||||
if ((ch != nullptr) && (ch->_sourceClipID == clip->id)) {
|
||||
AudioChannel_Stop(&_G(scrAudioChannel)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScriptAudioChannel *AudioClip_Play(ScriptAudioClip *clip, int priority, int repeat) {
|
||||
ScriptAudioChannel *sc_ch = play_audio_clip(clip, priority, repeat, 0, false);
|
||||
return sc_ch;
|
||||
}
|
||||
|
||||
ScriptAudioChannel *AudioClip_PlayFrom(ScriptAudioClip *clip, int position, int priority, int repeat) {
|
||||
ScriptAudioChannel *sc_ch = play_audio_clip(clip, priority, repeat, position, false);
|
||||
return sc_ch;
|
||||
}
|
||||
|
||||
ScriptAudioChannel *AudioClip_PlayQueued(ScriptAudioClip *clip, int priority, int repeat) {
|
||||
ScriptAudioChannel *sc_ch = play_audio_clip(clip, priority, repeat, 0, true);
|
||||
return sc_ch;
|
||||
}
|
||||
|
||||
ScriptAudioChannel *AudioClip_PlayOnChannel(ScriptAudioClip *clip, int chan, int priority, int repeat) {
|
||||
if (chan < NUM_SPEECH_CHANS || chan >= _GP(game).numGameChannels)
|
||||
quitprintf("!AudioClip.PlayOnChannel: invalid channel %d, the range is %d - %d",
|
||||
chan, NUM_SPEECH_CHANS, _GP(game).numGameChannels - 1);
|
||||
if (priority == SCR_NO_VALUE)
|
||||
priority = clip->defaultPriority;
|
||||
if (repeat == SCR_NO_VALUE)
|
||||
repeat = clip->defaultRepeat;
|
||||
return play_audio_clip_on_channel(chan, clip, priority, repeat, 0);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
ScriptAudioClip *AudioClip_GetByName(const char *name) {
|
||||
return static_cast<ScriptAudioClip *>(ccGetScriptObjectAddress(name, _GP(ccDynamicAudioClip).GetType()));
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioClip_GetByName(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJ_POBJ(ScriptAudioClip, _GP(ccDynamicAudioClip), AudioClip_GetByName, const char);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioClip_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetID);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioClip_GetScriptName(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ(ScriptAudioClip, const char, _GP(myScriptStringImpl), AudioClip_GetScriptName);
|
||||
}
|
||||
|
||||
// int | ScriptAudioClip *clip
|
||||
RuntimeScriptValue Sc_AudioClip_GetFileType(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetFileType);
|
||||
}
|
||||
|
||||
// int | ScriptAudioClip *clip
|
||||
RuntimeScriptValue Sc_AudioClip_GetType(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetType);
|
||||
}
|
||||
|
||||
// int | ScriptAudioClip *clip
|
||||
RuntimeScriptValue Sc_AudioClip_GetIsAvailable(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetIsAvailable);
|
||||
}
|
||||
|
||||
// void | ScriptAudioClip *clip
|
||||
RuntimeScriptValue Sc_AudioClip_Stop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptAudioClip, AudioClip_Stop);
|
||||
}
|
||||
|
||||
// ScriptAudioChannel* | ScriptAudioClip *clip, int priority, int repeat
|
||||
RuntimeScriptValue Sc_AudioClip_Play(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ_PINT2(ScriptAudioClip, ScriptAudioChannel, _GP(ccDynamicAudio), AudioClip_Play);
|
||||
}
|
||||
|
||||
// ScriptAudioChannel* | ScriptAudioClip *clip, int position, int priority, int repeat
|
||||
RuntimeScriptValue Sc_AudioClip_PlayFrom(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ_PINT3(ScriptAudioClip, ScriptAudioChannel, _GP(ccDynamicAudio), AudioClip_PlayFrom);
|
||||
}
|
||||
|
||||
// ScriptAudioChannel* | ScriptAudioClip *clip, int priority, int repeat
|
||||
RuntimeScriptValue Sc_AudioClip_PlayQueued(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ_PINT2(ScriptAudioClip, ScriptAudioChannel, _GP(ccDynamicAudio), AudioClip_PlayQueued);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_AudioClip_PlayOnChannel(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ_PINT3(ScriptAudioClip, ScriptAudioChannel, _GP(ccDynamicAudio), AudioClip_PlayOnChannel);
|
||||
}
|
||||
|
||||
void RegisterAudioClipAPI() {
|
||||
ScFnRegister audioclip_api[] = {
|
||||
{"AudioClip::GetByName", API_FN_PAIR(AudioClip_GetByName)},
|
||||
{"AudioClip::Play^2", API_FN_PAIR(AudioClip_Play)},
|
||||
{"AudioClip::PlayFrom^3", API_FN_PAIR(AudioClip_PlayFrom)},
|
||||
{"AudioClip::PlayQueued^2", API_FN_PAIR(AudioClip_PlayQueued)},
|
||||
{"AudioClip::PlayOnChannel^3", API_FN_PAIR(AudioClip_PlayOnChannel)},
|
||||
{"AudioClip::Stop^0", API_FN_PAIR(AudioClip_Stop)},
|
||||
{"AudioClip::get_ID", API_FN_PAIR(AudioClip_GetID)},
|
||||
{"AudioClip::get_FileType", API_FN_PAIR(AudioClip_GetFileType)},
|
||||
{"AudioClip::get_IsAvailable", API_FN_PAIR(AudioClip_GetIsAvailable)},
|
||||
{"AudioClip::get_ScriptName", API_FN_PAIR(AudioClip_GetScriptName)},
|
||||
{"AudioClip::get_Type", API_FN_PAIR(AudioClip_GetType)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(audioclip_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
41
engines/ags/engine/ac/audio_clip.h
Normal file
41
engines/ags/engine/ac/audio_clip.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_AUDIO_CLIP_H
|
||||
#define AGS_ENGINE_AC_AUDIO_CLIP_H
|
||||
|
||||
#include "ags/shared/ac/dynobj/script_audio_clip.h"
|
||||
#include "ags/engine/ac/dynobj/script_audio_channel.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int AudioClip_GetFileType(ScriptAudioClip *clip);
|
||||
int AudioClip_GetType(ScriptAudioClip *clip);
|
||||
int AudioClip_GetIsAvailable(ScriptAudioClip *clip);
|
||||
void AudioClip_Stop(ScriptAudioClip *clip);
|
||||
ScriptAudioChannel *AudioClip_Play(ScriptAudioClip *clip, int priority, int repeat);
|
||||
ScriptAudioChannel *AudioClip_PlayFrom(ScriptAudioClip *clip, int position, int priority, int repeat);
|
||||
ScriptAudioChannel *AudioClip_PlayQueued(ScriptAudioClip *clip, int priority, int repeat);
|
||||
ScriptAudioChannel *AudioClip_PlayOnChannel(ScriptAudioClip *clip, int chan, int priority, int repeat);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
455
engines/ags/engine/ac/button.cpp
Normal file
455
engines/ags/engine/ac/button.cpp
Normal file
@@ -0,0 +1,455 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/button.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/engine/ac/gui.h"
|
||||
#include "ags/shared/ac/view.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/global_translation.h"
|
||||
#include "ags/engine/ac/object.h"
|
||||
#include "ags/engine/ac/string.h"
|
||||
#include "ags/engine/ac/view_frame.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/gui/animating_gui_button.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/engine/ac/dynobj/script_string.h"
|
||||
#include "ags/engine/main/game_run.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// *** BUTTON FUNCTIONS
|
||||
|
||||
// Update the actual button's image from the current animation frame
|
||||
void UpdateButtonState(const AnimatingGUIButton &abtn) {
|
||||
// Assign view frame as normal image and reset all the rest
|
||||
_GP(guibuts)[abtn.buttonid].SetImages(_GP(views)[abtn.view].loops[abtn.loop].frames[abtn.frame].pic, 0, 0);
|
||||
}
|
||||
|
||||
void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat, int blocking, int direction, int sframe, int volume) {
|
||||
int guin = butt->ParentId;
|
||||
int objn = butt->Id;
|
||||
|
||||
view--; // convert to internal 0-based view ID
|
||||
ValidateViewAnimVLF("Button.Animate", view, loop, sframe);
|
||||
|
||||
ValidateViewAnimParams("Button.Animate", repeat, blocking, direction);
|
||||
|
||||
volume = Math::Clamp(volume, 0, 100);
|
||||
|
||||
// if it's already animating, stop it
|
||||
FindAndRemoveButtonAnimation(guin, objn);
|
||||
|
||||
int but_id = _GP(guis)[guin].GetControlID(objn);
|
||||
AnimatingGUIButton abtn;
|
||||
abtn.ongui = guin;
|
||||
abtn.onguibut = objn;
|
||||
abtn.buttonid = but_id;
|
||||
abtn.view = view;
|
||||
abtn.loop = loop;
|
||||
abtn.speed = speed;
|
||||
abtn.repeat = (repeat != 0) ? ANIM_REPEAT : ANIM_ONCE; // for now, clamp to supported modes
|
||||
abtn.blocking = blocking;
|
||||
abtn.direction = direction;
|
||||
abtn.frame = SetFirstAnimFrame(view, loop, sframe, direction);
|
||||
abtn.wait = abtn.speed + _GP(views)[abtn.view].loops[abtn.loop].frames[abtn.frame].speed;
|
||||
abtn.volume = volume;
|
||||
_GP(animbuts).push_back(abtn);
|
||||
// launch into the first frame, and play the first frame's sound
|
||||
UpdateButtonState(abtn);
|
||||
CheckViewFrame(abtn.view, abtn.loop, abtn.frame);
|
||||
|
||||
// Blocking animate
|
||||
if (blocking)
|
||||
GameLoopUntilButAnimEnd(guin, objn);
|
||||
}
|
||||
|
||||
void Button_Animate4(GUIButton *butt, int view, int loop, int speed, int repeat) {
|
||||
Button_Animate(butt, view, loop, speed, repeat, IN_BACKGROUND, FORWARDS, 0, 100 /* full volume */);
|
||||
}
|
||||
|
||||
void Button_Animate7(GUIButton *butt, int view, int loop, int speed, int repeat, int blocking, int direction, int sframe) {
|
||||
Button_Animate(butt, view, loop, speed, repeat, blocking, direction, sframe, 100 /* full volume */);
|
||||
}
|
||||
|
||||
const char *Button_GetText_New(GUIButton *butt) {
|
||||
return CreateNewScriptString(butt->GetText().GetCStr());
|
||||
}
|
||||
|
||||
void Button_GetText(GUIButton *butt, char *buffer) {
|
||||
snprintf(buffer, MAX_MAXSTRLEN, "%s", butt->GetText().GetCStr());
|
||||
}
|
||||
|
||||
void Button_SetText(GUIButton *butt, const char *newtx) {
|
||||
newtx = get_translation(newtx);
|
||||
|
||||
if (butt->GetText() != newtx) {
|
||||
butt->SetText(newtx);
|
||||
}
|
||||
}
|
||||
|
||||
void Button_SetFont(GUIButton *butt, int newFont) {
|
||||
if ((newFont < 0) || (newFont >= _GP(game).numfonts))
|
||||
quit("!Button.Font: invalid font number.");
|
||||
|
||||
if (butt->Font != newFont) {
|
||||
butt->Font = newFont;
|
||||
butt->MarkChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int Button_GetFont(GUIButton *butt) {
|
||||
return butt->Font;
|
||||
}
|
||||
|
||||
int Button_GetClipImage(GUIButton *butt) {
|
||||
return butt->IsClippingImage() ? 1 : 0;
|
||||
}
|
||||
|
||||
void Button_SetClipImage(GUIButton *butt, int newval) {
|
||||
if (butt->IsClippingImage() != (newval != 0)) {
|
||||
butt->SetClipImage(newval != 0);
|
||||
}
|
||||
}
|
||||
|
||||
int Button_GetGraphic(GUIButton *butt) {
|
||||
// return currently displayed pic
|
||||
if (butt->GetCurrentImage() < 0)
|
||||
return butt->GetNormalImage();
|
||||
return butt->GetCurrentImage();
|
||||
}
|
||||
|
||||
int Button_GetMouseOverGraphic(GUIButton *butt) {
|
||||
return butt->GetMouseOverImage();
|
||||
}
|
||||
|
||||
void Button_SetMouseOverGraphic(GUIButton *guil, int slotn) {
|
||||
debug_script_log("GUI %d Button %d mouseover set to slot %d", guil->ParentId, guil->Id, slotn);
|
||||
slotn = std::max(0, slotn);
|
||||
guil->SetMouseOverImage(slotn);
|
||||
FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
|
||||
}
|
||||
|
||||
int Button_GetNormalGraphic(GUIButton *butt) {
|
||||
return butt->GetNormalImage();
|
||||
}
|
||||
|
||||
void Button_SetNormalGraphic(GUIButton *butt, int slotn) {
|
||||
debug_script_log("GUI %d Button %d normal set to slot %d", butt->ParentId, butt->Id, slotn);
|
||||
slotn = std::max(0, slotn);
|
||||
// NormalGraphic = 0 will turn the Button into a standard colored button
|
||||
if (slotn == 0) {
|
||||
butt->SetNormalImage(slotn);
|
||||
}
|
||||
// Any other sprite - update the clickable area to the same size as the graphic
|
||||
else {
|
||||
const int width = static_cast<size_t>(slotn) < _GP(game).SpriteInfos.size() ? _GP(game).SpriteInfos[slotn].Width : 0;
|
||||
const int height = static_cast<size_t>(slotn) < _GP(game).SpriteInfos.size() ? _GP(game).SpriteInfos[slotn].Height : 0;
|
||||
butt->SetNormalImage(slotn);
|
||||
butt->SetSize(width, height);
|
||||
}
|
||||
|
||||
FindAndRemoveButtonAnimation(butt->ParentId, butt->Id);
|
||||
}
|
||||
|
||||
int Button_GetPushedGraphic(GUIButton *butt) {
|
||||
return butt->GetPushedImage();
|
||||
}
|
||||
|
||||
void Button_SetPushedGraphic(GUIButton *guil, int slotn) {
|
||||
debug_script_log("GUI %d Button %d pushed set to slot %d", guil->ParentId, guil->Id, slotn);
|
||||
slotn = std::max(0, slotn);
|
||||
guil->SetPushedImage(slotn);
|
||||
FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
|
||||
}
|
||||
|
||||
int Button_GetTextColor(GUIButton *butt) {
|
||||
return butt->TextColor;
|
||||
}
|
||||
|
||||
void Button_SetTextColor(GUIButton *butt, int newcol) {
|
||||
if (butt->TextColor != newcol) {
|
||||
butt->TextColor = newcol;
|
||||
butt->MarkChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// ** start animating buttons code
|
||||
|
||||
size_t GetAnimatingButtonCount() {
|
||||
return _GP(animbuts).size();
|
||||
}
|
||||
|
||||
AnimatingGUIButton *GetAnimatingButtonByIndex(int idxn) {
|
||||
return idxn >= 0 && (size_t)idxn < _GP(animbuts).size() ?
|
||||
&_GP(animbuts)[idxn] : nullptr;
|
||||
}
|
||||
|
||||
void AddButtonAnimation(const AnimatingGUIButton &abtn) {
|
||||
_GP(animbuts).push_back(abtn);
|
||||
}
|
||||
|
||||
// returns 1 if animation finished
|
||||
bool UpdateAnimatingButton(int bu) {
|
||||
AnimatingGUIButton &abtn = _GP(animbuts)[bu];
|
||||
if (abtn.wait > 0) {
|
||||
abtn.wait--;
|
||||
return true;
|
||||
}
|
||||
if (!CycleViewAnim(abtn.view, abtn.loop, abtn.frame, !abtn.direction, abtn.repeat))
|
||||
return false;
|
||||
CheckViewFrame(abtn.view, abtn.loop, abtn.frame, abtn.volume);
|
||||
abtn.wait = abtn.speed + _GP(views)[abtn.view].loops[abtn.loop].frames[abtn.frame].speed;
|
||||
UpdateButtonState(abtn);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StopButtonAnimation(int idxn) {
|
||||
_GP(animbuts).erase(_GP(animbuts).begin() + idxn);
|
||||
}
|
||||
|
||||
void RemoveAllButtonAnimations() {
|
||||
_GP(animbuts).clear();
|
||||
}
|
||||
|
||||
// Returns the index of the AnimatingGUIButton object corresponding to the
|
||||
// given button ID; returns -1 if no such animation exists
|
||||
int FindButtonAnimation(int guin, int objn) {
|
||||
for (size_t i = 0; i < _GP(animbuts).size(); ++i) {
|
||||
if (_GP(animbuts)[i].ongui == guin && _GP(animbuts)[i].onguibut == objn)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FindAndRemoveButtonAnimation(int guin, int objn) {
|
||||
int idx = FindButtonAnimation(guin, objn);
|
||||
if (idx >= 0)
|
||||
StopButtonAnimation(idx);
|
||||
}
|
||||
|
||||
// ** end animating buttons code
|
||||
|
||||
void Button_Click(GUIButton *butt, int mbut) {
|
||||
process_interface_click(butt->ParentId, butt->Id, mbut);
|
||||
}
|
||||
|
||||
bool Button_IsAnimating(GUIButton *butt) {
|
||||
return FindButtonAnimation(butt->ParentId, butt->Id) >= 0;
|
||||
}
|
||||
|
||||
// NOTE: in correspondance to similar functions for Character & Object,
|
||||
// GetView returns (view index + 1), while GetLoop and GetFrame return
|
||||
// zero-based index and 0 in case of no animation.
|
||||
int Button_GetAnimView(GUIButton *butt) {
|
||||
int idx = FindButtonAnimation(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? _GP(animbuts)[idx].view + 1 : 0;
|
||||
}
|
||||
|
||||
int Button_GetAnimLoop(GUIButton *butt) {
|
||||
int idx = FindButtonAnimation(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? _GP(animbuts)[idx].loop : 0;
|
||||
}
|
||||
|
||||
int Button_GetAnimFrame(GUIButton *butt) {
|
||||
int idx = FindButtonAnimation(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? _GP(animbuts)[idx].frame : 0;
|
||||
}
|
||||
|
||||
int Button_GetTextAlignment(GUIButton *butt) {
|
||||
return butt->TextAlignment;
|
||||
}
|
||||
|
||||
void Button_SetTextAlignment(GUIButton *butt, int align) {
|
||||
if (butt->TextAlignment != align) {
|
||||
butt->TextAlignment = (FrameAlignment)align;
|
||||
butt->MarkChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// void | GUIButton *butt, int view, int loop, int speed, int repeat
|
||||
RuntimeScriptValue Sc_Button_Animate4(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT4(GUIButton, Button_Animate4);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_Animate7(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT7(GUIButton, Button_Animate7);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_Animate(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT8(GUIButton, Button_Animate);
|
||||
}
|
||||
|
||||
// const char* | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetText_New(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ(GUIButton, const char, _GP(myScriptStringImpl), Button_GetText_New);
|
||||
}
|
||||
|
||||
// void | GUIButton *butt, char *buffer
|
||||
RuntimeScriptValue Sc_Button_GetText(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_POBJ(GUIButton, Button_GetText, char);
|
||||
}
|
||||
|
||||
// void | GUIButton *butt, const char *newtx
|
||||
RuntimeScriptValue Sc_Button_SetText(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_POBJ(GUIButton, Button_SetText, const char);
|
||||
}
|
||||
|
||||
// void | GUIButton *butt, int newFont
|
||||
RuntimeScriptValue Sc_Button_SetFont(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetFont);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetFont(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetFont);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetClipImage(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetClipImage);
|
||||
}
|
||||
|
||||
// void | GUIButton *butt, int newval
|
||||
RuntimeScriptValue Sc_Button_SetClipImage(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetClipImage);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetGraphic);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetMouseOverGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetMouseOverGraphic);
|
||||
}
|
||||
|
||||
// void | GUIButton *guil, int slotn
|
||||
RuntimeScriptValue Sc_Button_SetMouseOverGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetMouseOverGraphic);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetNormalGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetNormalGraphic);
|
||||
}
|
||||
|
||||
// void | GUIButton *guil, int slotn
|
||||
RuntimeScriptValue Sc_Button_SetNormalGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetNormalGraphic);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetPushedGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetPushedGraphic);
|
||||
}
|
||||
|
||||
// void | GUIButton *guil, int slotn
|
||||
RuntimeScriptValue Sc_Button_SetPushedGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetPushedGraphic);
|
||||
}
|
||||
|
||||
// int | GUIButton *butt
|
||||
RuntimeScriptValue Sc_Button_GetTextColor(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetTextColor);
|
||||
}
|
||||
|
||||
// void | GUIButton *butt, int newcol
|
||||
RuntimeScriptValue Sc_Button_SetTextColor(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetTextColor);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_Click(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_Click);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_IsAnimating(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_BOOL(GUIButton, Button_IsAnimating);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetTextAlignment(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetTextAlignment);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_SetTextAlignment(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(GUIButton, Button_SetTextAlignment);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetAnimFrame(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimFrame);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetAnimLoop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimLoop);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetAnimView(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimView);
|
||||
}
|
||||
|
||||
void RegisterButtonAPI() {
|
||||
ScFnRegister button_api[] = {
|
||||
{"Button::Animate^4", API_FN_PAIR(Button_Animate4)},
|
||||
{"Button::Animate^7", API_FN_PAIR(Button_Animate7)},
|
||||
{"Button::Animate^8", API_FN_PAIR(Button_Animate)},
|
||||
{"Button::Click^1", API_FN_PAIR(Button_Click)},
|
||||
{"Button::GetText^1", API_FN_PAIR(Button_GetText)},
|
||||
{"Button::SetText^1", API_FN_PAIR(Button_SetText)},
|
||||
{"Button::get_TextAlignment", API_FN_PAIR(Button_GetTextAlignment)},
|
||||
{"Button::set_TextAlignment", API_FN_PAIR(Button_SetTextAlignment)},
|
||||
{"Button::get_Animating", API_FN_PAIR(Button_IsAnimating)},
|
||||
{"Button::get_ClipImage", API_FN_PAIR(Button_GetClipImage)},
|
||||
{"Button::set_ClipImage", API_FN_PAIR(Button_SetClipImage)},
|
||||
{"Button::get_Font", API_FN_PAIR(Button_GetFont)},
|
||||
{"Button::set_Font", API_FN_PAIR(Button_SetFont)},
|
||||
{"Button::get_Frame", API_FN_PAIR(Button_GetAnimFrame)},
|
||||
{"Button::get_Graphic", API_FN_PAIR(Button_GetGraphic)},
|
||||
{"Button::get_Loop", API_FN_PAIR(Button_GetAnimLoop)},
|
||||
{"Button::get_MouseOverGraphic", API_FN_PAIR(Button_GetMouseOverGraphic)},
|
||||
{"Button::set_MouseOverGraphic", API_FN_PAIR(Button_SetMouseOverGraphic)},
|
||||
{"Button::get_NormalGraphic", API_FN_PAIR(Button_GetNormalGraphic)},
|
||||
{"Button::set_NormalGraphic", API_FN_PAIR(Button_SetNormalGraphic)},
|
||||
{"Button::get_PushedGraphic", API_FN_PAIR(Button_GetPushedGraphic)},
|
||||
{"Button::set_PushedGraphic", API_FN_PAIR(Button_SetPushedGraphic)},
|
||||
{"Button::get_Text", API_FN_PAIR(Button_GetText_New)},
|
||||
{"Button::set_Text", API_FN_PAIR(Button_SetText)},
|
||||
{"Button::get_TextColor", API_FN_PAIR(Button_GetTextColor)},
|
||||
{"Button::set_TextColor", API_FN_PAIR(Button_SetTextColor)},
|
||||
{"Button::get_View", API_FN_PAIR(Button_GetAnimView)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(button_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
64
engines/ags/engine/ac/button.h
Normal file
64
engines/ags/engine/ac/button.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_BUTTON_H
|
||||
#define AGS_ENGINE_AC_BUTTON_H
|
||||
|
||||
#include "ags/globals.h"
|
||||
#include "ags/shared/gui/gui_button.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using AGS::Shared::GUIButton;
|
||||
struct AnimatingGUIButton;
|
||||
|
||||
void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat, int blocking, int direction, int sframe = 0, int volume = 100);
|
||||
void Button_Animate4(GUIButton *butt, int view, int loop, int speed, int repeat);
|
||||
const char *Button_GetText_New(GUIButton *butt);
|
||||
void Button_GetText(GUIButton *butt, char *buffer);
|
||||
void Button_SetText(GUIButton *butt, const char *newtx);
|
||||
void Button_SetFont(GUIButton *butt, int newFont);
|
||||
int Button_GetFont(GUIButton *butt);
|
||||
int Button_GetClipImage(GUIButton *butt);
|
||||
void Button_SetClipImage(GUIButton *butt, int newval);
|
||||
int Button_GetGraphic(GUIButton *butt);
|
||||
int Button_GetMouseOverGraphic(GUIButton *butt);
|
||||
void Button_SetMouseOverGraphic(GUIButton *guil, int slotn);
|
||||
int Button_GetNormalGraphic(GUIButton *butt);
|
||||
void Button_SetNormalGraphic(GUIButton *guil, int slotn);
|
||||
int Button_GetPushedGraphic(GUIButton *butt);
|
||||
void Button_SetPushedGraphic(GUIButton *guil, int slotn);
|
||||
int Button_GetTextColor(GUIButton *butt);
|
||||
void Button_SetTextColor(GUIButton *butt, int newcol);
|
||||
|
||||
// Update button's animation, returns whether the animation continues
|
||||
bool UpdateAnimatingButton(int bu);
|
||||
size_t GetAnimatingButtonCount();
|
||||
AnimatingGUIButton *GetAnimatingButtonByIndex(int idxn);
|
||||
void AddButtonAnimation(const AnimatingGUIButton &abtn);
|
||||
void StopButtonAnimation(int idxn);
|
||||
int FindButtonAnimation(int guin, int objn);
|
||||
void FindAndRemoveButtonAnimation(int guin, int objn);
|
||||
void RemoveAllButtonAnimations();
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
44
engines/ags/engine/ac/cd_audio.cpp
Normal file
44
engines/ags/engine/ac/cd_audio.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/cd_audio.h"
|
||||
#include "ags/engine/platform/base/ags_platform_driver.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int init_cd_player() {
|
||||
_G(use_cdplayer) = 0;
|
||||
return _G(platform)->InitializeCDPlayer();
|
||||
}
|
||||
|
||||
int cd_manager(int cmdd, int datt) {
|
||||
if (!_G(triedToUseCdAudioCommand)) {
|
||||
_G(triedToUseCdAudioCommand) = true;
|
||||
init_cd_player();
|
||||
}
|
||||
if (cmdd == 0) return _G(use_cdplayer);
|
||||
if (_G(use_cdplayer) == 0) return 0; // ignore other commands
|
||||
|
||||
return _G(platform)->CDPlayerCommand(cmdd, datt);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
39
engines/ags/engine/ac/cd_audio.h
Normal file
39
engines/ags/engine/ac/cd_audio.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_CDAUDIO_H
|
||||
#define AGS_ENGINE_AC_CDAUDIO_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// CD Player functions
|
||||
// flags returned with cd_getstatus
|
||||
#define CDS_DRIVEOPEN 0x0001 // tray is open
|
||||
#define CDS_DRIVELOCKED 0x0002 // tray locked shut by software
|
||||
#define CDS_AUDIOSUPPORT 0x0010 // supports audio CDs
|
||||
#define CDS_DRIVEEMPTY 0x0800 // no CD in drive
|
||||
|
||||
int init_cd_player();
|
||||
int cd_manager(int cmdd, int datt);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
3836
engines/ags/engine/ac/character.cpp
Normal file
3836
engines/ags/engine/ac/character.cpp
Normal file
File diff suppressed because it is too large
Load Diff
247
engines/ags/engine/ac/character.h
Normal file
247
engines/ags/engine/ac/character.h
Normal file
@@ -0,0 +1,247 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_CHARACTER_H
|
||||
#define AGS_ENGINE_AC_CHARACTER_H
|
||||
|
||||
#include "ags/shared/ac/character_info.h"
|
||||
#include "ags/engine/ac/character_extras.h"
|
||||
#include "ags/engine/ac/dynobj/script_object.h"
|
||||
#include "ags/engine/ac/dynobj/script_inv_item.h"
|
||||
#include "ags/engine/ac/dynobj/script_overlay.h"
|
||||
#include "ags/engine/game/viewport.h"
|
||||
#include "ags/shared/util/geometry.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// **** CHARACTER: FUNCTIONS ****
|
||||
|
||||
bool is_valid_character(int char_id);
|
||||
// Asserts the character ID is valid,
|
||||
// if not then prints a warning to the log; returns assertion result
|
||||
bool AssertCharacter(const char *apiname, int char_id);
|
||||
|
||||
void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addIndex);
|
||||
void Character_AddWaypoint(CharacterInfo *chaa, int x, int y);
|
||||
void Character_Animate(CharacterInfo *chaa, int loop, int delay, int repeat, int blocking, int direction, int sframe = 0, int volume = 100);
|
||||
void Character_Animate5(CharacterInfo *chaa, int loop, int delay, int repeat, int blocking, int direction);
|
||||
void Character_ChangeRoomAutoPosition(CharacterInfo *chaa, int room, int newPos);
|
||||
void Character_ChangeRoom(CharacterInfo *chaa, int room, int x, int y);
|
||||
void Character_ChangeRoomSetLoop(CharacterInfo *chaa, int room, int x, int y, int direction);
|
||||
void Character_ChangeView(CharacterInfo *chap, int vii);
|
||||
void Character_FaceDirection(CharacterInfo *char1, int direction, int blockingStyle);
|
||||
void Character_FaceCharacter(CharacterInfo *char1, CharacterInfo *char2, int blockingStyle);
|
||||
void Character_FaceLocation(CharacterInfo *char1, int xx, int yy, int blockingStyle);
|
||||
void Character_FaceObject(CharacterInfo *char1, ScriptObject *obj, int blockingStyle);
|
||||
void Character_FollowCharacter(CharacterInfo *chaa, CharacterInfo *tofollow, int distaway, int eagerness);
|
||||
int Character_IsCollidingWithChar(CharacterInfo *char1, CharacterInfo *char2);
|
||||
int Character_IsCollidingWithObject(CharacterInfo *chin, ScriptObject *objid);
|
||||
bool Character_IsInteractionAvailable(CharacterInfo *cchar, int mood);
|
||||
void Character_LockView(CharacterInfo *chap, int vii);
|
||||
void Character_LockViewEx(CharacterInfo *chap, int vii, int stopMoving);
|
||||
void Character_LockViewAligned(CharacterInfo *chap, int vii, int loop, int align);
|
||||
void Character_LockViewAligned_Old(CharacterInfo *chap, int vii, int loop, int align);
|
||||
void Character_LockViewAlignedEx(CharacterInfo *chap, int vii, int loop, int align, int stopMoving);
|
||||
void Character_LockViewAlignedEx_Old(CharacterInfo *chap, int vii, int loop, int align, int stopMoving);
|
||||
void Character_LockViewFrame(CharacterInfo *chaa, int view, int loop, int frame);
|
||||
void Character_LockViewFrameEx(CharacterInfo *chaa, int view, int loop, int frame, int stopMoving);
|
||||
void Character_LockViewOffset(CharacterInfo *chap, int vii, int xoffs, int yoffs);
|
||||
void Character_LockViewOffsetEx(CharacterInfo *chap, int vii, int xoffs, int yoffs, int stopMoving);
|
||||
void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi);
|
||||
void Character_PlaceOnWalkableArea(CharacterInfo *chap);
|
||||
void Character_RemoveTint(CharacterInfo *chaa);
|
||||
int Character_GetHasExplicitTint(CharacterInfo *chaa);
|
||||
int Character_GetHasExplicitTint_Old(CharacterInfo *ch);
|
||||
void Character_Say(CharacterInfo *chaa, const char *text);
|
||||
void Character_SayAt(CharacterInfo *chaa, int x, int y, int width, const char *texx);
|
||||
ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx);
|
||||
void Character_SetAsPlayer(CharacterInfo *chaa);
|
||||
void Character_SetIdleView(CharacterInfo *chaa, int iview, int itime);
|
||||
void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno);
|
||||
bool Character_SetProperty(CharacterInfo *chaa, const char *property, int value);
|
||||
bool Character_SetTextProperty(CharacterInfo *chaa, const char *property, const char *value);
|
||||
void Character_SetSpeed(CharacterInfo *chaa, int xspeed, int yspeed);
|
||||
void Character_StopMoving(CharacterInfo *charp);
|
||||
void Character_Tint(CharacterInfo *chaa, int red, int green, int blue, int opacity, int luminance);
|
||||
void Character_Think(CharacterInfo *chaa, const char *text);
|
||||
void Character_UnlockView(CharacterInfo *chaa);
|
||||
void Character_UnlockViewEx(CharacterInfo *chaa, int stopMoving);
|
||||
void Character_Walk(CharacterInfo *chaa, int x, int y, int blocking, int direct);
|
||||
void Character_Move(CharacterInfo *chaa, int x, int y, int blocking, int direct);
|
||||
void Character_WalkStraight(CharacterInfo *chaa, int xx, int yy, int blocking);
|
||||
|
||||
void Character_RunInteraction(CharacterInfo *chaa, int mood);
|
||||
|
||||
// **** CHARACTER: PROPERTIES ****
|
||||
|
||||
int Character_GetProperty(CharacterInfo *chaa, const char *property);
|
||||
void Character_GetPropertyText(CharacterInfo *chaa, const char *property, char *bufer);
|
||||
const char *Character_GetTextProperty(CharacterInfo *chaa, const char *property);
|
||||
|
||||
ScriptInvItem *Character_GetActiveInventory(CharacterInfo *chaa);
|
||||
void Character_SetActiveInventory(CharacterInfo *chaa, ScriptInvItem *iit);
|
||||
int Character_GetAnimating(CharacterInfo *chaa);
|
||||
int Character_GetAnimationSpeed(CharacterInfo *chaa);
|
||||
void Character_SetAnimationSpeed(CharacterInfo *chaa, int newval);
|
||||
int Character_GetBaseline(CharacterInfo *chaa);
|
||||
void Character_SetBaseline(CharacterInfo *chaa, int basel);
|
||||
int Character_GetBlinkInterval(CharacterInfo *chaa);
|
||||
void Character_SetBlinkInterval(CharacterInfo *chaa, int interval);
|
||||
int Character_GetBlinkView(CharacterInfo *chaa);
|
||||
void Character_SetBlinkView(CharacterInfo *chaa, int vii);
|
||||
int Character_GetBlinkWhileThinking(CharacterInfo *chaa);
|
||||
void Character_SetBlinkWhileThinking(CharacterInfo *chaa, int yesOrNo);
|
||||
int Character_GetBlockingHeight(CharacterInfo *chaa);
|
||||
void Character_SetBlockingHeight(CharacterInfo *chaa, int hit);
|
||||
int Character_GetBlockingWidth(CharacterInfo *chaa);
|
||||
void Character_SetBlockingWidth(CharacterInfo *chaa, int wid);
|
||||
int Character_GetDiagonalWalking(CharacterInfo *chaa);
|
||||
void Character_SetDiagonalWalking(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetClickable(CharacterInfo *chaa);
|
||||
void Character_SetClickable(CharacterInfo *chaa, int clik);
|
||||
int Character_GetDestinationX(CharacterInfo *chaa);
|
||||
int Character_GetDestinationY(CharacterInfo *chaa);
|
||||
int Character_GetID(CharacterInfo *chaa);
|
||||
int Character_GetFrame(CharacterInfo *chaa);
|
||||
void Character_SetFrame(CharacterInfo *chaa, int newval);
|
||||
int Character_GetIdleView(CharacterInfo *chaa);
|
||||
int Character_GetIInventoryQuantity(CharacterInfo *chaa, int index);
|
||||
int Character_HasInventory(CharacterInfo *chaa, ScriptInvItem *invi);
|
||||
void Character_SetIInventoryQuantity(CharacterInfo *chaa, int index, int quant);
|
||||
int Character_GetIgnoreLighting(CharacterInfo *chaa);
|
||||
void Character_SetIgnoreLighting(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetIgnoreScaling(CharacterInfo *chaa);
|
||||
void Character_SetIgnoreScaling(CharacterInfo *chaa, int yesorno);
|
||||
void Character_SetManualScaling(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetIgnoreWalkbehinds(CharacterInfo *chaa);
|
||||
void Character_SetIgnoreWalkbehinds(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetMovementLinkedToAnimation(CharacterInfo *chaa);
|
||||
void Character_SetMovementLinkedToAnimation(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetLoop(CharacterInfo *chaa);
|
||||
void Character_SetLoop(CharacterInfo *chaa, int newval);
|
||||
int Character_GetMoving(CharacterInfo *chaa);
|
||||
const char *Character_GetName(CharacterInfo *chaa);
|
||||
void Character_SetName(CharacterInfo *chaa, const char *newName);
|
||||
int Character_GetNormalView(CharacterInfo *chaa);
|
||||
int Character_GetPreviousRoom(CharacterInfo *chaa);
|
||||
int Character_GetRoom(CharacterInfo *chaa);
|
||||
int Character_GetScaleMoveSpeed(CharacterInfo *chaa);
|
||||
void Character_SetScaleMoveSpeed(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetScaleVolume(CharacterInfo *chaa);
|
||||
void Character_SetScaleVolume(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetScaling(CharacterInfo *chaa);
|
||||
void Character_SetScaling(CharacterInfo *chaa, int zoomlevel);
|
||||
int Character_GetSolid(CharacterInfo *chaa);
|
||||
void Character_SetSolid(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetSpeaking(CharacterInfo *chaa);
|
||||
int Character_GetSpeechColor(CharacterInfo *chaa);
|
||||
void Character_SetSpeechColor(CharacterInfo *chaa, int ncol);
|
||||
void Character_SetSpeechAnimationDelay(CharacterInfo *chaa, int newDelay);
|
||||
int Character_GetSpeechView(CharacterInfo *chaa);
|
||||
void Character_SetSpeechView(CharacterInfo *chaa, int vii);
|
||||
int Character_GetThinkView(CharacterInfo *chaa);
|
||||
void Character_SetThinkView(CharacterInfo *chaa, int vii);
|
||||
int Character_GetTransparency(CharacterInfo *chaa);
|
||||
void Character_SetTransparency(CharacterInfo *chaa, int trans);
|
||||
int Character_GetTurnBeforeWalking(CharacterInfo *chaa);
|
||||
void Character_SetTurnBeforeWalking(CharacterInfo *chaa, int yesorno);
|
||||
int Character_GetView(CharacterInfo *chaa);
|
||||
int Character_GetWalkSpeedX(CharacterInfo *chaa);
|
||||
int Character_GetWalkSpeedY(CharacterInfo *chaa);
|
||||
int Character_GetX(CharacterInfo *chaa);
|
||||
void Character_SetX(CharacterInfo *chaa, int newval);
|
||||
int Character_GetY(CharacterInfo *chaa);
|
||||
void Character_SetY(CharacterInfo *chaa, int newval);
|
||||
int Character_GetZ(CharacterInfo *chaa);
|
||||
void Character_SetZ(CharacterInfo *chaa, int newval);
|
||||
int Character_GetSpeakingFrame(CharacterInfo *chaa);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
struct MoveList;
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Bitmap;
|
||||
}
|
||||
}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
// Configures and starts character animation.
|
||||
void animate_character(CharacterInfo *chap, int loopn, int sppd, int rept, int direction = 0, int sframe = 0, int volume = 100);
|
||||
// Clears up animation parameters
|
||||
void stop_character_anim(CharacterInfo *chap);
|
||||
void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims);
|
||||
int find_looporder_index(int curloop);
|
||||
// returns 0 to use diagonal, 1 to not
|
||||
int useDiagonal(CharacterInfo *char1);
|
||||
// returns 1 normally, or 0 if they only have horizontal animations
|
||||
int hasUpDownLoops(CharacterInfo *char1);
|
||||
void start_character_turning(CharacterInfo *chinf, int useloop, int no_diagonal);
|
||||
void fix_player_sprite(MoveList *cmls, CharacterInfo *chinf);
|
||||
// Check whether two characters have walked into each other
|
||||
int has_hit_another_character(int sourceChar);
|
||||
int doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *chex);
|
||||
// Tells if character is currently moving, in eWalkableAreas mode
|
||||
bool is_char_walking_ndirect(CharacterInfo *chi);
|
||||
int find_nearest_walkable_area_within(int *xx, int *yy, int range, int step);
|
||||
void find_nearest_walkable_area(int *xx, int *yy);
|
||||
void FindReasonableLoopForCharacter(CharacterInfo *chap);
|
||||
void walk_or_move_character(CharacterInfo *chaa, int x, int y, int blocking, int direct, bool isWalk);
|
||||
int wantMoveNow(CharacterInfo *chi, CharacterExtras *chex);
|
||||
void setup_player_character(int charid);
|
||||
int GetCharacterFrameVolume(CharacterInfo *chi);
|
||||
Shared::Bitmap *GetCharacterImage(int charid, bool *is_original = nullptr);
|
||||
CharacterInfo *GetCharacterAtScreen(int xx, int yy);
|
||||
// Deduces room object's scale, accounting for both manual scaling and the room region effects;
|
||||
// calculates resulting sprite size.
|
||||
void update_character_scale(int charid);
|
||||
CharacterInfo *GetCharacterAtRoom(int x, int y);
|
||||
// Get character ID at the given room coordinates
|
||||
int is_pos_on_character(int xx, int yy);
|
||||
void get_char_blocking_rect(int charid, int *x1, int *y1, int *width, int *y2);
|
||||
// Check whether the source char is standing inside otherChar's blocking rectangle
|
||||
int is_char_in_blocking_rect(int sourceChar, int otherChar, int *fromxptr, int *cwidptr);
|
||||
int my_getpixel(Shared::Bitmap *blk, int x, int y);
|
||||
int check_click_on_character(int xx, int yy, int mood);
|
||||
void _DisplaySpeechCore(int chid, const char *displbuf);
|
||||
void _DisplayThoughtCore(int chid, const char *displbuf);
|
||||
void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int isThought);
|
||||
int get_character_currently_talking();
|
||||
void DisplaySpeech(const char *texx, int aschar);
|
||||
int update_lip_sync(int talkview, int talkloop, int *talkframeptr);
|
||||
|
||||
// Recalculate dynamic character properties, e.g. after restoring a game save
|
||||
void restore_characters();
|
||||
|
||||
// Calculates character's bounding box in room coordinates (takes only in-room transform into account)
|
||||
// use_frame_0 optionally tells to use frame 0 of current loop instead of current frame.
|
||||
Rect GetCharacterRoomBBox(int charid, bool use_frame_0 = false);
|
||||
// Find a closest viewport given character is to. Checks viewports in their order in game's array,
|
||||
// and returns either first viewport character's bounding box intersects with (or rather with its camera),
|
||||
// or the one that is least far away from its camera; calculated as a perpendicular distance between two AABBs.
|
||||
PViewport FindNearestViewport(int charid);
|
||||
|
||||
// order of loops to turn character in circle from down to down
|
||||
extern int turnlooporder[8];
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
91
engines/ags/engine/ac/character_extras.cpp
Normal file
91
engines/ags/engine/ac/character_extras.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/character_extras.h"
|
||||
#include "ags/engine/ac/view_frame.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int CharacterExtras::GetEffectiveY(CharacterInfo *chi) const {
|
||||
return chi->y - (chi->z * zoom_offs) / 100;
|
||||
}
|
||||
|
||||
int CharacterExtras::GetFrameSoundVolume(CharacterInfo *chi) const {
|
||||
return AGS3::CalcFrameSoundVolume(
|
||||
anim_volume, cur_anim_volume,
|
||||
(chi->flags & CHF_SCALEVOLUME) ? zoom : 100);
|
||||
}
|
||||
|
||||
void CharacterExtras::CheckViewFrame(CharacterInfo *chi) {
|
||||
AGS3::CheckViewFrame(chi->view, chi->loop, chi->frame, GetFrameSoundVolume(chi));
|
||||
}
|
||||
|
||||
void CharacterExtras::ReadFromSavegame(Stream *in, CharacterSvgVersion save_ver) {
|
||||
in->ReadArrayOfInt16(invorder, MAX_INVORDER);
|
||||
invorder_count = in->ReadInt16();
|
||||
width = in->ReadInt16();
|
||||
height = in->ReadInt16();
|
||||
zoom = in->ReadInt16();
|
||||
xwas = in->ReadInt16();
|
||||
ywas = in->ReadInt16();
|
||||
tint_r = in->ReadInt16();
|
||||
tint_g = in->ReadInt16();
|
||||
tint_b = in->ReadInt16();
|
||||
tint_level = in->ReadInt16();
|
||||
tint_light = in->ReadInt16();
|
||||
process_idle_this_time = in->ReadInt8();
|
||||
slow_move_counter = in->ReadInt8();
|
||||
animwait = in->ReadInt16();
|
||||
if (save_ver >= kCharSvgVersion_36025) {
|
||||
anim_volume = static_cast<uint8_t>(in->ReadInt8());
|
||||
cur_anim_volume = static_cast<uint8_t>(in->ReadInt8());
|
||||
in->ReadInt8(); // reserved to fill int32
|
||||
in->ReadInt8();
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterExtras::WriteToSavegame(Stream *out) const {
|
||||
out->WriteArrayOfInt16(invorder, MAX_INVORDER);
|
||||
out->WriteInt16(invorder_count);
|
||||
out->WriteInt16(width);
|
||||
out->WriteInt16(height);
|
||||
out->WriteInt16(zoom);
|
||||
out->WriteInt16(xwas);
|
||||
out->WriteInt16(ywas);
|
||||
out->WriteInt16(tint_r);
|
||||
out->WriteInt16(tint_g);
|
||||
out->WriteInt16(tint_b);
|
||||
out->WriteInt16(tint_level);
|
||||
out->WriteInt16(tint_light);
|
||||
out->WriteInt8(process_idle_this_time);
|
||||
out->WriteInt8(slow_move_counter);
|
||||
out->WriteInt16(animwait);
|
||||
out->WriteInt8(static_cast<uint8_t>(anim_volume));
|
||||
out->WriteInt8(static_cast<uint8_t>(cur_anim_volume));
|
||||
out->WriteInt8(0); // reserved to fill int32
|
||||
out->WriteInt8(0);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
95
engines/ags/engine/ac/character_extras.h
Normal file
95
engines/ags/engine/ac/character_extras.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
//=============================================================================
|
||||
//
|
||||
// CharacterExtras is a separate runtime character data. Historically it was
|
||||
// separated from the design-time CharacterInfo, because the latter is exposed
|
||||
// to script API and plugin API in such way that its memory layout could not
|
||||
// be changed at all. Although, today this is less of an issue (see comment
|
||||
// to CharacterInfo).
|
||||
//
|
||||
// TODO: in the long run it will be beneficial to remake this into a more
|
||||
// explicit runtime Character class, while perhaps keeping CharacterInfo only
|
||||
// to load design-time data.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_CHARACTER_EXTRAS_H
|
||||
#define AGS_ENGINE_AC_CHARACTER_EXTRAS_H
|
||||
|
||||
#include "ags/shared/ac/character_info.h"
|
||||
#include "ags/engine/ac/runtime_defines.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
}
|
||||
}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
// The CharacterInfo struct size is fixed because it's exposed to script
|
||||
// and plugin API, therefore new stuff has to go here
|
||||
struct CharacterExtras {
|
||||
short invorder[MAX_INVORDER] = {};
|
||||
short invorder_count = 0;
|
||||
// TODO: implement full AABB and keep updated, so that engine could rely on these cached values all time = 0;
|
||||
// TODO: consider having both fixed AABB and volatile one that changes with animation frame (unless you change how anims work)
|
||||
short width = 0;
|
||||
short height = 0;
|
||||
short zoom = 100;
|
||||
short xwas = 0;
|
||||
short ywas = 0;
|
||||
short tint_r = 0;
|
||||
short tint_g = 0;
|
||||
short tint_b = 0;
|
||||
short tint_level = 0;
|
||||
short tint_light = 0;
|
||||
int8 process_idle_this_time = 0;
|
||||
int8 slow_move_counter = 0;
|
||||
short animwait = 0;
|
||||
int anim_volume = 100; // default animation volume (relative factor)
|
||||
int cur_anim_volume = 100; // current animation sound volume (relative factor)
|
||||
|
||||
// Following fields are deriatives of the above (calculated from these
|
||||
// and other factors), and hence are not serialized.
|
||||
//
|
||||
// zoom factor of sprite offsets, fixed at 100 in backwards compatible mode
|
||||
int zoom_offs = 100;
|
||||
|
||||
int GetEffectiveY(CharacterInfo *chi) const; // return Y - Z
|
||||
|
||||
// Calculate wanted frame sound volume based on multiple factors
|
||||
int GetFrameSoundVolume(CharacterInfo *chi) const;
|
||||
// Process the current animation frame for the character:
|
||||
// play linked sounds, and so forth.
|
||||
void CheckViewFrame(CharacterInfo *chi);
|
||||
|
||||
// Read character extra data from saves.
|
||||
void ReadFromSavegame(Shared::Stream *in, CharacterSvgVersion save_ver);
|
||||
void WriteToSavegame(Shared::Stream *out) const;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
468
engines/ags/engine/ac/character_info_engine.cpp
Normal file
468
engines/ags/engine/ac/character_info_engine.cpp
Normal file
@@ -0,0 +1,468 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/character_info.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/character.h"
|
||||
#include "ags/engine/ac/character_extras.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/engine/ac/global_character.h"
|
||||
#include "ags/engine/ac/global_game.h"
|
||||
#include "ags/engine/ac/math.h"
|
||||
#include "ags/engine/ac/object.h"
|
||||
#include "ags/engine/ac/view_frame.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/engine/main/update.h"
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/ags.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
#define Random __Rand
|
||||
|
||||
int CharacterInfo::get_baseline() const {
|
||||
if (baseline < 1)
|
||||
return y;
|
||||
return baseline;
|
||||
}
|
||||
|
||||
int CharacterInfo::get_blocking_top() const {
|
||||
if (blocking_height > 0)
|
||||
return y - blocking_height / 2;
|
||||
return y - 2;
|
||||
}
|
||||
|
||||
int CharacterInfo::get_blocking_bottom() const {
|
||||
// the blocking_bottom should be 1 less than the top + height
|
||||
// since the code does <= checks on it rather than < checks
|
||||
if (blocking_height > 0)
|
||||
return (y + (blocking_height + 1) / 2) - 1;
|
||||
return y + 3;
|
||||
}
|
||||
|
||||
void CharacterInfo::FixupCurrentLoopAndFrame() {
|
||||
// If current loop property exceeds number of loops,
|
||||
// or if selected loop has no frames, then try select any first loop that has frames.
|
||||
// NOTE: although this may seem like a weird solution to a problem,
|
||||
// we do so for backwards compatibility; this approximately emulates older games behavior.
|
||||
|
||||
if (view >= 0 &&
|
||||
(loop >= _GP(views)[view].numLoops || _GP(views)[view].loops[loop].numFrames == 0)) {
|
||||
for (loop = 0;
|
||||
(loop < _GP(views)[view].numLoops) && (_GP(views)[view].loops[loop].numFrames == 0); ++loop) {
|
||||
}
|
||||
if (loop == _GP(views)[view].numLoops) {
|
||||
// view has no frames?!
|
||||
// amazingly enough there are old games that allow this to happen...
|
||||
if (_G(loaded_game_file_version) >= kGameVersion_300)
|
||||
quitprintf("!Character %s is assigned view %d that has no frames!", scrname, view);
|
||||
loop = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If the last saved frame exceeds a new loop, then switch to frame 1
|
||||
// (first walking frame) if walking, or frame 0 otherwise or if there's less than 2 frames.
|
||||
int frames_in_loop = _GP(views)[view].loops[loop].numFrames;
|
||||
if (frame >= frames_in_loop) {
|
||||
frame = (walking > 0 && frames_in_loop > 1) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterInfo::UpdateMoveAndAnim(int &char_index, CharacterExtras *chex, std::vector<int> &followingAsSheep) {
|
||||
int res;
|
||||
|
||||
if (on != 1)
|
||||
return;
|
||||
|
||||
// Turn around during walk
|
||||
res = update_character_walkturning(chex);
|
||||
// Fixup character's loop prior to any further logic updates
|
||||
FixupCurrentLoopAndFrame();
|
||||
|
||||
// FIXME: refactor this nonsense!
|
||||
// [IKM] Yes, it should return! upon getting RETURN_CONTINUE here
|
||||
if (res == RETURN_CONTINUE) { // [IKM] now, this is one of those places...
|
||||
return; // must be careful not to screw things up
|
||||
}
|
||||
|
||||
int doing_nothing = 1;
|
||||
update_character_moving(char_index, chex, doing_nothing);
|
||||
|
||||
// [IKM] 2012-06-28:
|
||||
// Character index value is used to set up some variables in there, so I cannot just cease using it
|
||||
res = update_character_animating(char_index, doing_nothing);
|
||||
// [IKM] Yes, it should return! upon getting RETURN_CONTINUE here
|
||||
if (res == RETURN_CONTINUE) { // [IKM] now, this is one of those places...
|
||||
return; // must be careful not to screw things up
|
||||
}
|
||||
|
||||
update_character_follower(char_index, followingAsSheep, doing_nothing);
|
||||
|
||||
update_character_idle(chex, doing_nothing);
|
||||
|
||||
chex->process_idle_this_time = 0;
|
||||
}
|
||||
|
||||
void CharacterInfo::UpdateFollowingExactlyCharacter() {
|
||||
x = _GP(game).chars[following].x;
|
||||
y = _GP(game).chars[following].y;
|
||||
z = _GP(game).chars[following].z;
|
||||
room = _GP(game).chars[following].room;
|
||||
prevroom = _GP(game).chars[following].prevroom;
|
||||
|
||||
int usebase = _GP(game).chars[following].get_baseline();
|
||||
|
||||
if (flags & CHF_BEHINDSHEPHERD)
|
||||
baseline = usebase - 1;
|
||||
else
|
||||
baseline = usebase + 1;
|
||||
}
|
||||
|
||||
int CharacterInfo::update_character_walkturning(CharacterExtras *chex) {
|
||||
if (walking >= TURNING_AROUND) {
|
||||
// Currently rotating to correct direction
|
||||
if (walkwait > 0) walkwait--;
|
||||
else {
|
||||
// Work out which direction is next
|
||||
int wantloop = find_looporder_index(loop) + 1;
|
||||
// going anti-clockwise, take one before instead
|
||||
if (walking >= TURNING_BACKWARDS)
|
||||
wantloop -= 2;
|
||||
while (1) {
|
||||
if (wantloop >= 8)
|
||||
wantloop = 0;
|
||||
if (wantloop < 0)
|
||||
wantloop = 7;
|
||||
if ((turnlooporder[wantloop] >= _GP(views)[view].numLoops) ||
|
||||
(_GP(views)[view].loops[turnlooporder[wantloop]].numFrames < 1) ||
|
||||
((turnlooporder[wantloop] >= 4) && ((flags & CHF_NODIAGONAL) != 0))) {
|
||||
if (walking >= TURNING_BACKWARDS)
|
||||
wantloop--;
|
||||
else
|
||||
wantloop++;
|
||||
} else break;
|
||||
}
|
||||
loop = turnlooporder[wantloop];
|
||||
walking -= TURNING_AROUND;
|
||||
// if still turning, wait for next frame
|
||||
if (walking % TURNING_BACKWARDS >= TURNING_AROUND)
|
||||
walkwait = animspeed;
|
||||
else
|
||||
walking = walking % TURNING_BACKWARDS;
|
||||
chex->animwait = 0;
|
||||
}
|
||||
return RETURN_CONTINUE;
|
||||
//continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CharacterInfo::update_character_moving(int &char_index, CharacterExtras *chex, int &doing_nothing) {
|
||||
if ((walking > 0) && (room == _G(displayed_room))) {
|
||||
if (walkwait > 0) walkwait--;
|
||||
else {
|
||||
flags &= ~CHF_AWAITINGMOVE;
|
||||
|
||||
// Move the character
|
||||
int numSteps = wantMoveNow(this, chex);
|
||||
|
||||
if ((numSteps) && (chex->xwas != INVALID_X)) {
|
||||
// if the zoom level changed mid-move, the walkcounter
|
||||
// might not have come round properly - so sort it out
|
||||
x = chex->xwas;
|
||||
y = chex->ywas;
|
||||
chex->xwas = INVALID_X;
|
||||
}
|
||||
|
||||
int oldxp = x, oldyp = y;
|
||||
|
||||
for (int ff = 0; ff < abs(numSteps); ff++) {
|
||||
if (doNextCharMoveStep(this, char_index, chex))
|
||||
break;
|
||||
if ((walking == 0) || (walking >= TURNING_AROUND))
|
||||
break;
|
||||
}
|
||||
|
||||
if (numSteps < 0) {
|
||||
// very small scaling, intersperse the movement
|
||||
// to stop it being jumpy
|
||||
chex->xwas = x;
|
||||
chex->ywas = y;
|
||||
x = ((x) - oldxp) / 2 + oldxp;
|
||||
y = ((y) - oldyp) / 2 + oldyp;
|
||||
} else if (numSteps > 0)
|
||||
chex->xwas = INVALID_X;
|
||||
|
||||
if ((flags & CHF_ANTIGLIDE) == 0)
|
||||
walkwaitcounter++;
|
||||
}
|
||||
|
||||
// Fixup character's loop, it may be changed when making a walk-move
|
||||
FixupCurrentLoopAndFrame();
|
||||
|
||||
doing_nothing = 0; // still walking?
|
||||
|
||||
if (walking < 1) {
|
||||
// Finished walking, stop and reset state
|
||||
chex->process_idle_this_time = 1;
|
||||
doing_nothing = 1;
|
||||
walkwait = 0;
|
||||
Character_StopMoving(this);
|
||||
if ((flags & CHF_MOVENOTWALK) == 0) {
|
||||
// use standing pic
|
||||
chex->animwait = 0;
|
||||
frame = 0;
|
||||
chex->CheckViewFrame(this);
|
||||
}
|
||||
} else if (chex->animwait > 0) {
|
||||
chex->animwait--;
|
||||
} else {
|
||||
if (flags & CHF_ANTIGLIDE)
|
||||
walkwaitcounter++;
|
||||
|
||||
if ((flags & CHF_MOVENOTWALK) == 0) {
|
||||
frame++;
|
||||
if (frame >= _GP(views)[view].loops[loop].numFrames) {
|
||||
// end of loop, so loop back round skipping the standing frame
|
||||
frame = 1;
|
||||
|
||||
if (_GP(views)[view].loops[loop].numFrames < 2)
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
chex->animwait = _GP(views)[view].loops[loop].frames[frame].speed + animspeed;
|
||||
|
||||
if (flags & CHF_ANTIGLIDE)
|
||||
walkwait = chex->animwait;
|
||||
else
|
||||
walkwait = 0;
|
||||
|
||||
chex->CheckViewFrame(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
|
||||
CharacterExtras *chex = &_GP(charextra)[index_id];
|
||||
|
||||
// not moving, but animating
|
||||
// idleleft is <0 while idle view is playing (.animating is 0)
|
||||
if (((animating != 0) || (idleleft < 0)) &&
|
||||
((walking == 0) || ((flags & CHF_MOVENOTWALK) != 0)) &&
|
||||
(room == _G(displayed_room))) {
|
||||
doing_nothing = 0;
|
||||
// idle anim doesn't count as doing something
|
||||
if (idleleft < 0)
|
||||
doing_nothing = 1;
|
||||
|
||||
if (wait > 0) wait--;
|
||||
else if ((_G(char_speaking) == aa) && (_GP(game).options[OPT_LIPSYNCTEXT] != 0)) {
|
||||
// currently talking with lip-sync speech
|
||||
int fraa = frame;
|
||||
wait = update_lip_sync(view, loop, &fraa) - 1;
|
||||
// closed mouth at end of sentence
|
||||
// NOTE: standard lip-sync is synchronized with text timer, not voice file
|
||||
if (_GP(play).speech_in_post_state ||
|
||||
((_GP(play).messagetime >= 0) && (_GP(play).messagetime < _GP(play).close_mouth_speech_time)))
|
||||
frame = 0;
|
||||
|
||||
if (frame != fraa) {
|
||||
frame = fraa;
|
||||
chex->CheckViewFrame(this);
|
||||
}
|
||||
|
||||
//continue;
|
||||
return RETURN_CONTINUE;
|
||||
} else {
|
||||
// Normal view animation
|
||||
const int oldframe = frame;
|
||||
|
||||
bool done_anim = false;
|
||||
if ((aa == _G(char_speaking)) &&
|
||||
(_GP(play).speech_in_post_state ||
|
||||
((!_GP(play).speech_has_voice) &&
|
||||
(_GP(play).close_mouth_speech_time > 0) &&
|
||||
(_GP(play).messagetime < _GP(play).close_mouth_speech_time)))) {
|
||||
// finished talking - stop animation
|
||||
done_anim = true;
|
||||
frame = 0;
|
||||
} else {
|
||||
if (!CycleViewAnim(view, loop, frame, get_anim_forwards(), get_anim_repeat())) {
|
||||
done_anim = true; // finished animating
|
||||
// end of idle anim
|
||||
if (idleleft < 0) {
|
||||
// constant anim, reset (need this cos animating==0)
|
||||
if (idletime == 0)
|
||||
frame = 0;
|
||||
// one-off anim, stop
|
||||
else {
|
||||
ReleaseCharacterView(aa);
|
||||
idleleft = idletime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait = _GP(views)[view].loops[loop].frames[frame].speed;
|
||||
// idle anim doesn't have speed stored cos animating==0 (TODO: investigate why?)
|
||||
if (idleleft < 0)
|
||||
wait += idle_anim_speed;
|
||||
else
|
||||
wait += get_anim_delay();
|
||||
|
||||
if (frame != oldframe)
|
||||
chex->CheckViewFrame(this);
|
||||
|
||||
if (done_anim)
|
||||
stop_character_anim(this);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CharacterInfo::update_character_follower(int &aa, std::vector<int> &followingAsSheep, int &doing_nothing) {
|
||||
if ((following >= 0) && (followinfo == FOLLOW_ALWAYSONTOP)) {
|
||||
// an always-on-top follow
|
||||
followingAsSheep.push_back(aa);
|
||||
}
|
||||
|
||||
// not moving, but should be following another character
|
||||
else if ((following >= 0) && (doing_nothing == 1)) {
|
||||
short distaway = (followinfo >> 8) & 0x00ff;
|
||||
// no character in this room
|
||||
if ((_GP(game).chars[following].on == 0) || (on == 0));
|
||||
else if (room < 0) {
|
||||
room++;
|
||||
if (room == 0) {
|
||||
// appear in the new room
|
||||
room = _GP(game).chars[following].room;
|
||||
x = _GP(play).entered_at_x;
|
||||
y = _GP(play).entered_at_y;
|
||||
}
|
||||
}
|
||||
// wait a bit, so we're not constantly walking
|
||||
else if (Random(100) < (followinfo & 0x00ff));
|
||||
// the followed character has changed room
|
||||
else if ((room != _GP(game).chars[following].room)
|
||||
&& (_GP(game).chars[following].on == 0))
|
||||
; // do nothing if the player isn't visible
|
||||
else if (room != _GP(game).chars[following].room) {
|
||||
prevroom = room;
|
||||
room = _GP(game).chars[following].room;
|
||||
|
||||
if (room == _G(displayed_room)) {
|
||||
// only move to the room-entered position if coming into
|
||||
// the current room
|
||||
if (_GP(play).entered_at_x > (_GP(thisroom).Width - 8)) {
|
||||
x = _GP(thisroom).Width + 8;
|
||||
y = _GP(play).entered_at_y;
|
||||
} else if (_GP(play).entered_at_x < 8) {
|
||||
x = -8;
|
||||
y = _GP(play).entered_at_y;
|
||||
} else if (_GP(play).entered_at_y > (_GP(thisroom).Height - 8)) {
|
||||
y = _GP(thisroom).Height + 8;
|
||||
x = _GP(play).entered_at_x;
|
||||
} else if (_GP(play).entered_at_y < _GP(thisroom).Edges.Top + 8) {
|
||||
y = _GP(thisroom).Edges.Top + 1;
|
||||
x = _GP(play).entered_at_x;
|
||||
} else {
|
||||
// not at one of the edges
|
||||
// delay for a few seconds to let the player move
|
||||
room = -_GP(play).follow_change_room_timer;
|
||||
}
|
||||
if (room >= 0) {
|
||||
walk_character(aa, _GP(play).entered_at_x, _GP(play).entered_at_y, 1, true);
|
||||
doing_nothing = 0;
|
||||
}
|
||||
}
|
||||
} else if (room != _G(displayed_room)) {
|
||||
// if the character is following another character and
|
||||
// neither is in the current room, don't try to move
|
||||
} else if ((abs(_GP(game).chars[following].x - x) > distaway + 30) ||
|
||||
(abs(_GP(game).chars[following].y - y) > distaway + 30) ||
|
||||
((followinfo & 0x00ff) == 0)) {
|
||||
// in same room
|
||||
int goxoffs = (Random(50) - 25);
|
||||
// make sure he's not standing on top of the other man
|
||||
if (goxoffs < 0) goxoffs -= distaway;
|
||||
else goxoffs += distaway;
|
||||
walk_character(aa, _GP(game).chars[following].x + goxoffs,
|
||||
_GP(game).chars[following].y + (Random(50) - 25), 0, true);
|
||||
doing_nothing = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterInfo::update_character_idle(CharacterExtras *chex, int &doing_nothing) {
|
||||
// no idle animation, so skip this bit
|
||||
if (idleview < 1);
|
||||
// currently playing idle anim
|
||||
else if (idleleft < 0);
|
||||
// not in the current room
|
||||
else if (room != _G(displayed_room));
|
||||
// they are moving or animating (or the view is locked), so
|
||||
// reset idle timeout
|
||||
else if ((doing_nothing == 0) || ((flags & CHF_FIXVIEW) != 0))
|
||||
idleleft = idletime;
|
||||
// count idle time
|
||||
else if ((_G(loopcounter) % GetGameSpeed() == 0) || (chex->process_idle_this_time == 1)) {
|
||||
idleleft--;
|
||||
if (idleleft == -1) {
|
||||
int useloop = loop;
|
||||
debug_script_log("%s: Now idle (view %d)", scrname, idleview + 1);
|
||||
Character_LockView(this, idleview + 1);
|
||||
// SetCharView resets it to 0
|
||||
idleleft = -2;
|
||||
int maxLoops = _GP(views)[idleview].numLoops;
|
||||
// if the char is set to "no diagonal loops", don't try
|
||||
// to use diagonal idle loops either
|
||||
if ((maxLoops > 4) && (useDiagonal(this)))
|
||||
maxLoops = 4;
|
||||
// If it's not a "swimming"-type idleanim, choose a random loop
|
||||
// if there arent enough loops to do the current one.
|
||||
if ((idletime > 0) && (useloop >= maxLoops)) {
|
||||
do {
|
||||
useloop = ::AGS::g_vm->getRandomNumber(maxLoops - 1);
|
||||
// don't select a loop which is a continuation of a previous one
|
||||
} while ((useloop > 0) && (_GP(views)[idleview].loops[useloop - 1].RunNextLoop()));
|
||||
}
|
||||
// Normal idle anim - just reset to loop 0 if not enough to
|
||||
// use the current one
|
||||
else if (useloop >= maxLoops)
|
||||
useloop = 0;
|
||||
|
||||
animate_character(this, useloop, idle_anim_speed, (idletime == 0) ? 1 : 0 /* repeat */);
|
||||
|
||||
// don't set Animating while the idle anim plays (TODO: investigate why?)
|
||||
animating = 0;
|
||||
}
|
||||
} // end do idle animation
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
136
engines/ags/engine/ac/date_time.cpp
Normal file
136
engines/ags/engine/ac/date_time.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/date_time.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/platform/base/ags_platform_driver.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
ScriptDateTime *DateTime_Now_Core() {
|
||||
ScriptDateTime *sdt = new ScriptDateTime();
|
||||
|
||||
_G(platform)->GetSystemTime(sdt);
|
||||
|
||||
return sdt;
|
||||
}
|
||||
|
||||
ScriptDateTime *DateTime_Now() {
|
||||
ScriptDateTime *sdt = DateTime_Now_Core();
|
||||
ccRegisterManagedObject(sdt, sdt);
|
||||
return sdt;
|
||||
}
|
||||
|
||||
int DateTime_GetYear(ScriptDateTime *sdt) {
|
||||
return sdt->year;
|
||||
}
|
||||
|
||||
int DateTime_GetMonth(ScriptDateTime *sdt) {
|
||||
return sdt->month;
|
||||
}
|
||||
|
||||
int DateTime_GetDayOfMonth(ScriptDateTime *sdt) {
|
||||
return sdt->day;
|
||||
}
|
||||
|
||||
int DateTime_GetHour(ScriptDateTime *sdt) {
|
||||
return sdt->hour;
|
||||
}
|
||||
|
||||
int DateTime_GetMinute(ScriptDateTime *sdt) {
|
||||
return sdt->minute;
|
||||
}
|
||||
|
||||
int DateTime_GetSecond(ScriptDateTime *sdt) {
|
||||
return sdt->second;
|
||||
}
|
||||
|
||||
int DateTime_GetRawTime(ScriptDateTime *sdt) {
|
||||
return sdt->rawUnixTime;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// ScriptDateTime* ()
|
||||
RuntimeScriptValue Sc_DateTime_Now(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO(ScriptDateTime, DateTime_Now);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetYear(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetYear);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetMonth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetMonth);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetDayOfMonth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetDayOfMonth);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetHour(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetHour);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetMinute(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetMinute);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetSecond(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetSecond);
|
||||
}
|
||||
|
||||
// int (ScriptDateTime *sdt)
|
||||
RuntimeScriptValue Sc_DateTime_GetRawTime(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDateTime, DateTime_GetRawTime);
|
||||
}
|
||||
|
||||
void RegisterDateTimeAPI() {
|
||||
ScFnRegister datetime_api[] = {
|
||||
{"DateTime::get_Now", API_FN_PAIR(DateTime_Now)},
|
||||
|
||||
{"DateTime::get_DayOfMonth", API_FN_PAIR(DateTime_GetDayOfMonth)},
|
||||
{"DateTime::get_Hour", API_FN_PAIR(DateTime_GetHour)},
|
||||
{"DateTime::get_Minute", API_FN_PAIR(DateTime_GetMinute)},
|
||||
{"DateTime::get_Month", API_FN_PAIR(DateTime_GetMonth)},
|
||||
{"DateTime::get_RawTime", API_FN_PAIR(DateTime_GetRawTime)},
|
||||
{"DateTime::get_Second", API_FN_PAIR(DateTime_GetSecond)},
|
||||
{"DateTime::get_Year", API_FN_PAIR(DateTime_GetYear)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(datetime_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
41
engines/ags/engine/ac/date_time.h
Normal file
41
engines/ags/engine/ac/date_time.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DATETIME_H
|
||||
#define AGS_ENGINE_AC_DATETIME_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_date_time.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
ScriptDateTime *DateTime_Now_Core();
|
||||
ScriptDateTime *DateTime_Now();
|
||||
int DateTime_GetYear(ScriptDateTime *sdt);
|
||||
int DateTime_GetMonth(ScriptDateTime *sdt);
|
||||
int DateTime_GetDayOfMonth(ScriptDateTime *sdt);
|
||||
int DateTime_GetHour(ScriptDateTime *sdt);
|
||||
int DateTime_GetMinute(ScriptDateTime *sdt);
|
||||
int DateTime_GetSecond(ScriptDateTime *sdt);
|
||||
int DateTime_GetRawTime(ScriptDateTime *sdt);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
1271
engines/ags/engine/ac/dialog.cpp
Normal file
1271
engines/ags/engine/ac/dialog.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
engines/ags/engine/ac/dialog.h
Normal file
46
engines/ags/engine/ac/dialog.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DIALOG_H
|
||||
#define AGS_ENGINE_AC_DIALOG_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/ac/dialog_topic.h"
|
||||
#include "ags/engine/ac/dynobj/script_dialog.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int Dialog_GetID(ScriptDialog *sd);
|
||||
int Dialog_GetOptionCount(ScriptDialog *sd);
|
||||
int Dialog_GetShowTextParser(ScriptDialog *sd);
|
||||
const char *Dialog_GetOptionText(ScriptDialog *sd, int option);
|
||||
int Dialog_DisplayOptions(ScriptDialog *sd, int sayChosenOption);
|
||||
int Dialog_GetOptionState(ScriptDialog *sd, int option);
|
||||
int Dialog_HasOptionBeenChosen(ScriptDialog *sd, int option);
|
||||
void Dialog_SetOptionState(ScriptDialog *sd, int option, int newState);
|
||||
void Dialog_Start(ScriptDialog *sd);
|
||||
|
||||
void do_conversation(int dlgnum);
|
||||
int show_dialog_options(int dlgnum, int sayChosenOption, bool runGameLoopsInBackground);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
277
engines/ags/engine/ac/dialog_options_rendering.cpp
Normal file
277
engines/ags/engine/ac/dialog_options_rendering.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dialog.h"
|
||||
#include "ags/shared/ac/dialog_topic.h"
|
||||
#include "ags/engine/ac/dialog_options_rendering.h"
|
||||
#include "ags/shared/ac/game_struct_defines.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/engine/ac/dynobj/cc_dialog.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// ** SCRIPT DIALOGOPTIONSRENDERING OBJECT
|
||||
|
||||
void DialogOptionsRendering_Update(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
dlgOptRender->needRepaint = true;
|
||||
}
|
||||
|
||||
bool DialogOptionsRendering_RunActiveOption(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
dlgOptRender->chosenOptionID = dlgOptRender->activeOptionID;
|
||||
return dlgOptRender->chosenOptionID >= 0;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetX(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->x;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetX(ScriptDialogOptionsRendering *dlgOptRender, int newX) {
|
||||
dlgOptRender->x = newX;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetY(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->y;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetY(ScriptDialogOptionsRendering *dlgOptRender, int newY) {
|
||||
dlgOptRender->y = newY;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetWidth(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->width;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetWidth(ScriptDialogOptionsRendering *dlgOptRender, int newWidth) {
|
||||
dlgOptRender->width = newWidth;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetHeight(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->height;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetHeight(ScriptDialogOptionsRendering *dlgOptRender, int newHeight) {
|
||||
dlgOptRender->height = newHeight;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetHasAlphaChannel(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->hasAlphaChannel;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetHasAlphaChannel(ScriptDialogOptionsRendering *dlgOptRender, bool hasAlphaChannel) {
|
||||
dlgOptRender->hasAlphaChannel = hasAlphaChannel;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetParserTextboxX(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->parserTextboxX;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetParserTextboxX(ScriptDialogOptionsRendering *dlgOptRender, int newX) {
|
||||
dlgOptRender->parserTextboxX = newX;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetParserTextboxY(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->parserTextboxY;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetParserTextboxY(ScriptDialogOptionsRendering *dlgOptRender, int newY) {
|
||||
dlgOptRender->parserTextboxY = newY;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetParserTextboxWidth(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->parserTextboxWidth;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetParserTextboxWidth(ScriptDialogOptionsRendering *dlgOptRender, int newWidth) {
|
||||
dlgOptRender->parserTextboxWidth = newWidth;
|
||||
}
|
||||
|
||||
ScriptDialog *DialogOptionsRendering_GetDialogToRender(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return &_GP(scrDialog)[dlgOptRender->dialogID];
|
||||
}
|
||||
|
||||
ScriptDrawingSurface *DialogOptionsRendering_GetSurface(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
dlgOptRender->surfaceAccessed = true;
|
||||
return dlgOptRender->surfaceToRenderTo;
|
||||
}
|
||||
|
||||
int DialogOptionsRendering_GetActiveOptionID(ScriptDialogOptionsRendering *dlgOptRender) {
|
||||
return dlgOptRender->activeOptionID + 1;
|
||||
}
|
||||
|
||||
void DialogOptionsRendering_SetActiveOptionID(ScriptDialogOptionsRendering *dlgOptRender, int activeOptionID) {
|
||||
int optionCount = _G(dialog)[_GP(scrDialog)[dlgOptRender->dialogID].id].numoptions;
|
||||
if ((activeOptionID < 0) || (activeOptionID > optionCount))
|
||||
quitprintf("DialogOptionsRenderingInfo.ActiveOptionID: invalid ID specified for this dialog (specified %d, valid range: 1..%d)", activeOptionID, optionCount);
|
||||
|
||||
if (dlgOptRender->activeOptionID != activeOptionID - 1) {
|
||||
dlgOptRender->activeOptionID = activeOptionID - 1;
|
||||
dlgOptRender->needRepaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_Update(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptDialogOptionsRendering, DialogOptionsRendering_Update);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_RunActiveOption(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_BOOL(ScriptDialogOptionsRendering, DialogOptionsRendering_RunActiveOption);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetActiveOptionID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetActiveOptionID);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int activeOptionID)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetActiveOptionID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetActiveOptionID);
|
||||
}
|
||||
|
||||
// ScriptDialog* (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetDialogToRender(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJ(ScriptDialogOptionsRendering, ScriptDialog, _GP(ccDynamicDialog), DialogOptionsRendering_GetDialogToRender);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetHeight);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newHeight)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetHeight);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetParserTextboxX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetParserTextboxX);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newX)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetParserTextboxX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetParserTextboxX);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetParserTextboxY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetParserTextboxY);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newY)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetParserTextboxY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetParserTextboxY);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetParserTextboxWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetParserTextboxWidth);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newWidth)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetParserTextboxWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetParserTextboxWidth);
|
||||
}
|
||||
|
||||
// ScriptDrawingSurface* (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetSurface(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJAUTO(ScriptDialogOptionsRendering, ScriptDrawingSurface, DialogOptionsRendering_GetSurface);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetWidth);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newWidth)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetWidth);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetX);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newX)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetX);
|
||||
}
|
||||
|
||||
// int (ScriptDialogOptionsRendering *dlgOptRender)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetY);
|
||||
}
|
||||
|
||||
// void (ScriptDialogOptionsRendering *dlgOptRender, int newY)
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDialogOptionsRendering, DialogOptionsRendering_SetY);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_GetHasAlphaChannel(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDialogOptionsRendering, DialogOptionsRendering_GetHasAlphaChannel);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DialogOptionsRendering_SetHasAlphaChannel(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PBOOL(ScriptDialogOptionsRendering, DialogOptionsRendering_SetHasAlphaChannel);
|
||||
}
|
||||
|
||||
|
||||
void RegisterDialogOptionsRenderingAPI() {
|
||||
ScFnRegister dialogopt_api[] = {
|
||||
{"DialogOptionsRenderingInfo::Update^0", API_FN_PAIR(DialogOptionsRendering_Update)},
|
||||
{"DialogOptionsRenderingInfo::RunActiveOption^0", API_FN_PAIR(DialogOptionsRendering_RunActiveOption)},
|
||||
{"DialogOptionsRenderingInfo::get_ActiveOptionID", API_FN_PAIR(DialogOptionsRendering_GetActiveOptionID)},
|
||||
{"DialogOptionsRenderingInfo::set_ActiveOptionID", API_FN_PAIR(DialogOptionsRendering_SetActiveOptionID)},
|
||||
{"DialogOptionsRenderingInfo::get_DialogToRender", API_FN_PAIR(DialogOptionsRendering_GetDialogToRender)},
|
||||
{"DialogOptionsRenderingInfo::get_Height", API_FN_PAIR(DialogOptionsRendering_GetHeight)},
|
||||
{"DialogOptionsRenderingInfo::set_Height", API_FN_PAIR(DialogOptionsRendering_SetHeight)},
|
||||
{"DialogOptionsRenderingInfo::get_ParserTextBoxX", API_FN_PAIR(DialogOptionsRendering_GetParserTextboxX)},
|
||||
{"DialogOptionsRenderingInfo::set_ParserTextBoxX", API_FN_PAIR(DialogOptionsRendering_SetParserTextboxX)},
|
||||
{"DialogOptionsRenderingInfo::get_ParserTextBoxY", API_FN_PAIR(DialogOptionsRendering_GetParserTextboxY)},
|
||||
{"DialogOptionsRenderingInfo::set_ParserTextBoxY", API_FN_PAIR(DialogOptionsRendering_SetParserTextboxY)},
|
||||
{"DialogOptionsRenderingInfo::get_ParserTextBoxWidth", API_FN_PAIR(DialogOptionsRendering_GetParserTextboxWidth)},
|
||||
{"DialogOptionsRenderingInfo::set_ParserTextBoxWidth", API_FN_PAIR(DialogOptionsRendering_SetParserTextboxWidth)},
|
||||
{"DialogOptionsRenderingInfo::get_Surface", API_FN_PAIR(DialogOptionsRendering_GetSurface)},
|
||||
{"DialogOptionsRenderingInfo::get_Width", API_FN_PAIR(DialogOptionsRendering_GetWidth)},
|
||||
{"DialogOptionsRenderingInfo::set_Width", API_FN_PAIR(DialogOptionsRendering_SetWidth)},
|
||||
{"DialogOptionsRenderingInfo::get_X", API_FN_PAIR(DialogOptionsRendering_GetX)},
|
||||
{"DialogOptionsRenderingInfo::set_X", API_FN_PAIR(DialogOptionsRendering_SetX)},
|
||||
{"DialogOptionsRenderingInfo::get_Y", API_FN_PAIR(DialogOptionsRendering_GetY)},
|
||||
{"DialogOptionsRenderingInfo::set_Y", API_FN_PAIR(DialogOptionsRendering_SetY)},
|
||||
{"DialogOptionsRenderingInfo::get_HasAlphaChannel", API_FN_PAIR(DialogOptionsRendering_GetHasAlphaChannel)},
|
||||
{"DialogOptionsRenderingInfo::set_HasAlphaChannel", API_FN_PAIR(DialogOptionsRendering_SetHasAlphaChannel)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(dialogopt_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
53
engines/ags/engine/ac/dialog_options_rendering.h
Normal file
53
engines/ags/engine/ac/dialog_options_rendering.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DIALOG_OPTIONS_RENDERING_H
|
||||
#define AGS_ENGINE_AC_DIALOG_OPTIONS_RENDERING_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_dialog.h"
|
||||
#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int DialogOptionsRendering_GetX(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetX(ScriptDialogOptionsRendering *dlgOptRender, int newX);
|
||||
int DialogOptionsRendering_GetY(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetY(ScriptDialogOptionsRendering *dlgOptRender, int newY);
|
||||
int DialogOptionsRendering_GetWidth(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetWidth(ScriptDialogOptionsRendering *dlgOptRender, int newWidth);
|
||||
int DialogOptionsRendering_GetHeight(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetHeight(ScriptDialogOptionsRendering *dlgOptRender, int newHeight);
|
||||
int DialogOptionsRendering_GetHasAlphaChannel(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetHasAlphaChannel(ScriptDialogOptionsRendering *dlgOptRender, bool hasAlphaChannel);
|
||||
int DialogOptionsRendering_GetParserTextboxX(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetParserTextboxX(ScriptDialogOptionsRendering *dlgOptRender, int newX);
|
||||
int DialogOptionsRendering_GetParserTextboxY(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetParserTextboxY(ScriptDialogOptionsRendering *dlgOptRender, int newY);
|
||||
int DialogOptionsRendering_GetParserTextboxWidth(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetParserTextboxWidth(ScriptDialogOptionsRendering *dlgOptRender, int newWidth);
|
||||
ScriptDialog *DialogOptionsRendering_GetDialogToRender(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
ScriptDrawingSurface *DialogOptionsRendering_GetSurface(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
int DialogOptionsRendering_GetActiveOptionID(ScriptDialogOptionsRendering *dlgOptRender);
|
||||
void DialogOptionsRendering_SetActiveOptionID(ScriptDialogOptionsRendering *dlgOptRender, int activeOptionID);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
799
engines/ags/engine/ac/display.cpp
Normal file
799
engines/ags/engine/ac/display.cpp
Normal file
@@ -0,0 +1,799 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/std/algorithm.h"
|
||||
#include "ags/engine/ac/display.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/shared/font/ags_font_renderer.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/engine/ac/character.h"
|
||||
#include "ags/engine/ac/draw.h"
|
||||
#include "ags/engine/ac/game.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/engine/ac/global_audio.h"
|
||||
#include "ags/engine/ac/global_game.h"
|
||||
#include "ags/engine/ac/gui.h"
|
||||
#include "ags/engine/ac/mouse.h"
|
||||
#include "ags/engine/ac/overlay.h"
|
||||
#include "ags/engine/ac/sys_events.h"
|
||||
#include "ags/engine/ac/screen_overlay.h"
|
||||
#include "ags/engine/ac/speech.h"
|
||||
#include "ags/engine/ac/string.h"
|
||||
#include "ags/engine/ac/system.h"
|
||||
#include "ags/engine/ac/top_bar_settings.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/gfx/blender.h"
|
||||
#include "ags/shared/gui/gui_button.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/engine/main/game_run.h"
|
||||
#include "ags/engine/platform/base/ags_platform_driver.h"
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/engine/gfx/gfx_util.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
#include "ags/engine/ac/mouse.h"
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/engine/ac/timer.h"
|
||||
#include "ags/ags.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
using namespace AGS::Shared::BitmapHelper;
|
||||
|
||||
struct DisplayVars {
|
||||
int linespacing = 0; // font's line spacing
|
||||
int fulltxtheight = 0; // total height of all the text
|
||||
} disp;
|
||||
|
||||
// Generates a textual image and returns a disposable bitmap
|
||||
Bitmap *create_textual_image(const char *text, int asspch, int isThought,
|
||||
int &xx, int &yy, int &adjustedXX, int &adjustedYY, int wii, int usingfont, int allowShrink,
|
||||
bool &alphaChannel) {
|
||||
//
|
||||
// Configure the textual image
|
||||
//
|
||||
const bool use_speech_textwindow = (asspch < 0) && (_GP(game).options[OPT_SPEECHTYPE] >= 2);
|
||||
const bool use_thought_gui = (isThought) && (_GP(game).options[OPT_THOUGHTGUI] > 0);
|
||||
|
||||
alphaChannel = false;
|
||||
int usingGui = -1;
|
||||
if (use_speech_textwindow)
|
||||
usingGui = _GP(play).speech_textwindow_gui;
|
||||
else if (use_thought_gui)
|
||||
usingGui = _GP(game).options[OPT_THOUGHTGUI];
|
||||
|
||||
const int padding = get_textwindow_padding(usingGui);
|
||||
const int paddingScaled = get_fixed_pixel_size(padding);
|
||||
// Just in case screen size is not neatly divisible by 320x200
|
||||
const int paddingDoubledScaled = get_fixed_pixel_size(padding * 2);
|
||||
|
||||
// WORKAROUND: Guard Duty specifies a wii of 100,000, which is larger
|
||||
// than can be supported by ScummVM's surface classes
|
||||
wii = MIN(wii, 8000);
|
||||
|
||||
// Make message copy, because ensure_text_valid_for_font() may modify it
|
||||
char todis[STD_BUFFER_SIZE];
|
||||
snprintf(todis, STD_BUFFER_SIZE - 1, "%s", text);
|
||||
ensure_text_valid_for_font(todis, usingfont);
|
||||
break_up_text_into_lines(todis, _GP(Lines), wii - 2 * padding, usingfont);
|
||||
disp.linespacing = get_font_linespacing(usingfont);
|
||||
disp.fulltxtheight = get_text_lines_surf_height(usingfont, _GP(Lines).Count());
|
||||
|
||||
if (_GP(topBar).wantIt) {
|
||||
// ensure that the window is wide enough to display any top bar text
|
||||
int topBarWid = get_text_width_outlined(_GP(topBar).text, _GP(topBar).font);
|
||||
topBarWid += data_to_game_coord(_GP(play).top_bar_borderwidth + 2) * 2;
|
||||
if (_G(longestline) < topBarWid)
|
||||
_G(longestline) = topBarWid;
|
||||
}
|
||||
|
||||
const Rect &ui_view = _GP(play).GetUIViewport();
|
||||
if (xx == OVR_AUTOPLACE);
|
||||
// centre text in middle of screen
|
||||
else if (yy < 0) yy = ui_view.GetHeight() / 2 - disp.fulltxtheight / 2 - padding;
|
||||
// speech, so it wants to be above the character's head
|
||||
else if (asspch > 0) {
|
||||
yy -= disp.fulltxtheight;
|
||||
if (yy < 5) yy = 5;
|
||||
yy = adjust_y_for_guis(yy);
|
||||
}
|
||||
|
||||
if (_G(longestline) < wii - paddingDoubledScaled) {
|
||||
// shrink the width of the dialog box to fit the text
|
||||
int oldWid = wii;
|
||||
//if ((asspch >= 0) || (allowShrink > 0))
|
||||
// If it's not speech, or a shrink is allowed, then shrink it
|
||||
if ((asspch == 0) || (allowShrink > 0))
|
||||
wii = _G(longestline) + paddingDoubledScaled;
|
||||
|
||||
// shift the dialog box right to align it, if necessary
|
||||
if ((allowShrink == 2) && (xx >= 0))
|
||||
xx += (oldWid - wii);
|
||||
}
|
||||
|
||||
if (xx < -1) {
|
||||
xx = (-xx) - wii / 2;
|
||||
if (xx < 0)
|
||||
xx = 0;
|
||||
|
||||
xx = adjust_x_for_guis(xx, yy);
|
||||
|
||||
if (xx + wii >= ui_view.GetWidth())
|
||||
xx = (ui_view.GetWidth() - wii) - 5;
|
||||
} else if (xx < 0) xx = ui_view.GetWidth() / 2 - wii / 2;
|
||||
|
||||
const int extraHeight = paddingDoubledScaled;
|
||||
color_t text_color = MakeColor(15);
|
||||
const int bmp_width = MAX(2, wii);
|
||||
const int bmp_height = MAX(2, disp.fulltxtheight + extraHeight);
|
||||
Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap(
|
||||
bmp_width, bmp_height, _GP(game).GetColorDepth());
|
||||
|
||||
// inform draw_text_window to free the old bitmap
|
||||
const bool wantFreeScreenop = true;
|
||||
|
||||
//
|
||||
// Create the textual image (may also adjust some params in the process)
|
||||
//
|
||||
// may later change if usingGUI, needed to avoid changing original coordinates
|
||||
adjustedXX = xx;
|
||||
adjustedYY = yy;
|
||||
|
||||
if ((strlen(todis) < 1) || (strcmp(todis, " ") == 0) || (wii == 0));
|
||||
// if it's an empty speech line, don't draw anything
|
||||
else if (asspch) { //text_color = ds->GetCompatibleColor(12);
|
||||
int ttxleft = 0, ttxtop = paddingScaled, oriwid = wii - padding * 2;
|
||||
int drawBackground = 0;
|
||||
|
||||
if (use_speech_textwindow) {
|
||||
drawBackground = 1;
|
||||
} else if (use_thought_gui) {
|
||||
// make it treat it as drawing inside a window now
|
||||
if (asspch > 0)
|
||||
asspch = -asspch;
|
||||
drawBackground = 1;
|
||||
}
|
||||
|
||||
if (drawBackground) {
|
||||
draw_text_window_and_bar(&text_window_ds, wantFreeScreenop, &ttxleft, &ttxtop, &adjustedXX, &adjustedYY, &wii, &text_color, 0, usingGui);
|
||||
if (usingGui > 0) {
|
||||
alphaChannel = _GP(guis)[usingGui].HasAlphaChannel();
|
||||
}
|
||||
} else if ((ShouldAntiAliasText()) && (_GP(game).GetColorDepth() >= 24))
|
||||
alphaChannel = true;
|
||||
|
||||
for (size_t ee = 0; ee < _GP(Lines).Count(); ee++) {
|
||||
//int ttxp=wii/2 - get_text_width_outlined(lines[ee], usingfont)/2;
|
||||
int ttyp = ttxtop + ee * disp.linespacing;
|
||||
// asspch < 0 means that it's inside a text box so don't
|
||||
// centre the text
|
||||
if (asspch < 0) {
|
||||
if ((usingGui >= 0) &&
|
||||
((_GP(game).options[OPT_SPEECHTYPE] >= 2) || (isThought)))
|
||||
text_color = text_window_ds->GetCompatibleColor(_GP(guis)[usingGui].FgColor);
|
||||
else
|
||||
text_color = text_window_ds->GetCompatibleColor(-asspch);
|
||||
|
||||
wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, _GP(Lines)[ee].GetCStr(), _GP(play).text_align);
|
||||
} else {
|
||||
text_color = text_window_ds->GetCompatibleColor(asspch);
|
||||
wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, _GP(Lines)[ee].GetCStr(), _GP(play).speech_text_align);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int xoffs, yoffs, oriwid = wii - padding * 2;
|
||||
draw_text_window_and_bar(&text_window_ds, wantFreeScreenop, &xoffs, &yoffs, &adjustedXX, &adjustedYY, &wii, &text_color);
|
||||
|
||||
if (_GP(game).options[OPT_TWCUSTOM] > 0) {
|
||||
alphaChannel = _GP(guis)[_GP(game).options[OPT_TWCUSTOM]].HasAlphaChannel();
|
||||
}
|
||||
|
||||
adjust_y_coordinate_for_text(&yoffs, usingfont);
|
||||
|
||||
for (size_t ee = 0; ee < _GP(Lines).Count(); ee++)
|
||||
wouttext_aligned(text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, _GP(Lines)[ee].GetCStr(), _GP(play).text_align);
|
||||
}
|
||||
|
||||
return text_window_ds;
|
||||
}
|
||||
|
||||
// Pass yy = -1 to find Y co-ord automatically
|
||||
// allowShrink = 0 for none, 1 for leftwards, 2 for rightwards
|
||||
// pass blocking=2 to create permanent overlay
|
||||
ScreenOverlay *display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont,
|
||||
int asspch, int isThought, int allowShrink, bool overlayPositionFixed, bool roomlayer) {
|
||||
//
|
||||
// Prepare for the message display
|
||||
//
|
||||
|
||||
// AGS 2.x: If the screen is faded out, fade in again when displaying a message box.
|
||||
if (!asspch && (_G(loaded_game_file_version) <= kGameVersion_272))
|
||||
_GP(play).screen_is_faded_out = 0;
|
||||
|
||||
// if it's a normal message box and the game was being skipped,
|
||||
// ensure that the screen is up to date before the message box
|
||||
// is drawn on top of it
|
||||
// TODO: is this really necessary anymore?
|
||||
if ((_GP(play).skip_until_char_stops >= 0) && (disp_type == DISPLAYTEXT_MESSAGEBOX))
|
||||
render_graphics();
|
||||
|
||||
// TODO: should this really be called regardless of message type?
|
||||
// _display_main may be called even for custom textual overlays
|
||||
EndSkippingUntilCharStops();
|
||||
|
||||
if (_GP(topBar).wantIt) {
|
||||
// the top bar should behave like DisplaySpeech wrt blocking
|
||||
disp_type = DISPLAYTEXT_SPEECH;
|
||||
}
|
||||
|
||||
if ((asspch > 0) && (disp_type < DISPLAYTEXT_NORMALOVERLAY)) {
|
||||
// update the all_buttons_disabled variable in advance
|
||||
// of the adjust_x/y_for_guis calls
|
||||
_GP(play).disabled_user_interface++;
|
||||
update_gui_disabled_status();
|
||||
_GP(play).disabled_user_interface--;
|
||||
}
|
||||
|
||||
// remove any previous blocking texts if necessary
|
||||
if (disp_type < DISPLAYTEXT_NORMALOVERLAY)
|
||||
remove_screen_overlay(_GP(play).text_overlay_on);
|
||||
|
||||
// If fast-forwarding, then skip any blocking message immediately
|
||||
if (_GP(play).fast_forward && (disp_type < DISPLAYTEXT_NORMALOVERLAY)) {
|
||||
_GP(play).SetWaitSkipResult(SKIP_AUTOTIMER);
|
||||
post_display_cleanup();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure and create an overlay object
|
||||
//
|
||||
|
||||
int ovrtype;
|
||||
switch (disp_type) {
|
||||
case DISPLAYTEXT_SPEECH: ovrtype = OVER_TEXTSPEECH; break;
|
||||
case DISPLAYTEXT_MESSAGEBOX: ovrtype = OVER_TEXTMSG; break;
|
||||
case DISPLAYTEXT_NORMALOVERLAY: ovrtype = OVER_CUSTOM; break;
|
||||
default: ovrtype = disp_type; break; // must be precreated overlay id
|
||||
}
|
||||
|
||||
int adjustedXX, adjustedYY;
|
||||
bool alphaChannel;
|
||||
Bitmap *text_window_ds = create_textual_image(text, asspch, isThought, xx, yy, adjustedXX, adjustedYY, wii, usingfont, allowShrink, alphaChannel);
|
||||
|
||||
size_t nse = add_screen_overlay(roomlayer, xx, yy, ovrtype, text_window_ds, adjustedXX - xx, adjustedYY - yy, alphaChannel);
|
||||
auto *over = get_overlay(nse); // FIXME: optimize return value
|
||||
// we should not delete text_window_ds here, because it is now owned by Overlay
|
||||
|
||||
// If it's a non-blocking overlay type, then we're done here
|
||||
if (disp_type >= DISPLAYTEXT_NORMALOVERLAY) {
|
||||
return over;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for the blocking text to timeout or until skipped by another command
|
||||
//
|
||||
|
||||
if (disp_type == DISPLAYTEXT_MESSAGEBOX) {
|
||||
|
||||
int countdown = GetTextDisplayTime(text);
|
||||
int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)_GP(play).skip_display);
|
||||
// Loop until skipped
|
||||
while (true) {
|
||||
if (SHOULD_QUIT)
|
||||
return 0;
|
||||
|
||||
sys_evt_process_pending();
|
||||
|
||||
update_audio_system_on_game_loop();
|
||||
UpdateCursorAndDrawables();
|
||||
render_graphics();
|
||||
eAGSMouseButton mbut;
|
||||
int mwheelz;
|
||||
if (run_service_mb_controls(mbut, mwheelz) && mbut > kMouseNone) {
|
||||
check_skip_cutscene_mclick(mbut);
|
||||
if (_GP(play).fast_forward)
|
||||
break;
|
||||
if (skip_setting & SKIP_MOUSECLICK && !_GP(play).IsIgnoringInput()) {
|
||||
_GP(play).SetWaitSkipResult(SKIP_MOUSECLICK, mbut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool do_break = false;
|
||||
while (!_GP(play).fast_forward && !do_break && ags_keyevent_ready()) {
|
||||
KeyInput ki;
|
||||
if (run_service_key_controls(ki)) {
|
||||
check_skip_cutscene_keypress(ki.Key);
|
||||
if ((skip_setting & SKIP_KEYPRESS) && !_GP(play).IsIgnoringInput() && !IsAGSServiceKey(ki.Key)) {
|
||||
_GP(play).SetWaitKeySkip(ki);
|
||||
do_break = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_break)
|
||||
break;
|
||||
|
||||
update_polled_stuff();
|
||||
|
||||
if (_GP(play).fast_forward == 0) {
|
||||
WaitForNextFrame();
|
||||
}
|
||||
|
||||
countdown--;
|
||||
|
||||
// Special behavior when coupled with a voice-over
|
||||
if (_GP(play).speech_has_voice) {
|
||||
// extend life of text if the voice hasn't finished yet
|
||||
if (AudioChans::ChannelIsPlaying(SCHAN_SPEECH) && (_GP(play).fast_forward == 0)) {
|
||||
if (countdown <= 1)
|
||||
countdown = 1;
|
||||
} else // if the voice has finished, remove the speech
|
||||
countdown = 0;
|
||||
}
|
||||
// Test for the timed auto-skip
|
||||
if ((countdown < 1) && (skip_setting & SKIP_AUTOTIMER)) {
|
||||
_GP(play).SetWaitSkipResult(SKIP_AUTOTIMER);
|
||||
_GP(play).SetIgnoreInput(_GP(play).ignore_user_input_after_text_timeout_ms);
|
||||
break;
|
||||
}
|
||||
// if skipping cutscene, don't get stuck on No Auto Remove text boxes
|
||||
if ((countdown < 1) && (_GP(play).fast_forward))
|
||||
break;
|
||||
}
|
||||
|
||||
remove_screen_overlay(OVER_TEXTMSG);
|
||||
invalidate_screen();
|
||||
} else {
|
||||
/* DISPLAYTEXT_SPEECH */
|
||||
if (!overlayPositionFixed) {
|
||||
over->SetRoomRelative(true);
|
||||
VpPoint vpt = _GP(play).GetRoomViewport(0)->ScreenToRoom(over->x, over->y, false);
|
||||
over->x = vpt.first.X;
|
||||
over->y = vpt.first.Y;
|
||||
}
|
||||
|
||||
GameLoopUntilNoOverlay();
|
||||
}
|
||||
|
||||
//
|
||||
// Post-message cleanup
|
||||
//
|
||||
post_display_cleanup();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void display_at(int xx, int yy, int wii, const char *text) {
|
||||
EndSkippingUntilCharStops();
|
||||
// Start voice-over, if requested by the tokens in speech text
|
||||
try_auto_play_speech(text, text, _GP(play).narrator_speech);
|
||||
display_main(xx, yy, wii, text, DISPLAYTEXT_MESSAGEBOX, FONT_NORMAL, 0, 0, 0, false);
|
||||
|
||||
// Stop any blocking voice-over, if was started by this function
|
||||
if (_GP(play).IsBlockingVoiceSpeech())
|
||||
stop_voice_speech();
|
||||
}
|
||||
|
||||
void post_display_cleanup() {
|
||||
ags_clear_input_buffer();
|
||||
_GP(play).messagetime = -1;
|
||||
_GP(play).speech_in_post_state = false;
|
||||
}
|
||||
|
||||
bool try_auto_play_speech(const char *text, const char *&replace_text, int charid) {
|
||||
int voice_num;
|
||||
const char *src = parse_voiceover_token(text, &voice_num);
|
||||
if (src == text)
|
||||
return false; // no token
|
||||
|
||||
if (voice_num <= 0)
|
||||
quit("DisplaySpeech: auto-voice symbol '&' not followed by valid integer");
|
||||
|
||||
replace_text = src; // skip voice tag
|
||||
if (play_voice_speech(charid, voice_num)) {
|
||||
// if Voice Only, then blank out the text
|
||||
if (_GP(play).speech_mode == kSpeech_VoiceOnly)
|
||||
replace_text = " ";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetTextDisplayLength(const char *text) {
|
||||
// Skip voice-over token from the length calculation if required
|
||||
if (_GP(play).unfactor_speech_from_textlength != 0)
|
||||
text = parse_voiceover_token(text, nullptr);
|
||||
return static_cast<int>(strlen(text));
|
||||
}
|
||||
|
||||
// Calculates lipsync frame duration (or duration per character) in game loops.
|
||||
// NOTE: historical formula was this:
|
||||
// loops_per_character = (((text_len / play.lipsync_speed) + 1) * fps) / text_len;
|
||||
// But because of a precision loss due integer division this resulted in "jumping" values.
|
||||
// The new formula uses float division, and coefficent found experimentally to make
|
||||
// results match the old formula in certain key text lengths, for backwards compatibility.
|
||||
int CalcLipsyncFrameDuration(int text_len, int fps) {
|
||||
return static_cast<int>((((static_cast<float>(text_len) / _GP(play).lipsync_speed) + 0.75f) * fps) / text_len);
|
||||
}
|
||||
|
||||
int GetTextDisplayTime(const char *text, int canberel) {
|
||||
int uselen = 0;
|
||||
auto fpstimer = ::lround(get_game_fps());
|
||||
|
||||
// if it's background speech, make it stay relative to game speed
|
||||
if ((canberel == 1) && (_GP(play).bgspeech_game_speed == 1))
|
||||
fpstimer = 40; // NOTE: should be a fixed constant here, not game speed value
|
||||
|
||||
if (_G(source_text_length) >= 0) {
|
||||
// sync to length of original text, to make sure any animations
|
||||
// and music sync up correctly
|
||||
uselen = _G(source_text_length);
|
||||
_G(source_text_length) = -1;
|
||||
} else {
|
||||
uselen = GetTextDisplayLength(text);
|
||||
}
|
||||
|
||||
if (uselen <= 0)
|
||||
return 0;
|
||||
|
||||
if (_GP(play).text_speed + _GP(play).text_speed_modifier <= 0)
|
||||
quit("!Text speed is zero; unable to display text. Check your _GP(game).text_speed settings.");
|
||||
|
||||
// Store how many game loops per character of text
|
||||
_G(loops_per_character) = CalcLipsyncFrameDuration(uselen, fpstimer);
|
||||
|
||||
int textDisplayTimeInMS = ((uselen / (_GP(play).text_speed + _GP(play).text_speed_modifier)) + 1) * 1000;
|
||||
if (textDisplayTimeInMS < _GP(play).text_min_display_time_ms)
|
||||
textDisplayTimeInMS = _GP(play).text_min_display_time_ms;
|
||||
|
||||
return (textDisplayTimeInMS * fpstimer) / 1000;
|
||||
}
|
||||
|
||||
bool ShouldAntiAliasText() {
|
||||
return (_GP(game).GetColorDepth() >= 24) && (_GP(game).options[OPT_ANTIALIASFONTS] != 0 || ::AGS::g_vm->_forceTextAA);
|
||||
}
|
||||
|
||||
void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *texx, int &xxp, int &yyp) {
|
||||
const FontInfo &finfo = get_fontinfo(font);
|
||||
int const thickness = finfo.AutoOutlineThickness;
|
||||
auto const style = finfo.AutoOutlineStyle;
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
// 16-bit games should use 32-bit stencils to keep anti-aliasing working
|
||||
// because 16-bit blending works correctly if there's an actual color
|
||||
// on the destination bitmap (and our intermediate bitmaps are transparent).
|
||||
int const ds_cd = ds->GetColorDepth();
|
||||
bool const antialias = ds_cd >= 16 && _GP(game).options[OPT_ANTIALIASFONTS] != 0 && !is_bitmap_font(font);
|
||||
int const stencil_cd = antialias ? 32 : ds_cd;
|
||||
if (antialias) // This is to make sure TTFs render proper alpha channel in 16-bit games too
|
||||
color |= makeacol32(0, 0, 0, 0xff);
|
||||
|
||||
// WORKAROUND: Clifftop's Spritefont plugin returns a wrong font height for font 2 in Kathy Rain, which causes a partial outline
|
||||
// for some letters. Unfortunately fixing the value on the plugin side breaks the line spacing, so let's just correct it here.
|
||||
const int t_width = get_text_width(texx, font);
|
||||
const auto t_extent = get_font_surface_extent(font);
|
||||
const int t_height = t_extent.second - t_extent.first + ((strcmp(_GP(game).guid, "{d6795d1c-3cfe-49ec-90a1-85c313bfccaf}") == 0) && (font == 2) ? 1 : 0);
|
||||
|
||||
if (t_width == 0 || t_height == 0)
|
||||
return;
|
||||
|
||||
// Prepare stencils
|
||||
const int t_yoff = t_extent.first;
|
||||
Bitmap *texx_stencil, *outline_stencil;
|
||||
alloc_font_outline_buffers(font, &texx_stencil, &outline_stencil,
|
||||
t_width, t_height, stencil_cd);
|
||||
texx_stencil->ClearTransparent();
|
||||
outline_stencil->ClearTransparent();
|
||||
// Ready text stencil
|
||||
// Note we are drawing with y off, in case some font's glyphs exceed font's ascender
|
||||
wouttextxy(texx_stencil, 0, -t_yoff, font, color, texx);
|
||||
|
||||
// Anti-aliased TTFs require to be alpha-blended, not blit,
|
||||
// or the alpha values will be plain copied and final image will be broken.
|
||||
void(Bitmap:: * pfn_drawstencil)(Bitmap * src, int dst_x, int dst_y);
|
||||
if (antialias) { // NOTE: we must set out blender AFTER wouttextxy, or it will be overidden
|
||||
set_argb2any_blender();
|
||||
pfn_drawstencil = &Bitmap::TransBlendBlt;
|
||||
} else {
|
||||
pfn_drawstencil = &Bitmap::MaskedBlit;
|
||||
}
|
||||
|
||||
// move start of text so that the outline doesn't drop off the bitmap
|
||||
xxp += thickness;
|
||||
int const outline_y = yyp + t_yoff;
|
||||
yyp += thickness;
|
||||
|
||||
// What we do here: first we paint text onto outline_stencil offsetting vertically;
|
||||
// then we paint resulting outline_stencil onto final dest offsetting horizontally.
|
||||
int largest_y_diff_reached_so_far = -1;
|
||||
for (int x_diff = thickness; x_diff >= 0; x_diff--) {
|
||||
// Integer arithmetics: In the following, we use terms k*(k + 1) to account for rounding.
|
||||
// (k + 0.5)^2 == k*k + 2*k*0.5 + 0.5^2 == k*k + k + 0.25 ==approx. k*(k + 1)
|
||||
int y_term_limit = thickness * (thickness + 1);
|
||||
if (FontInfo::kRounded == style)
|
||||
y_term_limit -= x_diff * x_diff;
|
||||
|
||||
// Extend the outline stencil to the top and bottom
|
||||
for (int y_diff = largest_y_diff_reached_so_far + 1;
|
||||
y_diff <= thickness && y_diff * y_diff <= y_term_limit;
|
||||
y_diff++) {
|
||||
(outline_stencil->*pfn_drawstencil)(texx_stencil, 0, thickness - y_diff);
|
||||
if (y_diff > 0)
|
||||
(outline_stencil->*pfn_drawstencil)(texx_stencil, 0, thickness + y_diff);
|
||||
largest_y_diff_reached_so_far = y_diff;
|
||||
}
|
||||
|
||||
// Stamp the outline stencil to the left and right of the text
|
||||
(ds->*pfn_drawstencil)(outline_stencil, xxp - x_diff, outline_y);
|
||||
if (x_diff > 0)
|
||||
(ds->*pfn_drawstencil)(outline_stencil, xxp + x_diff, outline_y);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw an outline if requested, then draw the text on top
|
||||
void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int font, color_t text_color, const char *texx) {
|
||||
size_t const text_font = static_cast<size_t>(font);
|
||||
// Draw outline (a backdrop) if requested
|
||||
color_t const outline_color = ds->GetCompatibleColor(_GP(play).speech_text_shadow);
|
||||
int const outline_font = get_font_outline(font);
|
||||
if (outline_font >= 0)
|
||||
wouttextxy(ds, xxp, yyp, static_cast<size_t>(outline_font), outline_color, texx);
|
||||
else if (outline_font == FONT_OUTLINE_AUTO)
|
||||
wouttextxy_AutoOutline(ds, text_font, outline_color, texx, xxp, yyp);
|
||||
else
|
||||
; // no outline
|
||||
|
||||
// Draw text on top
|
||||
wouttextxy(ds, xxp, yyp, text_font, text_color, texx);
|
||||
}
|
||||
|
||||
void wouttext_aligned(Bitmap *ds, int usexp, int yy, int oriwid, int usingfont, color_t text_color, const char *text, HorAlignment align) {
|
||||
|
||||
if (align & kMAlignHCenter)
|
||||
usexp = usexp + (oriwid / 2) - (get_text_width_outlined(text, usingfont) / 2);
|
||||
else if (align & kMAlignRight)
|
||||
usexp = usexp + (oriwid - get_text_width_outlined(text, usingfont));
|
||||
|
||||
wouttext_outline(ds, usexp, yy, usingfont, text_color, text);
|
||||
}
|
||||
|
||||
int get_font_outline_padding(int font) {
|
||||
if (get_font_outline(font) == FONT_OUTLINE_AUTO) {
|
||||
// scaled up bitmap font, push outline further out
|
||||
if (is_bitmap_font(font) && get_font_scaling_mul(font) > 1)
|
||||
return get_fixed_pixel_size(2); // FIXME: should be 2 + get_fixed_pixel_size(2)?
|
||||
// otherwise, just push outline by 1 pixel
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void do_corner(Bitmap *ds, int sprn, int x, int y, int offx, int offy) {
|
||||
if (sprn < 0) return;
|
||||
if (!_GP(spriteset).DoesSpriteExist(sprn)) {
|
||||
sprn = 0;
|
||||
}
|
||||
|
||||
x = x + offx * _GP(game).SpriteInfos[sprn].Width;
|
||||
y = y + offy * _GP(game).SpriteInfos[sprn].Height;
|
||||
draw_gui_sprite_v330(ds, sprn, x, y);
|
||||
}
|
||||
|
||||
int get_but_pic(GUIMain *guo, int indx) {
|
||||
int butid = guo->GetControlID(indx);
|
||||
return butid >= 0 ? _GP(guibuts)[butid].GetNormalImage() : 0;
|
||||
}
|
||||
|
||||
void draw_button_background(Bitmap *ds, int xx1, int yy1, int xx2, int yy2, GUIMain *iep) {
|
||||
color_t draw_color;
|
||||
if (iep == nullptr) { // standard window
|
||||
draw_color = ds->GetCompatibleColor(15);
|
||||
ds->FillRect(Rect(xx1, yy1, xx2, yy2), draw_color);
|
||||
draw_color = ds->GetCompatibleColor(16);
|
||||
ds->DrawRect(Rect(xx1, yy1, xx2, yy2), draw_color);
|
||||
} else {
|
||||
if (_G(loaded_game_file_version) < kGameVersion_262) {
|
||||
// In pre-2.62 color 0 should be treated as "black" instead of "transparent";
|
||||
// this was an unintended effect in older versions (see 2.62 changelog fixes).
|
||||
if (iep->BgColor == 0)
|
||||
iep->BgColor = 16;
|
||||
}
|
||||
|
||||
if (iep->BgColor >= 0) draw_color = ds->GetCompatibleColor(iep->BgColor);
|
||||
else draw_color = ds->GetCompatibleColor(0); // black backrgnd behind picture
|
||||
|
||||
if (iep->BgColor > 0)
|
||||
ds->FillRect(Rect(xx1, yy1, xx2, yy2), draw_color);
|
||||
|
||||
const int leftRightWidth = _GP(game).SpriteInfos[get_but_pic(iep, 4)].Width;
|
||||
const int topBottomHeight = _GP(game).SpriteInfos[get_but_pic(iep, 6)].Height;
|
||||
// GUI middle space
|
||||
if (iep->BgImage > 0) {
|
||||
{
|
||||
// offset the background image and clip it so that it is drawn
|
||||
// such that the border graphics can have a transparent outside
|
||||
// edge
|
||||
int bgoffsx = xx1 - leftRightWidth / 2;
|
||||
int bgoffsy = yy1 - topBottomHeight / 2;
|
||||
ds->SetClip(Rect(bgoffsx, bgoffsy, xx2 + leftRightWidth / 2, yy2 + topBottomHeight / 2));
|
||||
int bgfinishx = xx2;
|
||||
int bgfinishy = yy2;
|
||||
int bgoffsyStart = bgoffsy;
|
||||
while (bgoffsx <= bgfinishx) {
|
||||
bgoffsy = bgoffsyStart;
|
||||
while (bgoffsy <= bgfinishy) {
|
||||
draw_gui_sprite_v330(ds, iep->BgImage, bgoffsx, bgoffsy);
|
||||
bgoffsy += _GP(game).SpriteInfos[iep->BgImage].Height;
|
||||
}
|
||||
bgoffsx += _GP(game).SpriteInfos[iep->BgImage].Width;
|
||||
}
|
||||
// return to normal clipping rectangle
|
||||
ds->ResetClip();
|
||||
}
|
||||
}
|
||||
// Vertical borders
|
||||
ds->SetClip(Rect(xx1 - leftRightWidth, yy1, xx2 + 1 + leftRightWidth, yy2));
|
||||
for (int uu = yy1; uu <= yy2; uu += _GP(game).SpriteInfos[get_but_pic(iep, 4)].Height) {
|
||||
do_corner(ds, get_but_pic(iep, 4), xx1, uu, -1, 0); // left side
|
||||
do_corner(ds, get_but_pic(iep, 5), xx2 + 1, uu, 0, 0); // right side
|
||||
}
|
||||
// Horizontal borders
|
||||
ds->SetClip(Rect(xx1, yy1 - topBottomHeight, xx2, yy2 + 1 + topBottomHeight));
|
||||
for (int uu = xx1; uu <= xx2; uu += _GP(game).SpriteInfos[get_but_pic(iep, 6)].Width) {
|
||||
do_corner(ds, get_but_pic(iep, 6), uu, yy1, 0, -1); // top side
|
||||
do_corner(ds, get_but_pic(iep, 7), uu, yy2 + 1, 0, 0); // bottom side
|
||||
}
|
||||
ds->ResetClip();
|
||||
// Four corners
|
||||
do_corner(ds, get_but_pic(iep, 0), xx1, yy1, -1, -1); // top left
|
||||
do_corner(ds, get_but_pic(iep, 1), xx1, yy2 + 1, -1, 0); // bottom left
|
||||
do_corner(ds, get_but_pic(iep, 2), xx2 + 1, yy1, 0, -1); // top right
|
||||
do_corner(ds, get_but_pic(iep, 3), xx2 + 1, yy2 + 1, 0, 0); // bottom right
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the width that the left and right border of the textwindow
|
||||
// GUI take up
|
||||
int get_textwindow_border_width(int twgui) {
|
||||
if (twgui < 0)
|
||||
return 0;
|
||||
|
||||
if (!_GP(guis)[twgui].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
int borwid = _GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 4)].Width +
|
||||
_GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 5)].Width;
|
||||
|
||||
return borwid;
|
||||
}
|
||||
|
||||
// get the hegiht of the text window's top border
|
||||
int get_textwindow_top_border_height(int twgui) {
|
||||
if (twgui < 0)
|
||||
return 0;
|
||||
|
||||
if (!_GP(guis)[twgui].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
return _GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 6)].Height;
|
||||
}
|
||||
|
||||
// Get the padding for a text window
|
||||
// -1 for the game's custom text window
|
||||
int get_textwindow_padding(int ifnum) {
|
||||
int result;
|
||||
|
||||
if (ifnum < 0)
|
||||
ifnum = _GP(game).options[OPT_TWCUSTOM];
|
||||
if (ifnum > 0 && ifnum < _GP(game).numgui)
|
||||
result = _GP(guis)[ifnum].Padding;
|
||||
else
|
||||
result = TEXTWINDOW_PADDING_DEFAULT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void draw_text_window(Bitmap **text_window_ds, bool should_free_ds,
|
||||
int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
|
||||
assert(text_window_ds);
|
||||
Bitmap *ds = *text_window_ds;
|
||||
if (ifnum < 0)
|
||||
ifnum = _GP(game).options[OPT_TWCUSTOM];
|
||||
|
||||
if (ifnum <= 0) {
|
||||
if (ovrheight)
|
||||
quit("!Cannot use QFG4 style options without custom text window");
|
||||
draw_button_background(ds, 0, 0, ds->GetWidth() - 1, ds->GetHeight() - 1, nullptr);
|
||||
if (set_text_color)
|
||||
*set_text_color = ds->GetCompatibleColor(16);
|
||||
xins[0] = 3;
|
||||
yins[0] = 3;
|
||||
} else {
|
||||
if (ifnum >= _GP(game).numgui)
|
||||
quitprintf("!Invalid GUI %d specified as text window (total GUIs: %d)", ifnum, _GP(game).numgui);
|
||||
if (!_GP(guis)[ifnum].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
int tbnum = get_but_pic(&_GP(guis)[ifnum], 0);
|
||||
|
||||
wii[0] += get_textwindow_border_width(ifnum);
|
||||
xx[0] -= _GP(game).SpriteInfos[tbnum].Width;
|
||||
yy[0] -= _GP(game).SpriteInfos[tbnum].Height;
|
||||
if (ovrheight == 0)
|
||||
ovrheight = disp.fulltxtheight;
|
||||
|
||||
if (should_free_ds)
|
||||
delete *text_window_ds;
|
||||
int padding = get_textwindow_padding(ifnum);
|
||||
*text_window_ds = BitmapHelper::CreateTransparentBitmap(wii[0], ovrheight + (padding * 2) + _GP(game).SpriteInfos[tbnum].Height * 2, _GP(game).GetColorDepth());
|
||||
ds = *text_window_ds;
|
||||
int xoffs = _GP(game).SpriteInfos[tbnum].Width, yoffs = _GP(game).SpriteInfos[tbnum].Height;
|
||||
draw_button_background(ds, xoffs, yoffs, (ds->GetWidth() - xoffs) - 1, (ds->GetHeight() - yoffs) - 1, &_GP(guis)[ifnum]);
|
||||
if (set_text_color)
|
||||
*set_text_color = ds->GetCompatibleColor(_GP(guis)[ifnum].FgColor);
|
||||
xins[0] = xoffs + padding;
|
||||
yins[0] = yoffs + padding;
|
||||
}
|
||||
}
|
||||
|
||||
void draw_text_window_and_bar(Bitmap **text_window_ds, bool should_free_ds,
|
||||
int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
|
||||
assert(text_window_ds);
|
||||
draw_text_window(text_window_ds, should_free_ds, xins, yins, xx, yy, wii, set_text_color, ovrheight, ifnum);
|
||||
|
||||
if ((_GP(topBar).wantIt) && (text_window_ds && *text_window_ds)) {
|
||||
// top bar on the dialog window with character's name
|
||||
// create an enlarged window, then free the old one
|
||||
Bitmap *ds = *text_window_ds;
|
||||
Bitmap *newScreenop = BitmapHelper::CreateBitmap(ds->GetWidth(), ds->GetHeight() + _GP(topBar).height, _GP(game).GetColorDepth());
|
||||
newScreenop->Blit(ds, 0, 0, 0, _GP(topBar).height, ds->GetWidth(), ds->GetHeight());
|
||||
delete *text_window_ds;
|
||||
*text_window_ds = newScreenop;
|
||||
ds = *text_window_ds;
|
||||
|
||||
// draw the top bar
|
||||
color_t draw_color = ds->GetCompatibleColor(_GP(play).top_bar_backcolor);
|
||||
ds->FillRect(Rect(0, 0, ds->GetWidth() - 1, _GP(topBar).height - 1), draw_color);
|
||||
if (_GP(play).top_bar_backcolor != _GP(play).top_bar_bordercolor) {
|
||||
// draw the border
|
||||
draw_color = ds->GetCompatibleColor(_GP(play).top_bar_bordercolor);
|
||||
for (int j = 0; j < data_to_game_coord(_GP(play).top_bar_borderwidth); j++)
|
||||
ds->DrawRect(Rect(j, j, ds->GetWidth() - (j + 1), _GP(topBar).height - (j + 1)), draw_color);
|
||||
}
|
||||
|
||||
// draw the text
|
||||
int textx = (ds->GetWidth() / 2) - get_text_width_outlined(_GP(topBar).text, _GP(topBar).font) / 2;
|
||||
color_t text_color = ds->GetCompatibleColor(_GP(play).top_bar_textcolor);
|
||||
wouttext_outline(ds, textx, _GP(play).top_bar_borderwidth + get_fixed_pixel_size(1), _GP(topBar).font, text_color, _GP(topBar).text);
|
||||
|
||||
// don't draw it next time
|
||||
_GP(topBar).wantIt = 0;
|
||||
// adjust the text Y position
|
||||
yins[0] += _GP(topBar).height;
|
||||
} else if (_GP(topBar).wantIt)
|
||||
_GP(topBar).wantIt = 0;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
87
engines/ags/engine/ac/display.h
Normal file
87
engines/ags/engine/ac/display.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DISPLAY_H
|
||||
#define AGS_ENGINE_AC_DISPLAY_H
|
||||
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using AGS::Shared::GUIMain;
|
||||
|
||||
// options for 'disp_type' parameter
|
||||
// blocking speech
|
||||
#define DISPLAYTEXT_SPEECH 0
|
||||
// super-blocking message box
|
||||
#define DISPLAYTEXT_MESSAGEBOX 1
|
||||
// regular non-blocking overlay
|
||||
#define DISPLAYTEXT_NORMALOVERLAY 2
|
||||
// also accepts explicit overlay ID >= OVER_CUSTOM
|
||||
|
||||
struct ScreenOverlay;
|
||||
Shared::Bitmap *create_textual_image(const char *text, int asspch, int isThought,
|
||||
int &xx, int &yy, int &adjustedXX, int &adjustedYY, int wii, int usingfont, int allowShrink,
|
||||
bool &alphaChannel);
|
||||
// Creates a textual overlay using the given parameters;
|
||||
// Pass yy = -1 to find Y co-ord automatically
|
||||
// allowShrink = 0 for none, 1 for leftwards, 2 for rightwards
|
||||
// pass blocking=2 to create permanent overlay
|
||||
ScreenOverlay *display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont,
|
||||
int asspch, int isThought, int allowShrink, bool overlayPositionFixed, bool roomlayer = false);
|
||||
// Displays a standard blocking message box at a given position
|
||||
void display_at(int xx, int yy, int wii, const char *text);
|
||||
// Cleans up display message state
|
||||
void post_display_cleanup();
|
||||
// Tests the given string for the voice-over tags and plays cue clip for the given character;
|
||||
// will assign replacement string, which will be blank string if game is in "voice-only" mode
|
||||
// and clip was started, or string cleaned from voice-over tags which is safe to display on screen.
|
||||
// Returns whether voice-over clip was started successfully.
|
||||
bool try_auto_play_speech(const char *text, const char *&replace_text, int charid);
|
||||
// Calculates meaningful length of the displayed text
|
||||
int GetTextDisplayLength(const char *text);
|
||||
// Calculates number of game loops for displaying a text on screen
|
||||
int GetTextDisplayTime(const char *text, int canberel = 0);
|
||||
// Draw an outline if requested, then draw the text on top
|
||||
void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int usingfont, color_t text_color, const char *texx);
|
||||
void wouttext_aligned(Shared::Bitmap *ds, int usexp, int yy, int oriwid, int usingfont, color_t text_color, const char *text, HorAlignment align);
|
||||
void do_corner(Shared::Bitmap *ds, int sprn, int xx1, int yy1, int typx, int typy);
|
||||
// Returns the image of a button control on the GUI under given child index
|
||||
int get_but_pic(GUIMain *guo, int indx);
|
||||
void draw_button_background(Shared::Bitmap *ds, int xx1, int yy1, int xx2, int yy2, GUIMain *iep);
|
||||
// Calculate the width that the left and right border of the textwindow
|
||||
// GUI take up
|
||||
int get_textwindow_border_width(int twgui);
|
||||
// get the hegiht of the text window's top border
|
||||
int get_textwindow_top_border_height(int twgui);
|
||||
// draw_text_window: draws the normal or custom text window
|
||||
// create a new bitmap the size of the window before calling, and
|
||||
// point text_window_ds to it
|
||||
// returns text start x & y pos in parameters
|
||||
// Warning!: draw_text_window() and draw_text_window_and_bar() can create new text_window_ds
|
||||
void draw_text_window(Shared::Bitmap **text_window_ds, bool should_free_ds, int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum);
|
||||
void draw_text_window_and_bar(Shared::Bitmap **text_window_ds, bool should_free_ds,
|
||||
int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight = 0, int ifnum = -1);
|
||||
int get_textwindow_padding(int ifnum);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
2273
engines/ags/engine/ac/draw.cpp
Normal file
2273
engines/ags/engine/ac/draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
322
engines/ags/engine/ac/draw.h
Normal file
322
engines/ags/engine/ac/draw.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DRAW_H
|
||||
#define AGS_ENGINE_AC_DRAW_H
|
||||
|
||||
#include "common/std/memory.h"
|
||||
#include "ags/shared/core/types.h"
|
||||
#include "ags/shared/ac/common_defines.h"
|
||||
#include "ags/shared/gfx/gfx_def.h"
|
||||
#include "ags/shared/gfx/allegro_bitmap.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/engine/ac/runtime_defines.h"
|
||||
#include "ags/engine/ac/walk_behind.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
typedef std::shared_ptr<Shared::Bitmap> PBitmap;
|
||||
} // namespace Shared
|
||||
|
||||
namespace Engine {
|
||||
class IDriverDependantBitmap;
|
||||
} // namespace Engine
|
||||
} // namespace AGS
|
||||
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
#define IS_ANTIALIAS_SPRITES _GP(usetup).enable_antialiasing && (_GP(play).disable_antialiasing == 0)
|
||||
|
||||
// Render stage flags, for filtering out certain elements
|
||||
// during room transitions, capturing screenshots, etc.
|
||||
// NOTE: these values are internal and purely arbitrary atm.
|
||||
#define RENDER_BATCH_ENGINE_OVERLAY 0x0001
|
||||
#define RENDER_BATCH_MOUSE_CURSOR 0x0002
|
||||
#define RENDER_SHOT_SKIP_ON_FADE (RENDER_BATCH_ENGINE_OVERLAY | RENDER_BATCH_MOUSE_CURSOR)
|
||||
|
||||
/**
|
||||
* Buffer and info flags for viewport/camera pairs rendering in software mode
|
||||
*/
|
||||
struct RoomCameraDrawData {
|
||||
// Intermediate bitmap for the software drawing method.
|
||||
// We use this bitmap in case room camera has scaling enabled, we draw dirty room rects on it,
|
||||
// and then pass to software renderer which draws sprite on top and then either blits or stretch-blits
|
||||
// to the virtual screen.
|
||||
// For more details see comment in ALSoftwareGraphicsDriver::RenderToBackBuffer().
|
||||
AGS::Shared::PBitmap Buffer; // this is the actual bitmap
|
||||
AGS::Shared::PBitmap Frame; // this is either same bitmap reference or sub-bitmap of virtual screen
|
||||
bool IsOffscreen; // whether room viewport was offscreen (cannot use sub-bitmap)
|
||||
bool IsOverlap; // whether room viewport overlaps any others (marking dirty rects is complicated)
|
||||
};
|
||||
|
||||
typedef int32_t sprkey_t;
|
||||
// TODO: refactor the draw unit into a virtual interface with
|
||||
// two implementations: for software and video-texture render,
|
||||
// instead of checking whether the current method is "software".
|
||||
struct DrawState {
|
||||
// Whether we should use software rendering methods
|
||||
// (aka raw draw), as opposed to video texture transform & fx
|
||||
bool SoftwareRender = false;
|
||||
// Whether we should redraw whole game screen each frame
|
||||
bool FullFrameRedraw = false;
|
||||
// Walk-behinds representation
|
||||
WalkBehindMethodEnum WalkBehindMethod = DrawAsSeparateSprite;
|
||||
// Whether there are currently remnants of a on-screen effect
|
||||
bool ScreenIsDirty = false;
|
||||
|
||||
// A map of shared "control blocks" per each sprite used
|
||||
// when preparing object textures. "Control block" is currently just
|
||||
// an integer which lets to check whether the object texture is in sync
|
||||
// with the sprite. When the dynamic sprite is updated or deleted,
|
||||
// the control block is marked as invalid and removed from the map;
|
||||
// but certain objects may keep the shared ptr to the old block with
|
||||
// "invalid" mark, thus they know that they must reset their texture.
|
||||
//
|
||||
// TODO: investigate an alternative of having a equivalent of
|
||||
// "shared texture" with sprite ID ref in Software renderer too,
|
||||
// which would allow to use same method of testing DDB ID for both
|
||||
// kinds of renderers, thus saving on 1 extra notification mechanism.
|
||||
std::unordered_map<sprkey_t, std::shared_ptr<uint32_t> >
|
||||
SpriteNotifyMap;
|
||||
};
|
||||
|
||||
// ObjTexture is a helper struct that pairs a raw bitmap with
|
||||
// a renderer's texture and an optional position
|
||||
struct ObjTexture {
|
||||
// Sprite ID
|
||||
uint32_t SpriteID = UINT32_MAX;
|
||||
// Raw bitmap; used for software render mode,
|
||||
// or when particular object types require generated image.
|
||||
std::unique_ptr<Shared::Bitmap> Bmp;
|
||||
// Corresponding texture, created by renderer
|
||||
Engine::IDriverDependantBitmap *Ddb = nullptr;
|
||||
// Sprite notification block: becomes invalid to notify an updated
|
||||
// or deleted sprtie
|
||||
std::shared_ptr<uint32_t> SpriteNotify;
|
||||
// Sprite's position
|
||||
Point Pos;
|
||||
// Texture's offset, *relative* to the logical sprite's position;
|
||||
// may be used in case the texture's size is different for any reason
|
||||
Point Off;
|
||||
|
||||
ObjTexture() = default;
|
||||
ObjTexture(uint32_t sprite_id, Shared::Bitmap *bmp, Engine::IDriverDependantBitmap *ddb, int x, int y, int xoff = 0, int yoff = 0)
|
||||
: SpriteID(sprite_id), Bmp(bmp), Ddb(ddb), Pos(x, y), Off(xoff, yoff) {
|
||||
}
|
||||
ObjTexture(ObjTexture &&o);
|
||||
~ObjTexture();
|
||||
|
||||
ObjTexture &operator =(ObjTexture &&o);
|
||||
|
||||
// Tests if the sprite change was notified
|
||||
inline bool IsChangeNotified() const {
|
||||
return SpriteNotify && (*SpriteNotify != SpriteID);
|
||||
}
|
||||
};
|
||||
|
||||
// ObjectCache stores cached object data, used to determine
|
||||
// if active sprite / texture should be reconstructed
|
||||
struct ObjectCache {
|
||||
std::unique_ptr<AGS::Shared::Bitmap> image;
|
||||
bool in_use = false; // CHECKME: possibly may be removed
|
||||
int sppic = 0;
|
||||
short tintr = 0, tintg = 0, tintb = 0, tintamnt = 0, tintlight = 0;
|
||||
short lightlev = 0, zoom = 0;
|
||||
bool mirrored = 0;
|
||||
int x = 0, y = 0;
|
||||
|
||||
ObjectCache() = default;
|
||||
ObjectCache(int pic_, int tintr_, int tintg_, int tintb_, int tint_amnt_, int tint_light_,
|
||||
int light_, int zoom_, bool mirror_, int posx_, int posy_)
|
||||
: sppic(pic_), tintr(tintr_), tintg(tintg_), tintb(tintb_), tintamnt(tint_amnt_), tintlight(tint_light_)
|
||||
, lightlev(light_), zoom(zoom_), mirrored(mirror_), x(posx_), y(posy_) {}
|
||||
};
|
||||
|
||||
struct DrawFPS {
|
||||
Engine::IDriverDependantBitmap *ddb = nullptr;
|
||||
std::unique_ptr<Shared::Bitmap> bmp;
|
||||
int font = -1; // in case normal font changes at runtime
|
||||
};
|
||||
|
||||
// Converts AGS color index to the actual bitmap color using game's color depth
|
||||
int MakeColor(int color_index);
|
||||
|
||||
class Viewport;
|
||||
class Camera;
|
||||
|
||||
// Initializes drawing methods and optimisation
|
||||
void init_draw_method();
|
||||
// Initializes global game drawing resources
|
||||
void init_game_drawdata();
|
||||
// Initializes drawing resources upon entering new room
|
||||
void init_room_drawdata();
|
||||
// Disposes resources related to the current drawing methods
|
||||
void dispose_draw_method();
|
||||
// Disposes global game drawing resources
|
||||
void dispose_game_drawdata();
|
||||
// Disposes any temporary resources on leaving current room
|
||||
void dispose_room_drawdata();
|
||||
// Releases all the cached textures of game objects
|
||||
void clear_drawobj_cache();
|
||||
// Updates drawing settings depending on main viewport's size and position on screen
|
||||
void on_mainviewport_changed();
|
||||
// Notifies that a new room viewport was created
|
||||
void on_roomviewport_created(int index);
|
||||
// Notifies that a new room viewport was deleted
|
||||
void on_roomviewport_deleted(int index);
|
||||
// Updates drawing settings if room viewport's position or size has changed
|
||||
void on_roomviewport_changed(Viewport *view);
|
||||
// Detects overlapping viewports, starting from the given index in z-sorted array
|
||||
void detect_roomviewport_overlaps(size_t z_index);
|
||||
// Updates drawing settings if room camera's size has changed
|
||||
void on_roomcamera_changed(Camera *cam);
|
||||
// Marks particular object as need to update the texture
|
||||
void mark_object_changed(int objid);
|
||||
// TODO: write a generic drawable/objcache system where each object
|
||||
// allocates a drawable for itself, and disposes one if being removed.
|
||||
void reset_drawobj_for_overlay(int objnum);
|
||||
// Marks all game objects which reference this sprite for redraw
|
||||
void notify_sprite_changed(int sprnum, bool deleted);
|
||||
|
||||
// whether there are currently remnants of a DisplaySpeech
|
||||
void mark_screen_dirty();
|
||||
bool is_screen_dirty();
|
||||
|
||||
// marks whole screen as needing a redraw
|
||||
void invalidate_screen();
|
||||
// marks all the camera frame as needing a redraw
|
||||
void invalidate_camera_frame(int index);
|
||||
// marks certain rectangle on screen as needing a redraw
|
||||
// in_room flag tells how to interpret the coordinates: as in-room coords or screen viewport coordinates.
|
||||
void invalidate_rect(int x1, int y1, int x2, int y2, bool in_room);
|
||||
|
||||
void mark_current_background_dirty();
|
||||
|
||||
// Avoid freeing and reallocating the memory if possible
|
||||
Shared::Bitmap *recycle_bitmap(Shared::Bitmap *bimp, int coldep, int wid, int hit, bool make_transparent = false);
|
||||
void recycle_bitmap(std::unique_ptr<Shared::Bitmap> &bimp, int coldep, int wid, int hit, bool make_transparent = false);
|
||||
Engine::IDriverDependantBitmap* recycle_ddb_sprite(Engine::IDriverDependantBitmap *ddb, uint32_t sprite_id, Shared::Bitmap *source, bool has_alpha = false, bool opaque = false);
|
||||
inline Engine::IDriverDependantBitmap* recycle_ddb_bitmap(Engine::IDriverDependantBitmap *ddb, Shared::Bitmap *source, bool has_alpha = false, bool opaque = false) {
|
||||
return recycle_ddb_sprite(ddb, UINT32_MAX, source, has_alpha, opaque);
|
||||
}
|
||||
// Draw everything
|
||||
void render_graphics(Engine::IDriverDependantBitmap *extraBitmap = nullptr, int extraX = 0, int extraY = 0);
|
||||
// Construct game scene, scheduling drawing list for the renderer
|
||||
void construct_game_scene(bool full_redraw = false);
|
||||
// Construct final game screen elements; updates and draws mouse cursor
|
||||
void construct_game_screen_overlay(bool draw_mouse = true);
|
||||
// Construct engine overlay with debugging tools (fps, console)
|
||||
void construct_engine_overlay();
|
||||
// Clears black game borders in legacy letterbox mode
|
||||
void clear_letterbox_borders();
|
||||
|
||||
void debug_draw_room_mask(RoomAreaMask mask);
|
||||
void debug_draw_movelist(int charnum);
|
||||
void update_room_debug();
|
||||
|
||||
void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
|
||||
void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,
|
||||
Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
|
||||
void draw_sprite_slot_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, int src_slot,
|
||||
Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
|
||||
void draw_gui_sprite(Shared::Bitmap *ds, int pic, int x, int y, bool use_alpha = true, Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha);
|
||||
void draw_gui_sprite_v330(Shared::Bitmap *ds, int pic, int x, int y, bool use_alpha = true, Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha);
|
||||
void draw_gui_sprite(Shared::Bitmap *ds, bool use_alpha, int xpos, int ypos,
|
||||
Shared::Bitmap *image, bool src_has_alpha, Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
|
||||
// Puts a pixel of certain color, scales it if running in upscaled resolution (legacy feature)
|
||||
void putpixel_scaled(Shared::Bitmap *ds, int x, int y, int col);
|
||||
|
||||
// Render game on screen
|
||||
void render_to_screen();
|
||||
// Callbacks for the graphics driver
|
||||
void draw_game_screen_callback();
|
||||
void GfxDriverOnInitCallback(void *data);
|
||||
bool GfxDriverSpriteEvtCallback(int evt, int data);
|
||||
|
||||
// Create the actsps[objid] image with the object drawn correctly.
|
||||
// Returns true if nothing at all has changed and actsps is still
|
||||
// intact from last time; false otherwise.
|
||||
// Hardware-accelerated do not require altering the raw bitmap itself,
|
||||
// so they only detect whether the sprite ID itself has changed.
|
||||
// Software renderers modify the cached bitmap whenever any visual
|
||||
// effect changes (scaling, tint, etc).
|
||||
// * force_software option forces HW renderers to construct the image
|
||||
// in software mode as well.
|
||||
bool construct_object_gfx(int objid, bool force_software);
|
||||
bool construct_char_gfx(int charid, bool force_software);
|
||||
// Returns a cached character image prepared for the render
|
||||
Shared::Bitmap *get_cached_character_image(int charid);
|
||||
// Returns a cached object image prepared for the render
|
||||
Shared::Bitmap *get_cached_object_image(int objid);
|
||||
// Adds a walk-behind sprite to the list for the given slot
|
||||
// (reuses existing texture if possible)
|
||||
void add_walkbehind_image(size_t index, Shared::Bitmap *bmp, int x, int y);
|
||||
|
||||
void draw_and_invalidate_text(Shared::Bitmap *ds, int x1, int y1, int font, color_t text_color, const char *text);
|
||||
|
||||
void setpal();
|
||||
|
||||
// These functions are converting coordinates between data resolution and
|
||||
// game resolution units. The first are units used by game data and script,
|
||||
// and second define the game's screen resolution, sprite and font sizes.
|
||||
// This conversion is done before anything else (like moving from room to
|
||||
// viewport on screen, or scaling game further in the window by the graphic
|
||||
// renderer).
|
||||
int get_fixed_pixel_size(int pixels);
|
||||
// coordinate conversion data,script ---> final game resolution
|
||||
extern int data_to_game_coord(int coord);
|
||||
extern void data_to_game_coords(int *x, int *y);
|
||||
extern void data_to_game_round_up(int *x, int *y);
|
||||
// coordinate conversion final game resolution ---> data,script
|
||||
extern int game_to_data_coord(int coord);
|
||||
extern void game_to_data_coords(int &x, int &y);
|
||||
extern int game_to_data_round_up(int coord);
|
||||
// convert contextual data coordinates to final game resolution
|
||||
extern void ctx_data_to_game_coord(int &x, int &y, bool hires_ctx);
|
||||
extern void ctx_data_to_game_size(int &x, int &y, bool hires_ctx);
|
||||
extern int ctx_data_to_game_size(int size, bool hires_ctx);
|
||||
extern int game_to_ctx_data_size(int size, bool hires_ctx);
|
||||
// This function converts game coordinates coming from script to the actual game resolution.
|
||||
extern void defgame_to_finalgame_coords(int &x, int &y);
|
||||
|
||||
// Creates bitmap of a format compatible with the gfxdriver;
|
||||
// if col_depth is 0, uses game's native color depth.
|
||||
Shared::Bitmap *CreateCompatBitmap(int width, int height, int col_depth = 0);
|
||||
// Checks if the bitmap is compatible with the gfxdriver;
|
||||
// returns same bitmap or its copy of a compatible format.
|
||||
Shared::Bitmap *ReplaceBitmapWithSupportedFormat(Shared::Bitmap *bitmap);
|
||||
// Checks if the bitmap needs any kind of adjustments before it may be used
|
||||
// in AGS sprite operations. Also handles number of certain special cases
|
||||
// (old systems or uncommon gfx modes, and similar stuff).
|
||||
// Original bitmap **gets deleted** if a new bitmap had to be created.
|
||||
Shared::Bitmap *PrepareSpriteForUse(Shared::Bitmap *bitmap, bool has_alpha);
|
||||
// Same as above, but compatible for std::shared_ptr.
|
||||
Shared::PBitmap PrepareSpriteForUse(Shared::PBitmap bitmap, bool has_alpha);
|
||||
// Makes a screenshot corresponding to the last screen render and returns it as a bitmap
|
||||
// of the requested width and height and game's native color depth.
|
||||
Shared::Bitmap *CopyScreenIntoBitmap(int width, int height, const Rect *src_rect = nullptr,
|
||||
bool at_native_res = false, uint32_t batch_skip_filter = 0u);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
409
engines/ags/engine/ac/draw_software.cpp
Normal file
409
engines/ags/engine/ac/draw_software.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Software drawing component. Optimizes drawing for software renderer using
|
||||
// dirty rectangles technique.
|
||||
//
|
||||
// TODO: do research/profiling to find out if this dirty rectangles thing
|
||||
// is still giving ANY notable performance boost at all.
|
||||
//
|
||||
// TODO: would that give any benefit to reorganize the code and move dirty
|
||||
// rectangles into SoftwareGraphicDriver?
|
||||
// Alternatively: we could pass dirty rects struct pointer and room background
|
||||
// DDB when calling BeginSpriteBatch(). Driver itself could be calling
|
||||
// update_invalid_region(). That will keep gfx driver's changes to minimum.
|
||||
//
|
||||
// NOTE: this code, including structs and functions, has underwent several
|
||||
// iterations of changes. Originally it was meant to perform full transform
|
||||
// of dirty rects right away, but later I realized it won't work that way
|
||||
// because a) Allegro does not support scaling bitmaps over destination with
|
||||
// different colour depth (which may be a case when running 16-bit game),
|
||||
// and b) Allegro does not support scaling and rotating of sprites with
|
||||
// blending and lighting at the same time which means that room objects have
|
||||
// to be drawn upon non-scaled background first. Possibly some of the code
|
||||
// below may be therefore simplified.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/engine/ac/draw_software.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/shared/util/scaling.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
using namespace AGS::Engine;
|
||||
|
||||
IRSpan::IRSpan()
|
||||
: x1(0), x2(0) {
|
||||
}
|
||||
|
||||
IRRow::IRRow()
|
||||
: numSpans(0) {
|
||||
}
|
||||
|
||||
int IRSpan::mergeSpan(int tx1, int tx2) {
|
||||
if ((tx1 > x2) || (tx2 < x1))
|
||||
return 0;
|
||||
// overlapping, increase the span
|
||||
if (tx1 < x1)
|
||||
x1 = tx1;
|
||||
if (tx2 > x2)
|
||||
x2 = tx2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
DirtyRects::DirtyRects()
|
||||
: NumDirtyRegions(0) {
|
||||
}
|
||||
|
||||
bool DirtyRects::IsInit() const {
|
||||
return DirtyRows.size() > 0;
|
||||
}
|
||||
|
||||
void DirtyRects::Init(const Size &surf_size, const Rect &viewport) {
|
||||
int height = surf_size.Height;
|
||||
if (SurfaceSize != surf_size) {
|
||||
Destroy();
|
||||
SurfaceSize = surf_size;
|
||||
DirtyRows.resize(height);
|
||||
|
||||
NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
for (int i = 0; i < height; ++i)
|
||||
DirtyRows[i].numSpans = 0;
|
||||
}
|
||||
|
||||
Viewport = viewport;
|
||||
Room2Screen.Init(surf_size, viewport);
|
||||
Screen2DirtySurf.Init(viewport, RectWH(0, 0, surf_size.Width, surf_size.Height));
|
||||
}
|
||||
|
||||
void DirtyRects::SetSurfaceOffsets(int x, int y) {
|
||||
Room2Screen.SetSrcOffsets(x, y);
|
||||
}
|
||||
|
||||
void DirtyRects::Destroy() {
|
||||
DirtyRows.clear();
|
||||
NumDirtyRegions = 0;
|
||||
}
|
||||
|
||||
void DirtyRects::Reset() {
|
||||
NumDirtyRegions = 0;
|
||||
|
||||
for (size_t i = 0; i < DirtyRows.size(); ++i)
|
||||
DirtyRows[i].numSpans = 0;
|
||||
}
|
||||
|
||||
void dispose_invalid_regions(bool /* room_only */) {
|
||||
_GP(RoomCamRects).clear();
|
||||
_GP(RoomCamPositions).clear();
|
||||
}
|
||||
|
||||
void set_invalidrects_globaloffs(int x, int y) {
|
||||
_GP(GlobalOffs) = Point(x, y);
|
||||
}
|
||||
|
||||
void init_invalid_regions(int view_index, const Size &surf_size, const Rect &viewport) {
|
||||
if (view_index < 0) {
|
||||
_GP(BlackRects).Init(surf_size, viewport);
|
||||
} else {
|
||||
if (_GP(RoomCamRects).size() <= (size_t)view_index) {
|
||||
_GP(RoomCamRects).resize(view_index + 1);
|
||||
_GP(RoomCamPositions).resize(view_index + 1);
|
||||
}
|
||||
_GP(RoomCamRects)[view_index].Init(surf_size, viewport);
|
||||
_GP(RoomCamPositions)[view_index] = std::make_pair(-1000, -1000);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_invalid_regions(int view_index) {
|
||||
if (view_index >= 0) {
|
||||
_GP(RoomCamRects).erase(_GP(RoomCamRects).begin() + view_index);
|
||||
_GP(RoomCamPositions).erase(_GP(RoomCamPositions).begin() + view_index);
|
||||
}
|
||||
}
|
||||
|
||||
void set_invalidrects_cameraoffs(int view_index, int x, int y) {
|
||||
if (view_index < 0) {
|
||||
_GP(BlackRects).SetSurfaceOffsets(x, y);
|
||||
return;
|
||||
} else {
|
||||
_GP(RoomCamRects)[view_index].SetSurfaceOffsets(x, y);
|
||||
}
|
||||
|
||||
int &posxwas = _GP(RoomCamPositions)[view_index].first;
|
||||
int &posywas = _GP(RoomCamPositions)[view_index].second;
|
||||
if ((x != posxwas) || (y != posywas)) {
|
||||
invalidate_all_camera_rects(view_index);
|
||||
posxwas = x;
|
||||
posywas = y;
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate_all_rects() {
|
||||
for (auto &rects : _GP(RoomCamRects)) {
|
||||
if (!IsRectInsideRect(rects.Viewport, _GP(BlackRects).Viewport))
|
||||
_GP(BlackRects).NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
rects.NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate_all_camera_rects(int view_index) {
|
||||
if (view_index < 0)
|
||||
return;
|
||||
_GP(RoomCamRects)[view_index].NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
}
|
||||
|
||||
void invalidate_rect_on_surf(int x1, int y1, int x2, int y2, DirtyRects &rects) {
|
||||
if (rects.DirtyRows.size() == 0)
|
||||
return;
|
||||
if (rects.NumDirtyRegions >= MAXDIRTYREGIONS) {
|
||||
// too many invalid rectangles, just mark the whole thing dirty
|
||||
rects.NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x1 > x2 || y1 > y2)
|
||||
return;
|
||||
|
||||
int a;
|
||||
|
||||
const Size &surfsz = rects.SurfaceSize;
|
||||
|
||||
if (x1 >= surfsz.Width || y1 >= surfsz.Height || x2 < 0 || y2 < 0)
|
||||
return;
|
||||
|
||||
if (x2 >= surfsz.Width) x2 = surfsz.Width - 1;
|
||||
if (y2 >= surfsz.Height) y2 = surfsz.Height - 1;
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
rects.NumDirtyRegions++;
|
||||
|
||||
// ** Span code
|
||||
std::vector<IRRow> &dirtyRow = rects.DirtyRows;
|
||||
int s, foundOne;
|
||||
// add this rect to the list for this row
|
||||
for (a = y1; a <= y2; a++) {
|
||||
foundOne = 0;
|
||||
for (s = 0; s < dirtyRow[a].numSpans; s++) {
|
||||
if (dirtyRow[a].span[s].mergeSpan(x1, x2)) {
|
||||
foundOne = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundOne) {
|
||||
// we were merged into a span, so we're ok
|
||||
int t;
|
||||
// check whether now two of the spans overlap each other
|
||||
// in which case merge them
|
||||
for (s = 0; s < dirtyRow[a].numSpans; s++) {
|
||||
for (t = s + 1; t < dirtyRow[a].numSpans; t++) {
|
||||
if (dirtyRow[a].span[s].mergeSpan(dirtyRow[a].span[t].x1, dirtyRow[a].span[t].x2)) {
|
||||
dirtyRow[a].numSpans--;
|
||||
for (int u = t; u < dirtyRow[a].numSpans; u++)
|
||||
dirtyRow[a].span[u] = dirtyRow[a].span[u + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dirtyRow[a].numSpans < MAX_SPANS_PER_ROW) {
|
||||
dirtyRow[a].span[dirtyRow[a].numSpans].x1 = x1;
|
||||
dirtyRow[a].span[dirtyRow[a].numSpans].x2 = x2;
|
||||
dirtyRow[a].numSpans++;
|
||||
} else {
|
||||
// didn't fit in an existing span, and there are none spare
|
||||
int nearestDist = 99999, nearestWas = -1, extendLeft = 0;
|
||||
// find the nearest span, and enlarge that to include this rect
|
||||
for (s = 0; s < dirtyRow[a].numSpans; s++) {
|
||||
int tleft = dirtyRow[a].span[s].x1 - x2;
|
||||
if ((tleft > 0) && (tleft < nearestDist)) {
|
||||
nearestDist = tleft;
|
||||
nearestWas = s;
|
||||
extendLeft = 1;
|
||||
}
|
||||
int tright = x1 - dirtyRow[a].span[s].x2;
|
||||
if ((tright > 0) && (tright < nearestDist)) {
|
||||
nearestDist = tright;
|
||||
nearestWas = s;
|
||||
extendLeft = 0;
|
||||
}
|
||||
}
|
||||
assert(nearestWas >= 0);
|
||||
if (extendLeft)
|
||||
dirtyRow[a].span[nearestWas].x1 = x1;
|
||||
else
|
||||
dirtyRow[a].span[nearestWas].x2 = x2;
|
||||
}
|
||||
}
|
||||
// ** End span code
|
||||
//}
|
||||
}
|
||||
|
||||
void invalidate_rect_ds(DirtyRects &rects, int x1, int y1, int x2, int y2, bool in_room) {
|
||||
if (!in_room) {
|
||||
// TODO: for most opimisation (esp. with multiple viewports) should perhaps
|
||||
// split/cut parts of the original rectangle which overlap room viewport(s).
|
||||
Rect r(x1, y1, x2, y2);
|
||||
// If overlay is NOT completely over the room, then invalidate black rect
|
||||
if (!IsRectInsideRect(rects.Viewport, r))
|
||||
invalidate_rect_on_surf(x1, y1, x2, y2, _GP(BlackRects));
|
||||
// If overlay is NOT intersecting room viewport at all, then stop
|
||||
if (!AreRectsIntersecting(rects.Viewport, r))
|
||||
return;
|
||||
|
||||
// Transform from screen to room coordinates through the known viewport
|
||||
x1 = rects.Screen2DirtySurf.X.ScalePt(x1);
|
||||
x2 = rects.Screen2DirtySurf.X.ScalePt(x2);
|
||||
y1 = rects.Screen2DirtySurf.Y.ScalePt(y1);
|
||||
y2 = rects.Screen2DirtySurf.Y.ScalePt(y2);
|
||||
} else {
|
||||
// Transform only from camera pos to room background
|
||||
x1 -= rects.Room2Screen.X.GetSrcOffset();
|
||||
y1 -= rects.Room2Screen.Y.GetSrcOffset();
|
||||
x2 -= rects.Room2Screen.X.GetSrcOffset();
|
||||
y2 -= rects.Room2Screen.Y.GetSrcOffset();
|
||||
}
|
||||
|
||||
invalidate_rect_on_surf(x1, y1, x2, y2, rects);
|
||||
}
|
||||
|
||||
void invalidate_rect_ds(int x1, int y1, int x2, int y2, bool in_room) {
|
||||
if (!in_room) { // convert from game viewport to global screen coords
|
||||
x1 += _GP(GlobalOffs).X;
|
||||
x2 += _GP(GlobalOffs).X;
|
||||
y1 += _GP(GlobalOffs).Y;
|
||||
y2 += _GP(GlobalOffs).Y;
|
||||
}
|
||||
|
||||
for (auto &rects : _GP(RoomCamRects))
|
||||
invalidate_rect_ds(rects, x1, y1, x2, y2, in_room);
|
||||
}
|
||||
|
||||
void invalidate_rect_global(int x1, int y1, int x2, int y2) {
|
||||
for (auto &rects : _GP(RoomCamRects))
|
||||
invalidate_rect_ds(rects, x1, y1, x2, y2, false);
|
||||
}
|
||||
|
||||
// Note that this function is denied to perform any kind of scaling or other transformation
|
||||
// other than blitting with offset. This is mainly because destination could be a 32-bit virtual screen
|
||||
// while room background was 16-bit and Allegro lib does not support stretching between colour depths.
|
||||
// The no_transform flag here means essentially "no offset", and indicates that the function
|
||||
// must blit src on ds at 0;0. Otherwise, actual Viewport offset is used.
|
||||
void update_invalid_region(Bitmap *ds, Bitmap *src, const DirtyRects &rects, bool no_transform) {
|
||||
if (rects.NumDirtyRegions == 0)
|
||||
return;
|
||||
|
||||
if (!no_transform)
|
||||
ds->SetClip(rects.Viewport);
|
||||
|
||||
const int src_x = rects.Room2Screen.X.GetSrcOffset();
|
||||
const int src_y = rects.Room2Screen.Y.GetSrcOffset();
|
||||
const int dst_x = no_transform ? 0 : rects.Viewport.Left;
|
||||
const int dst_y = no_transform ? 0 : rects.Viewport.Top;
|
||||
|
||||
if (rects.NumDirtyRegions == WHOLESCREENDIRTY) {
|
||||
ds->Blit(src, src_x, src_y, dst_x, dst_y, rects.SurfaceSize.Width, rects.SurfaceSize.Height);
|
||||
} else {
|
||||
const std::vector<IRRow> &dirtyRow = rects.DirtyRows;
|
||||
const int surf_height = rects.SurfaceSize.Height;
|
||||
// TODO: is this IsMemoryBitmap check is still relevant?
|
||||
// If bitmaps properties match and no transform required other than linear offset
|
||||
if (src->GetColorDepth() == ds->GetColorDepth()) {
|
||||
const int bypp = src->GetBPP();
|
||||
// do the fast memory copy
|
||||
for (int i = 0; i < surf_height; i++) {
|
||||
const uint8_t *src_scanline = src->GetScanLine(i + src_y);
|
||||
uint8_t *dst_scanline = ds->GetScanLineForWriting(i + dst_y);
|
||||
const IRRow &dirty_row = dirtyRow[i];
|
||||
for (int k = 0; k < dirty_row.numSpans; k++) {
|
||||
int tx1 = dirty_row.span[k].x1;
|
||||
int tx2 = dirty_row.span[k].x2;
|
||||
memcpy(&dst_scanline[(tx1 + dst_x) * bypp], &src_scanline[(tx1 + src_x) * bypp], ((tx2 - tx1) + 1) * bypp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If has to use Blit, but still must draw with no transform but offset
|
||||
else {
|
||||
// do fast copy without transform
|
||||
for (int i = 0, rowsInOne = 1; i < surf_height; i += rowsInOne, rowsInOne = 1) {
|
||||
// if there are rows with identical masks, do them all in one go
|
||||
// TODO: what is this for? may this be done at the invalidate_rect merge step?
|
||||
while ((i + rowsInOne < surf_height) && (memcmp(&dirtyRow[i], &dirtyRow[i + rowsInOne], sizeof(IRRow)) == 0))
|
||||
rowsInOne++;
|
||||
|
||||
const IRRow &dirty_row = dirtyRow[i];
|
||||
for (int k = 0; k < dirty_row.numSpans; k++) {
|
||||
int tx1 = dirty_row.span[k].x1;
|
||||
int tx2 = dirty_row.span[k].x2;
|
||||
ds->Blit(src, tx1 + src_x, i + src_y, tx1 + dst_x, i + dst_y, (tx2 - tx1) + 1, rowsInOne);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_invalid_region(Bitmap *ds, color_t fill_color, const DirtyRects &rects) {
|
||||
ds->SetClip(rects.Viewport);
|
||||
|
||||
if (rects.NumDirtyRegions == WHOLESCREENDIRTY) {
|
||||
ds->FillRect(rects.Viewport, fill_color);
|
||||
} else {
|
||||
const std::vector<IRRow> &dirtyRow = rects.DirtyRows;
|
||||
const int surf_height = rects.SurfaceSize.Height;
|
||||
{
|
||||
const AGS::Shared::PlaneScaling &tf = rects.Room2Screen;
|
||||
for (int i = 0, rowsInOne = 1; i < surf_height; i += rowsInOne, rowsInOne = 1) {
|
||||
// if there are rows with identical masks, do them all in one go
|
||||
// TODO: what is this for? may this be done at the invalidate_rect merge step?
|
||||
while ((i + rowsInOne < surf_height) && (memcmp(&dirtyRow[i], &dirtyRow[i + rowsInOne], sizeof(IRRow)) == 0))
|
||||
rowsInOne++;
|
||||
|
||||
const IRRow &dirty_row = dirtyRow[i];
|
||||
for (int k = 0; k < dirty_row.numSpans; k++) {
|
||||
Rect src_r(dirty_row.span[k].x1, i, dirty_row.span[k].x2, i + rowsInOne - 1);
|
||||
Rect dst_r = tf.ScaleRange(src_r);
|
||||
ds->FillRect(dst_r, fill_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_black_invreg_and_reset(Bitmap *ds) {
|
||||
if (!_GP(BlackRects).IsInit())
|
||||
return;
|
||||
update_invalid_region(ds, (color_t)0, _GP(BlackRects));
|
||||
_GP(BlackRects).Reset();
|
||||
}
|
||||
|
||||
void update_room_invreg_and_reset(int view_index, Bitmap *ds, Bitmap *src, bool no_transform) {
|
||||
if (view_index < 0 || _GP(RoomCamRects).size() == 0)
|
||||
return;
|
||||
|
||||
update_invalid_region(ds, src, _GP(RoomCamRects)[view_index], no_transform);
|
||||
_GP(RoomCamRects)[view_index].Reset();
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
116
engines/ags/engine/ac/draw_software.h
Normal file
116
engines/ags/engine/ac/draw_software.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Software drawing component. Optimizes drawing for software renderer using
|
||||
// dirty rectangles technique.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DRAW_SOFTWARE_H
|
||||
#define AGS_ENGINE_AC_DRAW_SOFTWARE_H
|
||||
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/engine/gfx/ddb.h"
|
||||
#include "ags/shared/util/geometry.h"
|
||||
#include "ags/shared/util/scaling.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using AGS::Shared::PlaneScaling;
|
||||
|
||||
// TODO: choose these values depending on game resolution?
|
||||
#define MAXDIRTYREGIONS 25
|
||||
#define WHOLESCREENDIRTY (MAXDIRTYREGIONS + 5)
|
||||
#define MAX_SPANS_PER_ROW 4
|
||||
|
||||
// Dirty rects store coordinate values in the coordinate system of a camera surface,
|
||||
// where coords always span from 0,0 to surface width,height.
|
||||
// Converting from room to dirty rects would require subtracting room camera offsets.
|
||||
struct IRSpan {
|
||||
int x1, x2;
|
||||
int mergeSpan(int tx1, int tx2);
|
||||
|
||||
IRSpan();
|
||||
};
|
||||
|
||||
struct IRRow {
|
||||
IRSpan span[MAX_SPANS_PER_ROW];
|
||||
int numSpans;
|
||||
|
||||
IRRow();
|
||||
};
|
||||
|
||||
struct DirtyRects {
|
||||
// Size of the surface managed by this dirty rects object
|
||||
Size SurfaceSize;
|
||||
// Where the surface is rendered on screen
|
||||
Rect Viewport;
|
||||
// Room -> screen coordinate transformation
|
||||
PlaneScaling Room2Screen;
|
||||
// Screen -> dirty surface rect
|
||||
// The dirty rects are saved in coordinates limited to (0,0)->(camera size) rather than room or screen coords
|
||||
PlaneScaling Screen2DirtySurf;
|
||||
|
||||
std::vector<IRRow> DirtyRows;
|
||||
Rect DirtyRegions[MAXDIRTYREGIONS];
|
||||
size_t NumDirtyRegions;
|
||||
|
||||
DirtyRects();
|
||||
bool IsInit() const;
|
||||
// Initialize dirty rects for the given surface size
|
||||
void Init(const Size &surf_size, const Rect &viewport);
|
||||
void SetSurfaceOffsets(int x, int y);
|
||||
// Delete dirty rects
|
||||
void Destroy();
|
||||
// Mark all surface as tidy
|
||||
void Reset();
|
||||
};
|
||||
|
||||
// Sets global viewport offset (used for legacy letterbox)
|
||||
void set_invalidrects_globaloffs(int x, int y);
|
||||
// Inits dirty rects array for the given room camera/viewport pair
|
||||
// View_index indicates the room viewport (>= 0) or the main viewport (-1)
|
||||
void init_invalid_regions(int view_index, const Size &surf_size, const Rect &viewport);
|
||||
// Deletes dirty rects for particular index
|
||||
void delete_invalid_regions(int view_index);
|
||||
// Disposes dirty rects arrays
|
||||
void dispose_invalid_regions(bool room_only);
|
||||
// Update the coordinate transformation for the particular dirty rects object
|
||||
void set_invalidrects_cameraoffs(int view_index, int x, int y);
|
||||
// Mark the whole screen dirty
|
||||
void invalidate_all_rects();
|
||||
// Mark the whole camera surface dirty
|
||||
void invalidate_all_camera_rects(int view_index);
|
||||
// Mark certain rectangle dirty; in_room tells if coordinates are room viewport or screen coords
|
||||
void invalidate_rect_ds(int x1, int y1, int x2, int y2, bool in_room);
|
||||
// Mark rectangle dirty, treat pos as global screen coords (not offset by legacy letterbox mode)
|
||||
void invalidate_rect_global(int x1, int y1, int x2, int y2);
|
||||
// Paints the black screen background in the regions marked as dirty
|
||||
void update_black_invreg_and_reset(AGS::Shared::Bitmap *ds);
|
||||
// Copies the room regions marked as dirty from source (src) to destination (ds) with the given offset (x, y)
|
||||
// no_transform flag tells the system that the regions should be plain copied to the ds.
|
||||
void update_room_invreg_and_reset(int view_index, AGS::Shared::Bitmap *ds, AGS::Shared::Bitmap *src, bool no_transform);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
590
engines/ags/engine/ac/drawing_surface.cpp
Normal file
590
engines/ags/engine/ac/drawing_surface.cpp
Normal file
@@ -0,0 +1,590 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/draw.h"
|
||||
#include "ags/engine/ac/drawing_surface.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/engine/ac/display.h"
|
||||
#include "ags/engine/ac/game.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/engine/ac/global_translation.h"
|
||||
#include "ags/engine/ac/room_object.h"
|
||||
#include "ags/engine/ac/room_status.h"
|
||||
#include "ags/engine/ac/string.h"
|
||||
#include "ags/engine/ac/walk_behind.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/shared/gfx/gfx_def.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/engine/gfx/gfx_util.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
using namespace AGS::Engine;
|
||||
|
||||
// ** SCRIPT DRAWINGSURFACE OBJECT
|
||||
|
||||
void DrawingSurface_Release(ScriptDrawingSurface *sds) {
|
||||
if (sds->roomBackgroundNumber >= 0) {
|
||||
if (sds->modified) {
|
||||
if (sds->roomBackgroundNumber == _GP(play).bg_frame) {
|
||||
invalidate_screen();
|
||||
mark_current_background_dirty();
|
||||
}
|
||||
_GP(play).raw_modified[sds->roomBackgroundNumber] = 1;
|
||||
}
|
||||
|
||||
sds->roomBackgroundNumber = -1;
|
||||
}
|
||||
if (sds->roomMaskType > kRoomAreaNone) {
|
||||
if (sds->roomMaskType == kRoomAreaWalkBehind) {
|
||||
walkbehinds_recalc();
|
||||
}
|
||||
sds->roomMaskType = kRoomAreaNone;
|
||||
}
|
||||
if (sds->dynamicSpriteNumber >= 0) {
|
||||
if (sds->modified) {
|
||||
game_sprite_updated(sds->dynamicSpriteNumber);
|
||||
}
|
||||
|
||||
sds->dynamicSpriteNumber = -1;
|
||||
}
|
||||
if (sds->dynamicSurfaceNumber >= 0) {
|
||||
_G(dynamicallyCreatedSurfaces)[sds->dynamicSurfaceNumber].reset();
|
||||
sds->dynamicSurfaceNumber = -1;
|
||||
}
|
||||
sds->modified = 0;
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::PointToGameResolution(int *xcoord, int *ycoord) {
|
||||
ctx_data_to_game_coord(*xcoord, *ycoord, highResCoordinates != 0);
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::SizeToGameResolution(int *width, int *height) {
|
||||
ctx_data_to_game_size(*width, *height, highResCoordinates != 0);
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::SizeToGameResolution(int *valueToAdjust) {
|
||||
*valueToAdjust = ctx_data_to_game_size(*valueToAdjust, highResCoordinates != 0);
|
||||
}
|
||||
|
||||
// convert actual co-ordinate back to what the script is expecting
|
||||
void ScriptDrawingSurface::SizeToDataResolution(int *valueToAdjust) {
|
||||
*valueToAdjust = game_to_ctx_data_size(*valueToAdjust, highResCoordinates != 0);
|
||||
}
|
||||
|
||||
ScriptDrawingSurface *DrawingSurface_CreateCopy(ScriptDrawingSurface *sds) {
|
||||
Bitmap *sourceBitmap = sds->GetBitmapSurface();
|
||||
|
||||
for (int i = 0; i < MAX_DYNAMIC_SURFACES; i++) {
|
||||
if (_G(dynamicallyCreatedSurfaces)[i] == nullptr) {
|
||||
_G(dynamicallyCreatedSurfaces)[i].reset(BitmapHelper::CreateBitmapCopy(sourceBitmap));
|
||||
ScriptDrawingSurface *newSurface = new ScriptDrawingSurface();
|
||||
newSurface->dynamicSurfaceNumber = i;
|
||||
newSurface->hasAlphaChannel = sds->hasAlphaChannel;
|
||||
ccRegisterManagedObject(newSurface, newSurface);
|
||||
return newSurface;
|
||||
}
|
||||
}
|
||||
|
||||
quit("!DrawingSurface.CreateCopy: too many copied surfaces created");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawImageImpl(ScriptDrawingSurface *sds, Bitmap *src,
|
||||
int dst_x, int dst_y, int trans, int dst_width, int dst_height,
|
||||
int src_x, int src_y, int src_width, int src_height, int sprite_id, bool src_has_alpha) {
|
||||
Bitmap *ds = sds->GetBitmapSurface();
|
||||
if (src == ds) {
|
||||
} // ignore for now; bitmap lib supports, and may be used for effects
|
||||
/* debug_script_warn("DrawingSurface.DrawImage: drawing onto itself"); */
|
||||
if (src->GetColorDepth() != ds->GetColorDepth()) {
|
||||
if (sprite_id >= 0)
|
||||
debug_script_warn("DrawImage: Sprite %d colour depth %d-bit not same as destination depth %d-bit", sprite_id, src->GetColorDepth(), ds->GetColorDepth());
|
||||
else
|
||||
debug_script_warn("DrawImage: Source image colour depth %d-bit not same as destination depth %d-bit", src->GetColorDepth(), ds->GetColorDepth());
|
||||
}
|
||||
if ((trans < 0) || (trans > 100))
|
||||
debug_script_warn("DrawingSurface.DrawImage: invalid transparency %d, range is %d - %d", trans, 0, 100);
|
||||
trans = Math::Clamp(trans, 0, 100);
|
||||
|
||||
if (trans == 100)
|
||||
return; // fully transparent
|
||||
if (dst_width < 1 || dst_height < 1 || src_width < 1 || src_height < 1)
|
||||
return; // invalid src or dest rectangles
|
||||
|
||||
// Setup uninitialized arguments; convert coordinates for legacy script mode
|
||||
if (dst_width == SCR_NO_VALUE) {
|
||||
dst_width = src->GetWidth();
|
||||
} else {
|
||||
sds->SizeToGameResolution(&dst_width);
|
||||
}
|
||||
if (dst_height == SCR_NO_VALUE) {
|
||||
dst_height = src->GetHeight();
|
||||
} else {
|
||||
sds->SizeToGameResolution(&dst_height);
|
||||
}
|
||||
|
||||
if (src_x == SCR_NO_VALUE) {
|
||||
src_x = 0;
|
||||
}
|
||||
if (src_y == SCR_NO_VALUE) {
|
||||
src_y = 0;
|
||||
}
|
||||
sds->PointToGameResolution(&src_x, &src_y);
|
||||
if (src_width == SCR_NO_VALUE) {
|
||||
src_width = src->GetWidth();
|
||||
} else {
|
||||
sds->SizeToGameResolution(&src_width);
|
||||
}
|
||||
if (src_height == SCR_NO_VALUE) {
|
||||
src_height = src->GetHeight();
|
||||
} else {
|
||||
sds->SizeToGameResolution(&src_height);
|
||||
}
|
||||
|
||||
sds->PointToGameResolution(&dst_x, &dst_y);
|
||||
|
||||
if (dst_x >= ds->GetWidth() || dst_x + dst_width <= 0 || dst_y >= ds->GetHeight() || dst_y + dst_height <= 0 ||
|
||||
src_x >= src->GetWidth() || src_x + src_width <= 0 || src_y >= src->GetHeight() || src_y + src_height <= 0)
|
||||
return; // source or destination rects lie completely off surface
|
||||
// Clamp the source rect to the valid limits to prevent exceptions (ignore dest, bitmap drawing deals with that)
|
||||
Math::ClampLength(src_x, src_width, 0, src->GetWidth());
|
||||
Math::ClampLength(src_y, src_height, 0, src->GetHeight());
|
||||
|
||||
// TODO: possibly optimize by not making a stretched intermediate bitmap
|
||||
// if simpler blit/draw_sprite could be called (no translucency with alpha channel).
|
||||
std::unique_ptr<Bitmap> conv_src;
|
||||
if (dst_width != src->GetWidth() || dst_height != src->GetHeight() ||
|
||||
src_width != src->GetWidth() || src_height != src->GetHeight()) {
|
||||
// Resize and/or partial copy specified
|
||||
conv_src.reset(BitmapHelper::CreateBitmap(dst_width, dst_height, src->GetColorDepth()));
|
||||
conv_src->StretchBlt(src,
|
||||
RectWH(src_x, src_y, src_width, src_height),
|
||||
RectWH(0, 0, dst_width, dst_height));
|
||||
|
||||
src = conv_src.get();
|
||||
}
|
||||
|
||||
ds = sds->StartDrawing();
|
||||
|
||||
draw_sprite_support_alpha(ds, sds->hasAlphaChannel != 0, dst_x, dst_y, src, src_has_alpha,
|
||||
kBlendMode_Alpha, GfxDef::Trans100ToAlpha255(trans));
|
||||
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawImage(ScriptDrawingSurface *sds,
|
||||
int dst_x, int dst_y, int slot, int trans,
|
||||
int dst_width, int dst_height,
|
||||
int src_x, int src_y, int src_width, int src_height) {
|
||||
if ((slot < 0) || (!_GP(spriteset).DoesSpriteExist(slot)))
|
||||
quit("!DrawingSurface.DrawImage: invalid sprite slot number specified");
|
||||
DrawingSurface_DrawImageImpl(sds, _GP(spriteset)[slot], dst_x, dst_y, trans, dst_width, dst_height,
|
||||
src_x, src_y, src_width, src_height, slot, (_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawImage6(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height) {
|
||||
DrawingSurface_DrawImage(sds, xx, yy, slot, trans, width, height, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawSurface(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans,
|
||||
int dst_x, int dst_y, int dst_width, int dst_height,
|
||||
int src_x, int src_y, int src_width, int src_height) {
|
||||
DrawingSurface_DrawImageImpl(target, source->GetBitmapSurface(), dst_x, dst_y, trans, dst_width, dst_height,
|
||||
src_x, src_y, src_width, src_height, -1, source->hasAlphaChannel != 0);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawSurface2(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans) {
|
||||
DrawingSurface_DrawSurface(target, source, trans, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE);
|
||||
}
|
||||
|
||||
void DrawingSurface_SetDrawingColor(ScriptDrawingSurface *sds, int newColour) {
|
||||
sds->currentColourScript = newColour;
|
||||
// StartDrawing to set up ds to set the colour at the appropriate
|
||||
// depth for the background
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
if (newColour == SCR_COLOR_TRANSPARENT) {
|
||||
sds->currentColour = ds->GetMaskColor();
|
||||
} else {
|
||||
sds->currentColour = ds->GetCompatibleColor(newColour);
|
||||
}
|
||||
sds->FinishedDrawingReadOnly();
|
||||
}
|
||||
|
||||
int DrawingSurface_GetDrawingColor(ScriptDrawingSurface *sds) {
|
||||
return sds->currentColourScript;
|
||||
}
|
||||
|
||||
void DrawingSurface_SetUseHighResCoordinates(ScriptDrawingSurface *sds, int highRes) {
|
||||
if (_GP(game).AllowRelativeRes())
|
||||
sds->highResCoordinates = (highRes) ? 1 : 0;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetUseHighResCoordinates(ScriptDrawingSurface *sds) {
|
||||
return sds->highResCoordinates;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetHeight(ScriptDrawingSurface *sds) {
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
int height = ds->GetHeight();
|
||||
sds->FinishedDrawingReadOnly();
|
||||
sds->SizeToGameResolution(&height);
|
||||
return height;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetWidth(ScriptDrawingSurface *sds) {
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
int width = ds->GetWidth();
|
||||
sds->FinishedDrawingReadOnly();
|
||||
sds->SizeToGameResolution(&width);
|
||||
return width;
|
||||
}
|
||||
|
||||
void DrawingSurface_Clear(ScriptDrawingSurface *sds, int colour) {
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
int allegroColor;
|
||||
if ((colour == -SCR_NO_VALUE) || (colour == SCR_COLOR_TRANSPARENT)) {
|
||||
allegroColor = ds->GetMaskColor();
|
||||
} else {
|
||||
allegroColor = ds->GetCompatibleColor(colour);
|
||||
}
|
||||
ds->Fill(allegroColor);
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawCircle(ScriptDrawingSurface *sds, int x, int y, int radius) {
|
||||
sds->PointToGameResolution(&x, &y);
|
||||
sds->SizeToGameResolution(&radius);
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
ds->FillCircle(Circle(x, y, radius), sds->currentColour);
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawRectangle(ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2) {
|
||||
sds->PointToGameResolution(&x1, &y1);
|
||||
sds->PointToGameResolution(&x2, &y2);
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
ds->FillRect(Rect(x1, y1, x2, y2), sds->currentColour);
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawTriangle(ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
sds->PointToGameResolution(&x1, &y1);
|
||||
sds->PointToGameResolution(&x2, &y2);
|
||||
sds->PointToGameResolution(&x3, &y3);
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
ds->DrawTriangle(Triangle(x1, y1, x2, y2, x3, y3), sds->currentColour);
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawString(ScriptDrawingSurface *sds, int xx, int yy, int font, const char *text) {
|
||||
sds->PointToGameResolution(&xx, &yy);
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
// don't use wtextcolor because it will do a 16->32 conversion
|
||||
color_t text_color = sds->currentColour;
|
||||
if ((ds->GetColorDepth() <= 8) && (_GP(play).raw_color > 255)) {
|
||||
text_color = ds->GetCompatibleColor(1);
|
||||
debug_script_warn("RawPrint: Attempted to use hi-color on 256-col background");
|
||||
}
|
||||
String res_str = GUI::ApplyTextDirection(text);
|
||||
wouttext_outline(ds, xx, yy, font, text_color, res_str.GetCStr());
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawStringWrapped_Old(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg) {
|
||||
DrawingSurface_DrawStringWrapped(sds, xx, yy, wid, font, ConvertLegacyScriptAlignment((LegacyScriptAlignment)alignment), msg);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawStringWrapped(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg) {
|
||||
int linespacing = get_font_linespacing(font);
|
||||
sds->PointToGameResolution(&xx, &yy);
|
||||
sds->SizeToGameResolution(&wid);
|
||||
|
||||
if (break_up_text_into_lines(msg, _GP(Lines), wid, font) == 0)
|
||||
return;
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
color_t text_color = sds->currentColour;
|
||||
|
||||
for (size_t i = 0; i < _GP(Lines).Count(); i++) {
|
||||
GUI::DrawTextAlignedHor(ds, _GP(Lines)[i].GetCStr(), font, text_color,
|
||||
xx, xx + wid - 1, yy + linespacing * i, (FrameAlignment)alignment);
|
||||
}
|
||||
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawMessageWrapped(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int msgm) {
|
||||
char displbuf[3000];
|
||||
get_message_text(msgm, displbuf);
|
||||
// it's probably too late but check anyway
|
||||
if (strlen(displbuf) > 2899)
|
||||
quit("!RawPrintMessageWrapped: message too long");
|
||||
|
||||
DrawingSurface_DrawStringWrapped_Old(sds, xx, yy, wid, font, kLegacyScAlignLeft, displbuf);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawLine(ScriptDrawingSurface *sds, int fromx, int fromy, int tox, int toy, int thickness) {
|
||||
sds->PointToGameResolution(&fromx, &fromy);
|
||||
sds->PointToGameResolution(&tox, &toy);
|
||||
sds->SizeToGameResolution(&thickness);
|
||||
int ii, jj, xx, yy;
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
// draw several lines to simulate the thickness
|
||||
color_t draw_color = sds->currentColour;
|
||||
for (ii = 0; ii < thickness; ii++) {
|
||||
xx = (ii - (thickness / 2));
|
||||
for (jj = 0; jj < thickness; jj++) {
|
||||
yy = (jj - (thickness / 2));
|
||||
ds->DrawLine(Line(fromx + xx, fromy + yy, tox + xx, toy + yy), draw_color);
|
||||
}
|
||||
}
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawPixel(ScriptDrawingSurface *sds, int x, int y) {
|
||||
sds->PointToGameResolution(&x, &y);
|
||||
int thickness = 1;
|
||||
sds->SizeToGameResolution(&thickness);
|
||||
int ii, jj;
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
// draw several pixels to simulate the thickness
|
||||
color_t draw_color = sds->currentColour;
|
||||
for (ii = 0; ii < thickness; ii++) {
|
||||
for (jj = 0; jj < thickness; jj++) {
|
||||
ds->PutPixel(x + ii, y + jj, draw_color);
|
||||
}
|
||||
}
|
||||
sds->FinishedDrawing();
|
||||
}
|
||||
|
||||
int DrawingSurface_GetPixel(ScriptDrawingSurface *sds, int x, int y) {
|
||||
sds->PointToGameResolution(&x, &y);
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
int rawPixel = ds->GetPixel(x, y);
|
||||
int maskColor = ds->GetMaskColor();
|
||||
int colDepth = ds->GetColorDepth();
|
||||
|
||||
if (rawPixel == maskColor) {
|
||||
rawPixel = (unsigned int)SCR_COLOR_TRANSPARENT;
|
||||
} else if (colDepth > 8) {
|
||||
int r = getr_depth(colDepth, rawPixel);
|
||||
int g = getg_depth(colDepth, rawPixel);
|
||||
int b = getb_depth(colDepth, rawPixel);
|
||||
rawPixel = Game_GetColorFromRGB(r, g, b);
|
||||
}
|
||||
|
||||
sds->FinishedDrawingReadOnly();
|
||||
return rawPixel;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int colour)
|
||||
RuntimeScriptValue Sc_DrawingSurface_Clear(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDrawingSurface, DrawingSurface_Clear);
|
||||
}
|
||||
|
||||
// ScriptDrawingSurface* (ScriptDrawingSurface *sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_CreateCopy(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJAUTO(ScriptDrawingSurface, ScriptDrawingSurface, DrawingSurface_CreateCopy);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int x, int y, int radius)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawCircle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT3(ScriptDrawingSurface, DrawingSurface_DrawCircle);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface* sds, int xx, int yy, int slot, int trans, int width, int height)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawImage6(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT6(ScriptDrawingSurface, DrawingSurface_DrawImage6);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawImage(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
|
||||
DrawingSurface_DrawImage((ScriptDrawingSurface *)self, params[0].IValue, params[1].IValue, params[2].IValue, params[3].IValue, params[4].IValue, params[5].IValue,
|
||||
params[6].IValue, params[7].IValue, params[8].IValue, params[9].IValue);
|
||||
return RuntimeScriptValue((int32_t)0);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int fromx, int fromy, int tox, int toy, int thickness)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawLine(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT5(ScriptDrawingSurface, DrawingSurface_DrawLine);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int msgm)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawMessageWrapped(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT5(ScriptDrawingSurface, DrawingSurface_DrawMessageWrapped);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int x, int y)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawPixel(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT2(ScriptDrawingSurface, DrawingSurface_DrawPixel);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawRectangle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT4(ScriptDrawingSurface, DrawingSurface_DrawRectangle);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int xx, int yy, int font, const char* texx, ...)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawString(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_SCRIPT_SPRINTF(DrawingSurface_DrawString, 4);
|
||||
DrawingSurface_DrawString((ScriptDrawingSurface *)self, params[0].IValue, params[1].IValue, params[2].IValue, scsf_buffer);
|
||||
return RuntimeScriptValue((int32_t)0);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawStringWrapped_Old(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT5_POBJ(ScriptDrawingSurface, DrawingSurface_DrawStringWrapped_Old, const char);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawStringWrapped(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_SCRIPT_SPRINTF(DrawingSurface_DrawString, 6);
|
||||
DrawingSurface_DrawStringWrapped((ScriptDrawingSurface *)self, params[0].IValue, params[1].IValue, params[2].IValue,
|
||||
params[3].IValue, params[4].IValue, scsf_buffer);
|
||||
return RuntimeScriptValue((int32_t)0);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface* target, ScriptDrawingSurface* source, int translev)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawSurface2(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_POBJ_PINT(ScriptDrawingSurface, DrawingSurface_DrawSurface2, ScriptDrawingSurface);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawSurface(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
|
||||
DrawingSurface_DrawSurface((ScriptDrawingSurface *)self, (ScriptDrawingSurface *)params[0].Ptr,
|
||||
params[1].IValue, params[2].IValue, params[3].IValue, params[4].IValue, params[5].IValue,
|
||||
params[6].IValue, params[7].IValue, params[8].IValue, params[9].IValue);
|
||||
return RuntimeScriptValue((int32_t)0);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2, int x3, int y3)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawTriangle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT6(ScriptDrawingSurface, DrawingSurface_DrawTriangle);
|
||||
}
|
||||
|
||||
// int (ScriptDrawingSurface *sds, int x, int y)
|
||||
RuntimeScriptValue Sc_DrawingSurface_GetPixel(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT_PINT2(ScriptDrawingSurface, DrawingSurface_GetPixel);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface* sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_Release(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptDrawingSurface, DrawingSurface_Release);
|
||||
}
|
||||
|
||||
// int (ScriptDrawingSurface *sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_GetDrawingColor(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDrawingSurface, DrawingSurface_GetDrawingColor);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int newColour)
|
||||
RuntimeScriptValue Sc_DrawingSurface_SetDrawingColor(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDrawingSurface, DrawingSurface_SetDrawingColor);
|
||||
}
|
||||
|
||||
// int (ScriptDrawingSurface *sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDrawingSurface, DrawingSurface_GetHeight);
|
||||
}
|
||||
|
||||
// int (ScriptDrawingSurface *sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_GetUseHighResCoordinates(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDrawingSurface, DrawingSurface_GetUseHighResCoordinates);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int highRes)
|
||||
RuntimeScriptValue Sc_DrawingSurface_SetUseHighResCoordinates(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDrawingSurface, DrawingSurface_SetUseHighResCoordinates);
|
||||
}
|
||||
|
||||
// int (ScriptDrawingSurface *sds)
|
||||
RuntimeScriptValue Sc_DrawingSurface_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDrawingSurface, DrawingSurface_GetWidth);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Exclusive variadic API implementation for Plugins
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ScPl_DrawingSurface_DrawStringWrapped(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg, ...) {
|
||||
API_PLUGIN_SCRIPT_SPRINTF(msg);
|
||||
DrawingSurface_DrawStringWrapped(sds, xx, yy, wid, font, alignment, scsf_buffer);
|
||||
}
|
||||
|
||||
void RegisterDrawingSurfaceAPI(ScriptAPIVersion base_api, ScriptAPIVersion /*compat_api */) {
|
||||
ScFnRegister drawsurf_api[] = {
|
||||
{"DrawingSurface::Clear^1", API_FN_PAIR(DrawingSurface_Clear)},
|
||||
{"DrawingSurface::CreateCopy^0", API_FN_PAIR(DrawingSurface_CreateCopy)},
|
||||
{"DrawingSurface::DrawCircle^3", API_FN_PAIR(DrawingSurface_DrawCircle)},
|
||||
{"DrawingSurface::DrawImage^6", API_FN_PAIR(DrawingSurface_DrawImage6)},
|
||||
{"DrawingSurface::DrawImage^10", API_FN_PAIR(DrawingSurface_DrawImage)},
|
||||
{"DrawingSurface::DrawLine^5", API_FN_PAIR(DrawingSurface_DrawLine)},
|
||||
{"DrawingSurface::DrawMessageWrapped^5", API_FN_PAIR(DrawingSurface_DrawMessageWrapped)},
|
||||
{"DrawingSurface::DrawPixel^2", API_FN_PAIR(DrawingSurface_DrawPixel)},
|
||||
{"DrawingSurface::DrawRectangle^4", API_FN_PAIR(DrawingSurface_DrawRectangle)},
|
||||
{"DrawingSurface::DrawString^104", Sc_DrawingSurface_DrawString},
|
||||
{"DrawingSurface::DrawSurface^2", API_FN_PAIR(DrawingSurface_DrawSurface2)},
|
||||
{"DrawingSurface::DrawSurface^10", API_FN_PAIR(DrawingSurface_DrawSurface)},
|
||||
{"DrawingSurface::DrawTriangle^6", API_FN_PAIR(DrawingSurface_DrawTriangle)},
|
||||
{"DrawingSurface::GetPixel^2", API_FN_PAIR(DrawingSurface_GetPixel)},
|
||||
{"DrawingSurface::Release^0", API_FN_PAIR(DrawingSurface_Release)},
|
||||
{"DrawingSurface::get_DrawingColor", API_FN_PAIR(DrawingSurface_GetDrawingColor)},
|
||||
{"DrawingSurface::set_DrawingColor", API_FN_PAIR(DrawingSurface_SetDrawingColor)},
|
||||
{"DrawingSurface::get_Height", API_FN_PAIR(DrawingSurface_GetHeight)},
|
||||
{"DrawingSurface::get_UseHighResCoordinates", API_FN_PAIR(DrawingSurface_GetUseHighResCoordinates)},
|
||||
{"DrawingSurface::set_UseHighResCoordinates", API_FN_PAIR(DrawingSurface_SetUseHighResCoordinates)},
|
||||
{"DrawingSurface::get_Width", API_FN_PAIR(DrawingSurface_GetWidth)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(drawsurf_api);
|
||||
|
||||
// Few functions have to be selected based on API level
|
||||
if (base_api < kScriptAPI_v350) {
|
||||
ccAddExternalObjectFunction361("DrawingSurface::DrawStringWrapped^6", API_FN_PAIR(DrawingSurface_DrawStringWrapped_Old));
|
||||
}
|
||||
else { // old non-variadic and new variadic variants
|
||||
ccAddExternalObjectFunction361("DrawingSurface::DrawStringWrapped^6", API_FN_PAIR(DrawingSurface_DrawStringWrapped));
|
||||
ccAddExternalObjectFunction361("DrawingSurface::DrawStringWrapped^106", Sc_DrawingSurface_DrawStringWrapped, (void *)ScPl_DrawingSurface_DrawStringWrapped);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
57
engines/ags/engine/ac/drawing_surface.h
Normal file
57
engines/ags/engine/ac/drawing_surface.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DRAWING_SURFACE_H
|
||||
#define AGS_ENGINE_AC_DRAWING_SURFACE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
void DrawingSurface_Release(ScriptDrawingSurface *sds);
|
||||
// convert actual co-ordinate back to what the script is expecting
|
||||
ScriptDrawingSurface *DrawingSurface_CreateCopy(ScriptDrawingSurface *sds);
|
||||
void DrawingSurface_DrawSurface(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans,
|
||||
int dst_x, int dst_y, int dst_width, int dst_height,
|
||||
int src_x, int src_y, int src_width, int src_height);
|
||||
void DrawingSurface_DrawSurface2(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans);
|
||||
void DrawingSurface_DrawImage6(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height);
|
||||
void DrawingSurface_SetDrawingColor(ScriptDrawingSurface *sds, int newColour);
|
||||
int DrawingSurface_GetDrawingColor(ScriptDrawingSurface *sds);
|
||||
void DrawingSurface_SetUseHighResCoordinates(ScriptDrawingSurface *sds, int highRes);
|
||||
int DrawingSurface_GetUseHighResCoordinates(ScriptDrawingSurface *sds);
|
||||
int DrawingSurface_GetHeight(ScriptDrawingSurface *sds);
|
||||
int DrawingSurface_GetWidth(ScriptDrawingSurface *sds);
|
||||
void DrawingSurface_Clear(ScriptDrawingSurface *sds, int colour);
|
||||
void DrawingSurface_DrawCircle(ScriptDrawingSurface *sds, int x, int y, int radius);
|
||||
void DrawingSurface_DrawRectangle(ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2);
|
||||
void DrawingSurface_DrawTriangle(ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void DrawingSurface_DrawString(ScriptDrawingSurface *sds, int xx, int yy, int font, const char *text);
|
||||
void DrawingSurface_DrawStringWrapped(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg);
|
||||
void DrawingSurface_DrawStringWrapped_Old(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int alignment, const char *msg);
|
||||
void DrawingSurface_DrawMessageWrapped(ScriptDrawingSurface *sds, int xx, int yy, int wid, int font, int msgm);
|
||||
void DrawingSurface_DrawLine(ScriptDrawingSurface *sds, int fromx, int fromy, int tox, int toy, int thickness);
|
||||
void DrawingSurface_DrawPixel(ScriptDrawingSurface *sds, int x, int y);
|
||||
int DrawingSurface_GetPixel(ScriptDrawingSurface *sds, int x, int y);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
609
engines/ags/engine/ac/dynamic_sprite.cpp
Normal file
609
engines/ags/engine/ac/dynamic_sprite.cpp
Normal file
@@ -0,0 +1,609 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynamic_sprite.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/engine/ac/draw.h"
|
||||
#include "ags/engine/ac/game.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/engine/ac/global_dynamic_sprite.h"
|
||||
#include "ags/engine/ac/global_game.h"
|
||||
#include "ags/engine/ac/math.h" // M_PI
|
||||
#include "ags/engine/ac/path_helper.h"
|
||||
#include "ags/engine/ac/room_object.h"
|
||||
#include "ags/engine/ac/room_status.h"
|
||||
#include "ags/engine/ac/system.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/gui/gui_button.h"
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/engine/gfx/graphics_driver.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/engine/script/script_api.h"
|
||||
#include "ags/engine/script/script_runtime.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace Shared;
|
||||
using namespace Engine;
|
||||
|
||||
// ** SCRIPT DYNAMIC SPRITE
|
||||
|
||||
void DynamicSprite_Delete(ScriptDynamicSprite *sds) {
|
||||
if (sds->slot) {
|
||||
free_dynamic_sprite(sds->slot);
|
||||
sds->slot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptDrawingSurface *DynamicSprite_GetDrawingSurface(ScriptDynamicSprite *dss) {
|
||||
ScriptDrawingSurface *surface = new ScriptDrawingSurface();
|
||||
surface->dynamicSpriteNumber = dss->slot;
|
||||
|
||||
if ((_GP(game).SpriteInfos[dss->slot].Flags & SPF_ALPHACHANNEL) != 0)
|
||||
surface->hasAlphaChannel = true;
|
||||
|
||||
ccRegisterManagedObject(surface, surface);
|
||||
return surface;
|
||||
}
|
||||
|
||||
int DynamicSprite_GetGraphic(ScriptDynamicSprite *sds) {
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.Graphic: Cannot get graphic, sprite has been deleted");
|
||||
return sds->slot;
|
||||
}
|
||||
|
||||
int DynamicSprite_GetWidth(ScriptDynamicSprite *sds) {
|
||||
return game_to_data_coord(_GP(game).SpriteInfos[sds->slot].Width);
|
||||
}
|
||||
|
||||
int DynamicSprite_GetHeight(ScriptDynamicSprite *sds) {
|
||||
return game_to_data_coord(_GP(game).SpriteInfos[sds->slot].Height);
|
||||
}
|
||||
|
||||
int DynamicSprite_GetColorDepth(ScriptDynamicSprite *sds) {
|
||||
// Dynamic sprite ensures the sprite exists always
|
||||
int depth = _GP(spriteset)[sds->slot]->GetColorDepth();
|
||||
if (depth == 15)
|
||||
depth = 16;
|
||||
if (depth == 24)
|
||||
depth = 32;
|
||||
return depth;
|
||||
}
|
||||
|
||||
void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height) {
|
||||
if ((width < 1) || (height < 1))
|
||||
quit("!DynamicSprite.Resize: width and height must be greater than zero");
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.Resize: sprite has been deleted");
|
||||
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
if (width * height >= 25000000)
|
||||
quitprintf("!DynamicSprite.Resize: new size is too large: %d x %d", width, height);
|
||||
|
||||
// resize the sprite to the requested size
|
||||
Bitmap *sprite = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmap(width, height, sprite->GetColorDepth()));
|
||||
new_pic->StretchBlt(sprite,
|
||||
RectWH(0, 0, _GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height),
|
||||
RectWH(0, 0, width, height));
|
||||
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
|
||||
if ((direction < 1) || (direction > 3))
|
||||
quit("!DynamicSprite.Flip: invalid direction");
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.Flip: sprite has been deleted");
|
||||
|
||||
// resize the sprite to the requested size
|
||||
Bitmap *sprite = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateTransparentBitmap(sprite->GetWidth(), sprite->GetHeight(), sprite->GetColorDepth()));
|
||||
|
||||
// AGS script FlipDirection corresponds to internal GraphicFlip
|
||||
new_pic->FlipBlt(sprite, 0, 0, static_cast<GraphicFlip>(direction));
|
||||
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) {
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted");
|
||||
|
||||
if ((_GP(game).SpriteInfos[sds->slot].Width != _GP(game).SpriteInfos[sourceSprite].Width) ||
|
||||
(_GP(game).SpriteInfos[sds->slot].Height != _GP(game).SpriteInfos[sourceSprite].Height)) {
|
||||
quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size");
|
||||
}
|
||||
|
||||
Bitmap *target = _GP(spriteset)[sds->slot];
|
||||
Bitmap *source = _GP(spriteset)[sourceSprite];
|
||||
|
||||
if (target->GetColorDepth() != source->GetColorDepth()) {
|
||||
quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same colour depth");
|
||||
}
|
||||
|
||||
// set the target's alpha channel depending on the source
|
||||
bool dst_has_alpha = (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0;
|
||||
bool src_has_alpha = (_GP(game).SpriteInfos[sourceSprite].Flags & SPF_ALPHACHANNEL) != 0;
|
||||
_GP(game).SpriteInfos[sds->slot].Flags &= ~SPF_ALPHACHANNEL;
|
||||
if (src_has_alpha) {
|
||||
_GP(game).SpriteInfos[sds->slot].Flags |= SPF_ALPHACHANNEL;
|
||||
}
|
||||
|
||||
BitmapHelper::CopyTransparency(target, source, dst_has_alpha, src_has_alpha);
|
||||
}
|
||||
|
||||
void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int height, int x, int y) {
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.ChangeCanvasSize: sprite has been deleted");
|
||||
if ((width < 1) || (height < 1))
|
||||
quit("!DynamicSprite.ChangeCanvasSize: new size is too small");
|
||||
|
||||
data_to_game_coords(&x, &y);
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
Bitmap *sprite = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateTransparentBitmap(width, height, sprite->GetColorDepth()));
|
||||
// blit it into the enlarged image
|
||||
new_pic->Blit(sprite, 0, 0, x, y, sprite->GetWidth(), sprite->GetHeight());
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x1, int y1, int width, int height) {
|
||||
if ((width < 1) || (height < 1))
|
||||
quit("!DynamicSprite.Crop: co-ordinates do not make sense");
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.Crop: sprite has been deleted");
|
||||
|
||||
data_to_game_coords(&x1, &y1);
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
if ((width > _GP(game).SpriteInfos[sds->slot].Width) || (height > _GP(game).SpriteInfos[sds->slot].Height))
|
||||
quit("!DynamicSprite.Crop: requested to crop an area larger than the source");
|
||||
|
||||
Bitmap *sprite = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmap(width, height, sprite->GetColorDepth()));
|
||||
// blit it cropped
|
||||
new_pic->Blit(sprite, x1, y1, 0, 0, new_pic->GetWidth(), new_pic->GetHeight());
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height) {
|
||||
if ((angle < 1) || (angle > 359))
|
||||
quit("!DynamicSprite.Rotate: invalid angle (must be 1-359)");
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.Rotate: sprite has been deleted");
|
||||
|
||||
if ((width == SCR_NO_VALUE) || (height == SCR_NO_VALUE)) {
|
||||
// calculate the new image size automatically
|
||||
// 1 degree = 181 degrees in terms of x/y size, so % 180
|
||||
int useAngle = angle % 180;
|
||||
// and 0..90 is the same as 180..90
|
||||
if (useAngle > 90)
|
||||
useAngle = 180 - useAngle;
|
||||
// useAngle is now between 0 and 90 (otherwise the sin/cos stuff doesn't work)
|
||||
double angleInRadians = (double)useAngle * (M_PI / 180.0);
|
||||
double sinVal = sin(angleInRadians);
|
||||
double cosVal = cos(angleInRadians);
|
||||
|
||||
width = (cosVal * (double)_GP(game).SpriteInfos[sds->slot].Width + sinVal * (double)_GP(game).SpriteInfos[sds->slot].Height);
|
||||
height = (sinVal * (double)_GP(game).SpriteInfos[sds->slot].Width + cosVal * (double)_GP(game).SpriteInfos[sds->slot].Height);
|
||||
} else {
|
||||
data_to_game_coords(&width, &height);
|
||||
}
|
||||
|
||||
// convert to allegro angle
|
||||
angle = (angle * 256) / 360;
|
||||
|
||||
// resize the sprite to the requested size
|
||||
Bitmap *sprite = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateTransparentBitmap(width, height, sprite->GetColorDepth()));
|
||||
|
||||
// rotate the sprite about its centre
|
||||
// (+ width%2 fixes one pixel offset problem)
|
||||
new_pic->RotateBlt(sprite, width / 2 + width % 2, height / 2,
|
||||
sprite->GetWidth() / 2, sprite->GetHeight() / 2, itofix(angle));
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DynamicSprite_Tint(ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance) {
|
||||
Bitmap *source = _GP(spriteset)[sds->slot];
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmap(source->GetWidth(), source->GetHeight(), source->GetColorDepth()));
|
||||
|
||||
tint_image(new_pic.get(), source, red, green, blue, saturation, (luminance * 25) / 10);
|
||||
|
||||
add_dynamic_sprite(sds->slot, std::move(new_pic), (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
int DynamicSprite_SaveToFile(ScriptDynamicSprite *sds, const char *namm) {
|
||||
if (sds->slot == 0)
|
||||
quit("!DynamicSprite.SaveToFile: sprite has been deleted");
|
||||
|
||||
auto filename = String(namm);
|
||||
if (filename.FindChar('.') == String::NoIndex)
|
||||
filename.Append(".bmp");
|
||||
|
||||
ResolvedPath rp;
|
||||
if (!ResolveWritePathAndCreateDirs(filename, rp))
|
||||
return 0;
|
||||
return _GP(spriteset)[sds->slot]->SaveToFile(rp.FullPath, _G(palette)) ? 1 : 0;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromSaveGame(int sgslot, int width, int height) {
|
||||
int slotnum = LoadSaveSlotScreenshot(sgslot, width, height);
|
||||
if (slotnum) {
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(slotnum);
|
||||
return new_spr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromFile(const char *filename) {
|
||||
int slotnum = LoadImageFile(filename);
|
||||
if (slotnum) {
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(slotnum);
|
||||
return new_spr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromScreenShot(int width, int height) {
|
||||
|
||||
// TODO: refactor and merge with create_savegame_screenshot()
|
||||
|
||||
if (!_GP(spriteset).HasFreeSlots())
|
||||
return nullptr;
|
||||
|
||||
// NOTE: be aware that by the historical logic AGS makes a screenshot
|
||||
// of a "main viewport", that may be smaller in legacy "letterbox" mode.
|
||||
const Rect &viewport = _GP(play).GetMainViewport();
|
||||
if (width <= 0)
|
||||
width = viewport.GetWidth();
|
||||
else
|
||||
width = data_to_game_coord(width);
|
||||
|
||||
if (height <= 0)
|
||||
height = viewport.GetHeight();
|
||||
else
|
||||
height = data_to_game_coord(height);
|
||||
|
||||
std::unique_ptr<Bitmap> new_pic(CopyScreenIntoBitmap(width, height, &viewport));
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
int new_slot = add_dynamic_sprite(std::move(new_pic));
|
||||
return new ScriptDynamicSprite(new_slot);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite(int slot, int preserveAlphaChannel) {
|
||||
|
||||
if (!_GP(spriteset).HasFreeSlots())
|
||||
return nullptr;
|
||||
|
||||
if (!_GP(spriteset).DoesSpriteExist(slot))
|
||||
quitprintf("DynamicSprite.CreateFromExistingSprite: sprite %d does not exist", slot);
|
||||
|
||||
// create a new sprite as a copy of the existing one
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmapCopy(_GP(spriteset)[slot]));
|
||||
if (!new_pic)
|
||||
return nullptr;
|
||||
|
||||
bool hasAlpha = (preserveAlphaChannel) && ((_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
int new_slot = add_dynamic_sprite(std::move(new_pic), hasAlpha);
|
||||
return new ScriptDynamicSprite(new_slot);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromDrawingSurface(ScriptDrawingSurface *sds, int x, int y, int width, int height) {
|
||||
if (!_GP(spriteset).HasFreeSlots())
|
||||
return nullptr;
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
debug_script_warn("WARNING: DynamicSprite.CreateFromDrawingSurface: invalid size %d x %d, will adjust", width, height);
|
||||
width = std::max(1, width);
|
||||
height = std::max(1, height);
|
||||
}
|
||||
|
||||
// use DrawingSurface resolution
|
||||
sds->PointToGameResolution(&x, &y);
|
||||
sds->SizeToGameResolution(&width, &height);
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
if ((x < 0) || (y < 0) || (x + width > ds->GetWidth()) || (y + height > ds->GetHeight()))
|
||||
quit("!DynamicSprite.CreateFromDrawingSurface: requested area is outside the surface");
|
||||
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmap(width, height, ds->GetColorDepth()));
|
||||
if (!new_pic)
|
||||
return nullptr;
|
||||
|
||||
new_pic->Blit(ds, x, y, 0, 0, width, height);
|
||||
|
||||
sds->FinishedDrawingReadOnly();
|
||||
|
||||
int new_slot = add_dynamic_sprite(std::move(new_pic), (sds->hasAlphaChannel != 0));
|
||||
return new ScriptDynamicSprite(new_slot);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_Create(int width, int height, int alphaChannel) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
debug_script_warn("WARNING: DynamicSprite.Create: invalid size %d x %d, will adjust", width, height);
|
||||
width = MAX(1, width);
|
||||
height = MAX(1, height);
|
||||
}
|
||||
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
if (!_GP(spriteset).HasFreeSlots())
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<Bitmap> new_pic(CreateCompatBitmap(width, height));
|
||||
if (!new_pic)
|
||||
return nullptr;
|
||||
|
||||
new_pic->ClearTransparent();
|
||||
if ((alphaChannel) && (_GP(game).GetColorDepth() < 32))
|
||||
alphaChannel = false;
|
||||
|
||||
int new_slot = add_dynamic_sprite(std::move(new_pic), alphaChannel != 0);
|
||||
return new ScriptDynamicSprite(new_slot);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite_Old(int slot) {
|
||||
return DynamicSprite_CreateFromExistingSprite(slot, 0);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromBackground(int frame, int x1, int y1, int width, int height) {
|
||||
if (frame == SCR_NO_VALUE) {
|
||||
frame = _GP(play).bg_frame;
|
||||
} else if ((frame < 0) || ((size_t)frame >= _GP(thisroom).BgFrameCount))
|
||||
quit("!DynamicSprite.CreateFromBackground: invalid frame specified");
|
||||
|
||||
if (x1 == SCR_NO_VALUE)
|
||||
x1 = 0;
|
||||
if (y1 == SCR_NO_VALUE)
|
||||
y1 = 0;
|
||||
if (width == SCR_NO_VALUE)
|
||||
width = _GP(play).room_width;
|
||||
if (height == SCR_NO_VALUE)
|
||||
height = _GP(play).room_height;
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
debug_script_warn("WARNING: DynamicSprite.CreateFromBackground: invalid size %d x %d, will adjust", width, height);
|
||||
width = std::max(1, width);
|
||||
height = std::max(1, height);
|
||||
}
|
||||
|
||||
if ((x1 < 0) || (y1 < 0) || (x1 + width > _GP(play).room_width) || (y1 + height > _GP(play).room_height))
|
||||
quit("!DynamicSprite.CreateFromBackground: invalid co-ordinates specified");
|
||||
|
||||
data_to_game_coords(&x1, &y1);
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
if (!_GP(spriteset).HasFreeSlots())
|
||||
return nullptr;
|
||||
|
||||
// create a new sprite as a copy of the existing one
|
||||
std::unique_ptr<Bitmap> new_pic(BitmapHelper::CreateBitmap(width, height, _GP(thisroom).BgFrames[frame].Graphic->GetColorDepth()));
|
||||
if (!new_pic)
|
||||
return nullptr;
|
||||
|
||||
new_pic->Blit(_GP(thisroom).BgFrames[frame].Graphic.get(), x1, y1, 0, 0, width, height);
|
||||
|
||||
int new_slot = add_dynamic_sprite(std::move(new_pic));
|
||||
return new ScriptDynamicSprite(new_slot);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
int add_dynamic_sprite(std::unique_ptr<Bitmap> image, bool has_alpha, uint32_t extra_flags) {
|
||||
int slot = _GP(spriteset).GetFreeIndex();
|
||||
if (slot <= 0)
|
||||
return 0;
|
||||
|
||||
return add_dynamic_sprite(slot, std::move(image), has_alpha, extra_flags);
|
||||
}
|
||||
|
||||
int add_dynamic_sprite(int slot, std::unique_ptr<Bitmap> image, bool has_alpha, uint32_t extra_flags) {
|
||||
assert(slot > 0 && !_GP(spriteset).IsAssetSprite(slot));
|
||||
if (slot <= 0 || _GP(spriteset).IsAssetSprite(slot))
|
||||
return 0; // invalid slot, or reserved for the static sprite
|
||||
|
||||
uint32_t flags = SPF_DYNAMICALLOC | (SPF_ALPHACHANNEL * has_alpha) | extra_flags;
|
||||
|
||||
if(!_GP(spriteset).SetSprite(slot, std::move(image), flags))
|
||||
return 0; // failed to add the sprite, bad image or realloc failed
|
||||
|
||||
// Notify a new (normal) dynamic sprite in case some objects
|
||||
// have this number assigned to their Graphic property
|
||||
if ((extra_flags & SPF_OBJECTOWNED) == 0)
|
||||
game_sprite_updated(slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
void free_dynamic_sprite(int slot, bool notify_all) {
|
||||
assert((slot > 0) && (static_cast<size_t>(slot) < _GP(game).SpriteInfos.size()) &&
|
||||
(_GP(game).SpriteInfos[slot].Flags & SPF_DYNAMICALLOC));
|
||||
if ((slot <= 0) || (static_cast<size_t>(slot) >= _GP(game).SpriteInfos.size()) ||
|
||||
(_GP(game).SpriteInfos[slot].Flags & SPF_DYNAMICALLOC) == 0)
|
||||
return;
|
||||
|
||||
_GP(spriteset).DeleteSprite(slot);
|
||||
if (notify_all)
|
||||
game_sprite_updated(slot, true);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int width, int height, int x, int y)
|
||||
RuntimeScriptValue Sc_DynamicSprite_ChangeCanvasSize(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT4(ScriptDynamicSprite, DynamicSprite_ChangeCanvasSize);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int sourceSprite)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CopyTransparencyMask(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDynamicSprite, DynamicSprite_CopyTransparencyMask);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int x1, int y1, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Crop(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT4(ScriptDynamicSprite, DynamicSprite_Crop);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Delete(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID(ScriptDynamicSprite, DynamicSprite_Delete);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int direction)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Flip(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT(ScriptDynamicSprite, DynamicSprite_Flip);
|
||||
}
|
||||
|
||||
// ScriptDrawingSurface* (ScriptDynamicSprite *dss)
|
||||
RuntimeScriptValue Sc_DynamicSprite_GetDrawingSurface(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_OBJAUTO(ScriptDynamicSprite, ScriptDrawingSurface, DynamicSprite_GetDrawingSurface);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Resize(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT2(ScriptDynamicSprite, DynamicSprite_Resize);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int angle, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Rotate(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT3(ScriptDynamicSprite, DynamicSprite_Rotate);
|
||||
}
|
||||
|
||||
// int (ScriptDynamicSprite *sds, const char* namm)
|
||||
RuntimeScriptValue Sc_DynamicSprite_SaveToFile(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT_POBJ(ScriptDynamicSprite, DynamicSprite_SaveToFile, const char);
|
||||
}
|
||||
|
||||
// void (ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Tint(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_VOID_PINT5(ScriptDynamicSprite, DynamicSprite_Tint);
|
||||
}
|
||||
|
||||
// int (ScriptDynamicSprite *sds)
|
||||
RuntimeScriptValue Sc_DynamicSprite_GetColorDepth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetColorDepth);
|
||||
}
|
||||
|
||||
// int (ScriptDynamicSprite *sds)
|
||||
RuntimeScriptValue Sc_DynamicSprite_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetGraphic);
|
||||
}
|
||||
|
||||
// int (ScriptDynamicSprite *sds)
|
||||
RuntimeScriptValue Sc_DynamicSprite_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetHeight);
|
||||
}
|
||||
|
||||
// int (ScriptDynamicSprite *sds)
|
||||
RuntimeScriptValue Sc_DynamicSprite_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_OBJCALL_INT(ScriptDynamicSprite, DynamicSprite_GetWidth);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int width, int height, int alphaChannel)
|
||||
RuntimeScriptValue Sc_DynamicSprite_Create(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT3(ScriptDynamicSprite, DynamicSprite_Create);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int frame, int x1, int y1, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromBackground(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT5(ScriptDynamicSprite, DynamicSprite_CreateFromBackground);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (ScriptDrawingSurface *sds, int x, int y, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromDrawingSurface(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_POBJ_PINT4(ScriptDynamicSprite, DynamicSprite_CreateFromDrawingSurface, ScriptDrawingSurface);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int slot)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromExistingSprite_Old(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT(ScriptDynamicSprite, DynamicSprite_CreateFromExistingSprite_Old);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int slot, int preserveAlphaChannel)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromExistingSprite(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT2(ScriptDynamicSprite, DynamicSprite_CreateFromExistingSprite);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (const char *filename)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromFile(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_POBJ(ScriptDynamicSprite, DynamicSprite_CreateFromFile, const char);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int sgslot, int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromSaveGame(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT3(ScriptDynamicSprite, DynamicSprite_CreateFromSaveGame);
|
||||
}
|
||||
|
||||
// ScriptDynamicSprite* (int width, int height)
|
||||
RuntimeScriptValue Sc_DynamicSprite_CreateFromScreenShot(const RuntimeScriptValue *params, int32_t param_count) {
|
||||
API_SCALL_OBJAUTO_PINT2(ScriptDynamicSprite, DynamicSprite_CreateFromScreenShot);
|
||||
}
|
||||
|
||||
void RegisterDynamicSpriteAPI() {
|
||||
ScFnRegister dynsprite_api[] = {
|
||||
{"DynamicSprite::Create^3", API_FN_PAIR(DynamicSprite_Create)},
|
||||
{"DynamicSprite::CreateFromBackground", API_FN_PAIR(DynamicSprite_CreateFromBackground)},
|
||||
{"DynamicSprite::CreateFromDrawingSurface^5", API_FN_PAIR(DynamicSprite_CreateFromDrawingSurface)},
|
||||
{"DynamicSprite::CreateFromExistingSprite^1", API_FN_PAIR(DynamicSprite_CreateFromExistingSprite_Old)},
|
||||
{"DynamicSprite::CreateFromExistingSprite^2", API_FN_PAIR(DynamicSprite_CreateFromExistingSprite)},
|
||||
{"DynamicSprite::CreateFromFile", API_FN_PAIR(DynamicSprite_CreateFromFile)},
|
||||
{"DynamicSprite::CreateFromSaveGame", API_FN_PAIR(DynamicSprite_CreateFromSaveGame)},
|
||||
{"DynamicSprite::CreateFromScreenShot", API_FN_PAIR(DynamicSprite_CreateFromScreenShot)},
|
||||
|
||||
{"DynamicSprite::ChangeCanvasSize^4", API_FN_PAIR(DynamicSprite_ChangeCanvasSize)},
|
||||
{"DynamicSprite::CopyTransparencyMask^1", API_FN_PAIR(DynamicSprite_CopyTransparencyMask)},
|
||||
{"DynamicSprite::Crop^4", API_FN_PAIR(DynamicSprite_Crop)},
|
||||
{"DynamicSprite::Delete", API_FN_PAIR(DynamicSprite_Delete)},
|
||||
{"DynamicSprite::Flip^1", API_FN_PAIR(DynamicSprite_Flip)},
|
||||
{"DynamicSprite::GetDrawingSurface^0", API_FN_PAIR(DynamicSprite_GetDrawingSurface)},
|
||||
{"DynamicSprite::Resize^2", API_FN_PAIR(DynamicSprite_Resize)},
|
||||
{"DynamicSprite::Rotate^3", API_FN_PAIR(DynamicSprite_Rotate)},
|
||||
{"DynamicSprite::SaveToFile^1", API_FN_PAIR(DynamicSprite_SaveToFile)},
|
||||
{"DynamicSprite::Tint^5", API_FN_PAIR(DynamicSprite_Tint)},
|
||||
{"DynamicSprite::get_ColorDepth", API_FN_PAIR(DynamicSprite_GetColorDepth)},
|
||||
{"DynamicSprite::get_Graphic", API_FN_PAIR(DynamicSprite_GetGraphic)},
|
||||
{"DynamicSprite::get_Height", API_FN_PAIR(DynamicSprite_GetHeight)},
|
||||
{"DynamicSprite::get_Width", API_FN_PAIR(DynamicSprite_GetWidth)},
|
||||
};
|
||||
|
||||
ccAddExternalFunctions361(dynsprite_api);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
67
engines/ags/engine/ac/dynamic_sprite.h
Normal file
67
engines/ags/engine/ac/dynamic_sprite.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNAMICSPRITE_H
|
||||
#define AGS_ENGINE_AC_DYNAMICSPRITE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
|
||||
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
void DynamicSprite_Delete(ScriptDynamicSprite *sds);
|
||||
ScriptDrawingSurface *DynamicSprite_GetDrawingSurface(ScriptDynamicSprite *dss);
|
||||
int DynamicSprite_GetGraphic(ScriptDynamicSprite *sds);
|
||||
int DynamicSprite_GetWidth(ScriptDynamicSprite *sds);
|
||||
int DynamicSprite_GetHeight(ScriptDynamicSprite *sds);
|
||||
int DynamicSprite_GetColorDepth(ScriptDynamicSprite *sds);
|
||||
void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height);
|
||||
void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction);
|
||||
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite);
|
||||
void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int height, int x, int y);
|
||||
void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x1, int y1, int width, int height);
|
||||
void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height);
|
||||
void DynamicSprite_Tint(ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance);
|
||||
int DynamicSprite_SaveToFile(ScriptDynamicSprite *sds, const char *namm);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromSaveGame(int sgslot, int width, int height);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromFile(const char *filename);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromScreenShot(int width, int height);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite(int slot, int preserveAlphaChannel);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromDrawingSurface(ScriptDrawingSurface *sds, int x, int y, int width, int height);
|
||||
ScriptDynamicSprite *DynamicSprite_Create(int width, int height, int alphaChannel);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromExistingSprite_Old(int slot);
|
||||
ScriptDynamicSprite *DynamicSprite_CreateFromBackground(int frame, int x1, int y1, int width, int height);
|
||||
|
||||
// Registers a new dynamic sprite, and returns a slot number;
|
||||
// returns 0 if no free slot could be found or allocated.
|
||||
// Updates game.SpriteInfos[].
|
||||
int add_dynamic_sprite(std::unique_ptr<AGS::Shared::Bitmap> image, bool has_alpha = false, uint32_t extra_flags = 0u);
|
||||
// Registers a new dynamic sprite in the given slot number,
|
||||
// previous bitmap on this slot (if any) will be deleted.
|
||||
// Returns same slot number on success, or 0 if there was an error.
|
||||
// Updates game.SpriteInfos[].
|
||||
int add_dynamic_sprite(int slot, std::unique_ptr<AGS::Shared::Bitmap> image, bool hasAlpha = false, uint32_t extra_flags = 0u);
|
||||
// Disposes a dynamic sprite, and frees the slot
|
||||
void free_dynamic_sprite(int slot, bool notify_all = true);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
38
engines/ags/engine/ac/dynobj/all_dynamic_classes.h
Normal file
38
engines/ags/engine/ac/dynobj/all_dynamic_classes.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_channel.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
|
||||
#include "ags/engine/ac/dynobj/cc_character.h"
|
||||
#include "ags/engine/ac/dynobj/cc_dialog.h"
|
||||
#include "ags/engine/ac/dynobj/cc_gui.h"
|
||||
#include "ags/engine/ac/dynobj/cc_gui_object.h"
|
||||
#include "ags/engine/ac/dynobj/cc_hotspot.h"
|
||||
#include "ags/engine/ac/dynobj/cc_inventory.h"
|
||||
#include "ags/engine/ac/dynobj/cc_object.h"
|
||||
#include "ags/engine/ac/dynobj/cc_region.h"
|
||||
#include "ags/engine/ac/dynobj/cc_serializer.h"
|
||||
|
||||
#endif
|
||||
41
engines/ags/engine/ac/dynobj/all_script_classes.h
Normal file
41
engines/ags/engine/ac/dynobj/all_script_classes.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_date_time.h"
|
||||
#include "ags/engine/ac/dynobj/script_dialog.h"
|
||||
#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
|
||||
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
|
||||
#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
|
||||
#include "ags/engine/ac/dynobj/script_gui.h"
|
||||
#include "ags/engine/ac/dynobj/script_hotspot.h"
|
||||
#include "ags/engine/ac/dynobj/script_inv_item.h"
|
||||
#include "ags/engine/ac/dynobj/script_mouse.h"
|
||||
#include "ags/engine/ac/dynobj/script_object.h"
|
||||
#include "ags/engine/ac/dynobj/script_overlay.h"
|
||||
#include "ags/engine/ac/dynobj/script_region.h"
|
||||
#include "ags/engine/ac/dynobj/script_string.h"
|
||||
#include "ags/engine/ac/dynobj/script_system.h"
|
||||
#include "ags/engine/ac/dynobj/script_view_frame.h"
|
||||
|
||||
#endif
|
||||
95
engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
Normal file
95
engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/core/types.h"
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/util/memory_stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int CCBasicObject::Dispose(void * /*address*/, bool /*force*/) {
|
||||
return 0; // cannot be removed from memory
|
||||
}
|
||||
|
||||
int CCBasicObject::Serialize(void * /*address*/, uint8_t * /*buffer*/, int /*bufsize*/) {
|
||||
return 0; // does not save data
|
||||
}
|
||||
|
||||
void *CCBasicObject::GetFieldPtr(void *address, intptr_t offset) {
|
||||
return static_cast<uint8_t *>(address) + offset;
|
||||
}
|
||||
|
||||
void CCBasicObject::Read(void *address, intptr_t offset, uint8_t *dest, size_t size) {
|
||||
memcpy(dest, static_cast<uint8_t *>(address) + offset, size);
|
||||
}
|
||||
|
||||
uint8_t CCBasicObject::ReadInt8(void *address, intptr_t offset) {
|
||||
return *(uint8_t *)(static_cast<uint8_t *>(address) + offset);
|
||||
}
|
||||
|
||||
int16_t CCBasicObject::ReadInt16(void *address, intptr_t offset) {
|
||||
return *(int16_t *)(static_cast<uint8_t *>(address) + offset);
|
||||
}
|
||||
|
||||
int32_t CCBasicObject::ReadInt32(void *address, intptr_t offset) {
|
||||
return *(int32_t *)(static_cast<uint8_t *>(address) + offset);
|
||||
}
|
||||
|
||||
float CCBasicObject::ReadFloat(void *address, intptr_t offset) {
|
||||
return *(float *)(static_cast<uint8_t *>(address) + offset);
|
||||
}
|
||||
|
||||
void CCBasicObject::Write(void *address, intptr_t offset, const uint8_t *src, size_t size) {
|
||||
memcpy(static_cast<uint8_t *>(address) + offset, src, size);
|
||||
}
|
||||
|
||||
void CCBasicObject::WriteInt8(void *address, intptr_t offset, uint8_t val) {
|
||||
*(uint8_t *)(static_cast<uint8_t *>(address) + offset) = val;
|
||||
}
|
||||
|
||||
void CCBasicObject::WriteInt16(void *address, intptr_t offset, int16_t val) {
|
||||
*(int16_t *)(static_cast<uint8_t *>(address) + offset) = val;
|
||||
}
|
||||
|
||||
void CCBasicObject::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
*(int32_t *)(static_cast<uint8_t *>(address) + offset) = val;
|
||||
}
|
||||
|
||||
void CCBasicObject::WriteFloat(void *address, intptr_t offset, float val) {
|
||||
*(float *)(static_cast<uint8_t *>(address) + offset) = val;
|
||||
}
|
||||
|
||||
int AGSCCDynamicObject::Serialize(void *address, uint8_t *buffer, int bufsize) {
|
||||
// If the required space is larger than the provided buffer,
|
||||
// then return negated required space, notifying the caller that a larger buffer is necessary
|
||||
size_t req_size = CalcSerializeSize(address);
|
||||
assert(req_size <= INT32_MAX); // dynamic object API does not support size > int32
|
||||
if (bufsize < 0 || req_size > static_cast<size_t>(bufsize))
|
||||
return -(static_cast<int32_t>(req_size));
|
||||
|
||||
MemoryStream mems(reinterpret_cast<uint8_t *>(buffer), bufsize, kStream_Write);
|
||||
Serialize(address, &mems);
|
||||
return static_cast<int32_t>(mems.GetPosition());
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
117
engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
Normal file
117
engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This is a collection of common implementations of the IScriptObject
|
||||
// interface. Intended to be used as parent classes for majority of the
|
||||
// script object managers.
|
||||
//
|
||||
// CCBasicObject: parent for managers that treat object contents as raw
|
||||
// byte buffer.
|
||||
//
|
||||
// AGSCCDynamicObject, extends CCBasicObject: parent for built-in dynamic
|
||||
// object managers; provides simpler serialization methods working with
|
||||
// streams instead of a raw memory buffer.
|
||||
//
|
||||
// AGSCCStaticObject, extends CCBasicObject: a formal stub, intended as
|
||||
// a parent for built-in static object managers.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_script_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS { namespace Shared { class Stream; } }
|
||||
|
||||
// CCBasicObject: basic implementation of the script object interface,
|
||||
// intended to be used as a parent for object/manager classes that do not
|
||||
// require specific implementation.
|
||||
// * Dispose ignored, never deletes any data on its own;
|
||||
// * Serialization skipped, does not save or load anything;
|
||||
// * Provides default implementation for reading and writing data fields,
|
||||
// treats the contents of an object as a raw byte buffer.
|
||||
struct CCBasicObject : public IScriptObject {
|
||||
public:
|
||||
virtual ~CCBasicObject() = default;
|
||||
|
||||
// Dispose the object
|
||||
int Dispose(void * /*address*/, bool /*force*/) override;
|
||||
// Serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(void * /*address*/, uint8_t * /*buffer*/, int /*bufsize*/) override;
|
||||
|
||||
//
|
||||
// Legacy support for reading and writing object fields by their relative offset
|
||||
//
|
||||
void *GetFieldPtr(void *address, intptr_t offset) override;
|
||||
void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) override;
|
||||
uint8_t ReadInt8(void *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(void *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
float ReadFloat(void *address, intptr_t offset) override;
|
||||
void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) override;
|
||||
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(void *address, intptr_t offset, float val) override;
|
||||
};
|
||||
|
||||
|
||||
// AGSCCDynamicObject: standard parent implementation for the built-in
|
||||
// script objects/manager.
|
||||
// * Serialization from a raw buffer; provides a virtual function that
|
||||
// accepts Stream, to be implemented in children instead.
|
||||
// * Provides Unserialize interface that accepts Stream.
|
||||
struct AGSCCDynamicObject : public CCBasicObject {
|
||||
public:
|
||||
virtual ~AGSCCDynamicObject() = default;
|
||||
|
||||
// TODO: pass savegame format version
|
||||
int Serialize(void *address, uint8_t *buffer, int bufsize) override;
|
||||
// Try unserializing the object from the given input stream
|
||||
virtual void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) = 0;
|
||||
|
||||
protected:
|
||||
// Savegame serialization
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
virtual size_t CalcSerializeSize(const void *address) = 0;
|
||||
// Write object data into the provided stream
|
||||
virtual void Serialize(const void *address, AGS::Shared::Stream *out) = 0;
|
||||
};
|
||||
|
||||
// CCStaticObject is a base class for managing static global objects in script.
|
||||
// The static objects can never be disposed, and do not support serialization
|
||||
// through IScriptObject interface.
|
||||
struct AGSCCStaticObject : public CCBasicObject {
|
||||
public:
|
||||
virtual ~AGSCCStaticObject() = default;
|
||||
|
||||
const char *GetType() override { return "StaticObject"; }
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
51
engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
Normal file
51
engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/engine/ac/dynobj/cc_audio_channel.h"
|
||||
#include "ags/engine/ac/dynobj/script_audio_channel.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const char *CCAudioChannel::GetType() {
|
||||
return "AudioChannel";
|
||||
}
|
||||
|
||||
size_t CCAudioChannel::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
void CCAudioChannel::Serialize(const void *address, Stream *out) {
|
||||
const ScriptAudioChannel *ach = static_cast<const ScriptAudioChannel *>(address);
|
||||
out->WriteInt32(ach->id);
|
||||
}
|
||||
|
||||
void CCAudioChannel::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int id = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_G(scrAudioChannel)[id], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
41
engines/ags/engine/ac/dynobj/cc_audio_channel.h
Normal file
41
engines/ags/engine/ac/dynobj/cc_audio_channel.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ_CC_AUDIO_CHANNEL_H
|
||||
#define AGS_ENGINE_DYNOBJ_CC_AUDIO_CHANNEL_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCAudioChannel final : AGSCCDynamicObject {
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
50
engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
Normal file
50
engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
|
||||
#include "ags/shared/ac/dynobj/script_audio_clip.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const char *CCAudioClip::GetType() {
|
||||
return "AudioClip";
|
||||
}
|
||||
|
||||
size_t CCAudioClip::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
void CCAudioClip::Serialize(const void *address, Stream *out) {
|
||||
const ScriptAudioClip *ach = static_cast<const ScriptAudioClip *>(address);
|
||||
out->WriteInt32(ach->id);
|
||||
}
|
||||
|
||||
void CCAudioClip::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int id = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_GP(game).audioClips[id], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
41
engines/ags/engine/ac/dynobj/cc_audio_clip.h
Normal file
41
engines/ags/engine/ac/dynobj/cc_audio_clip.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
|
||||
#define AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCAudioClip final : AGSCCDynamicObject {
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
370
engines/ags/engine/ac/dynobj/cc_character.cpp
Normal file
370
engines/ags/engine/ac/dynobj/cc_character.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_character.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/character_info.h"
|
||||
#include "ags/engine/ac/global_character.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/shared/script/cc_common.h" // cc_error
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCCharacter::GetType() {
|
||||
return "Character";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
size_t CCCharacter::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCCharacter::Serialize(const void *address, Stream *out) {
|
||||
const CharacterInfo *chaa = static_cast<const CharacterInfo *>(address);
|
||||
out->WriteInt32(chaa->index_id);
|
||||
}
|
||||
|
||||
void CCCharacter::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_GP(game).chars[num], this);
|
||||
}
|
||||
|
||||
uint8_t CCCharacter::ReadInt8(void *address, intptr_t offset) {
|
||||
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
const int on_offset = 28 * sizeof(int32_t) /* first var group */
|
||||
+ 301 * sizeof(int16_t) /* inventory */ + sizeof(int16_t) * 2 /* two shorts */ + 40 /* name */ + 20 /* scrname */;
|
||||
if (offset == on_offset)
|
||||
return ci->on;
|
||||
cc_error("ScriptCharacter: unsupported 'char' variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CCCharacter::WriteInt8(void *address, intptr_t offset, uint8_t val) {
|
||||
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
const int on_offset = 28 * sizeof(int32_t) /* first var group */
|
||||
+ 301 * sizeof(int16_t) /* inventory */ + sizeof(int16_t) * 2 /* two shorts */ + 40 /* name */ + 20 /* scrname */;
|
||||
if (offset == on_offset)
|
||||
ci->on = val;
|
||||
else
|
||||
cc_error("ScriptCharacter: unsupported 'char' variable offset %d", offset);
|
||||
}
|
||||
|
||||
int16_t CCCharacter::ReadInt16(void *address, intptr_t offset) {
|
||||
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
|
||||
// Handle inventory fields
|
||||
const int invoffset = 112;
|
||||
if (offset >= invoffset && offset < (uint)(invoffset + MAX_INV * sizeof(short))) {
|
||||
return ci->inv[(offset - invoffset) / sizeof(short)];
|
||||
}
|
||||
|
||||
switch (offset) {
|
||||
// +9 int32 = 36
|
||||
case 36:
|
||||
return ci->following;
|
||||
case 38:
|
||||
return ci->followinfo;
|
||||
// 40 +1 int32 = 44
|
||||
case 44:
|
||||
return ci->idletime;
|
||||
case 46:
|
||||
return ci->idleleft;
|
||||
case 48:
|
||||
return ci->transparency;
|
||||
case 50:
|
||||
return ci->baseline;
|
||||
// 52 +3 int32 = 64
|
||||
case 64:
|
||||
return ci->blinkview;
|
||||
case 66:
|
||||
return ci->blinkinterval;
|
||||
case 68:
|
||||
return ci->blinktimer;
|
||||
case 70:
|
||||
return ci->blinkframe;
|
||||
case 72:
|
||||
return ci->walkspeed_y;
|
||||
case 74:
|
||||
return ci->pic_yoffs;
|
||||
// 76 +2 int32 = 84
|
||||
case 84:
|
||||
return ci->speech_anim_speed;
|
||||
case 86:
|
||||
return ci->idle_anim_speed;
|
||||
case 88:
|
||||
return ci->blocking_width;
|
||||
case 90:
|
||||
return ci->blocking_height;
|
||||
// 92 +1 int32 = 96
|
||||
case 96:
|
||||
return ci->pic_xoffs;
|
||||
case 98:
|
||||
return ci->walkwaitcounter;
|
||||
case 100:
|
||||
return ci->loop;
|
||||
case 102:
|
||||
return ci->frame;
|
||||
case 104:
|
||||
return ci->walking;
|
||||
case 106:
|
||||
return ci->animating;
|
||||
case 108:
|
||||
return ci->walkspeed;
|
||||
case 110:
|
||||
return ci->animspeed;
|
||||
// 112 +301 int16 = 714 (skip inventory)
|
||||
case 714:
|
||||
return ci->actx;
|
||||
case 716:
|
||||
return ci->acty;
|
||||
default:
|
||||
cc_error("ScriptCharacter: unsupported 'short' variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCCharacter::WriteInt16(void *address, intptr_t offset, int16_t val) {
|
||||
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
|
||||
// Detect when a game directly modifies the inventory, which causes the displayed
|
||||
// and actual inventory to diverge since 2.70. Force an update of the displayed
|
||||
// inventory for older games that rely on this behaviour.
|
||||
const int invoffset = 112;
|
||||
if (offset >= invoffset && offset < (uint)(invoffset + MAX_INV * sizeof(short))) {
|
||||
ci->inv[(offset - invoffset) / sizeof(short)] = val;
|
||||
update_invorder();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: for safety, find out which of the following fields
|
||||
// must be readonly, and add assertions for them, i.e.:
|
||||
// cc_error("ScriptCharacter: attempt to write readonly 'short' variable at offset %d", offset);
|
||||
switch (offset) {
|
||||
// +9 int32 = 36
|
||||
case 36:
|
||||
ci->following = val;
|
||||
break;
|
||||
case 38:
|
||||
ci->followinfo = val;
|
||||
break;
|
||||
// 40 +1 int32 = 44
|
||||
case 44:
|
||||
ci->idletime = val;
|
||||
break;
|
||||
case 46:
|
||||
ci->idleleft = val;
|
||||
break;
|
||||
case 48:
|
||||
ci->transparency = val;
|
||||
break;
|
||||
case 50:
|
||||
ci->baseline = val;
|
||||
break;
|
||||
// 52 +3 int32 = 64
|
||||
case 64:
|
||||
ci->blinkview = val;
|
||||
break;
|
||||
case 66:
|
||||
ci->blinkinterval = val;
|
||||
break;
|
||||
case 68:
|
||||
ci->blinktimer = val;
|
||||
break;
|
||||
case 70:
|
||||
ci->blinkframe = val;
|
||||
break;
|
||||
case 72:
|
||||
ci->walkspeed_y = val;
|
||||
break;
|
||||
case 74:
|
||||
ci->pic_yoffs = val;
|
||||
break;
|
||||
// 76 +2 int32 = 84
|
||||
case 84:
|
||||
ci->speech_anim_speed = val;
|
||||
break;
|
||||
case 86:
|
||||
ci->idle_anim_speed = val;
|
||||
break;
|
||||
case 88:
|
||||
ci->blocking_width = val;
|
||||
break;
|
||||
case 90:
|
||||
ci->blocking_height = val;
|
||||
break;
|
||||
// 92 +1 int32 = 96
|
||||
case 96:
|
||||
ci->pic_xoffs = val;
|
||||
break;
|
||||
case 98:
|
||||
ci->walkwaitcounter = val;
|
||||
break;
|
||||
case 100:
|
||||
ci->loop = val;
|
||||
break;
|
||||
case 102:
|
||||
ci->frame = val;
|
||||
break;
|
||||
case 104:
|
||||
ci->walking = val;
|
||||
break;
|
||||
case 106:
|
||||
ci->animating = val;
|
||||
break;
|
||||
case 108:
|
||||
ci->walkspeed = val;
|
||||
break;
|
||||
case 110:
|
||||
ci->animspeed = val;
|
||||
break;
|
||||
// 112 +301 int16 = 714 (skip inventory)
|
||||
case 714:
|
||||
ci->actx = val;
|
||||
break;
|
||||
case 716:
|
||||
ci->acty = val;
|
||||
break;
|
||||
default:
|
||||
cc_error("ScriptCharacter: unsupported 'short' variable offset %d", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CCCharacter::ReadInt32(void *address, intptr_t offset) {
|
||||
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
return ci->defview;
|
||||
case 4:
|
||||
return ci->talkview;
|
||||
case 8:
|
||||
return ci->view;
|
||||
case 12:
|
||||
return ci->room;
|
||||
case 16:
|
||||
return ci->prevroom;
|
||||
case 20:
|
||||
return ci->x;
|
||||
case 24:
|
||||
return ci->y;
|
||||
case 28:
|
||||
return ci->wait;
|
||||
case 32:
|
||||
return ci->flags;
|
||||
// 36 +2 int16 = 40
|
||||
case 40:
|
||||
return ci->idleview;
|
||||
// 44 +4 int16 = 52
|
||||
case 52:
|
||||
return ci->activeinv;
|
||||
case 56:
|
||||
return ci->talkcolor;
|
||||
case 60:
|
||||
return ci->thinkview;
|
||||
// 64 +6 int16 = 76
|
||||
case 76:
|
||||
return ci->z;
|
||||
case 80:
|
||||
return ci->walkwait;
|
||||
// 84 +4 int16 = 100
|
||||
case 92:
|
||||
return ci->index_id;
|
||||
default:
|
||||
cc_error("ScriptCharacter: unsupported 'int' variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCCharacter::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
|
||||
|
||||
// TODO: for safety, find out which of the following fields
|
||||
// must be readonly, and add assertions for them, i.e.:
|
||||
// cc_error("ScriptCharacter: attempt to write readonly 'int' variable at offset %d", offset);
|
||||
switch (offset) {
|
||||
case 0:
|
||||
ci->defview = val;
|
||||
break;
|
||||
case 4:
|
||||
ci->talkview = val;
|
||||
break;
|
||||
case 8:
|
||||
ci->view = val;
|
||||
break;
|
||||
case 12:
|
||||
ci->room = val;
|
||||
break;
|
||||
case 16:
|
||||
ci->prevroom = val;
|
||||
break;
|
||||
case 20:
|
||||
ci->x = val;
|
||||
break;
|
||||
case 24:
|
||||
ci->y = val;
|
||||
break;
|
||||
case 28:
|
||||
ci->wait = val;
|
||||
break;
|
||||
case 32:
|
||||
ci->flags = val;
|
||||
break;
|
||||
// 36 +2 int16 = 40
|
||||
case 40:
|
||||
ci->idleview = val;
|
||||
break;
|
||||
// 44 +4 int16 = 52
|
||||
case 52:
|
||||
ci->activeinv = val;
|
||||
break;
|
||||
case 56:
|
||||
ci->talkcolor = val;
|
||||
break;
|
||||
case 60:
|
||||
ci->thinkview = val;
|
||||
break;
|
||||
// 64 +6 int16 = 76
|
||||
case 76:
|
||||
ci->z = val;
|
||||
break;
|
||||
case 80:
|
||||
ci->walkwait = val;
|
||||
break;
|
||||
// 84 +4 int16 = 100
|
||||
case 92:
|
||||
ci->index_id = val;
|
||||
break;
|
||||
default:
|
||||
cc_error("ScriptCharacter: unsupported 'int' variable offset %d", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
58
engines/ags/engine/ac/dynobj/cc_character.h
Normal file
58
engines/ags/engine/ac/dynobj/cc_character.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Wrapper around script "Character" struct, managing access to its variables.
|
||||
// Assumes object data contains CharacterInfo object.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCCharacter final : AGSCCDynamicObject {
|
||||
public:
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
uint8_t ReadInt8(void *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(void *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
55
engines/ags/engine/ac/dynobj/cc_dialog.cpp
Normal file
55
engines/ags/engine/ac/dynobj/cc_dialog.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_dialog.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/ac/dialog.h"
|
||||
#include "ags/shared/ac/dialog_topic.h"
|
||||
#include "ags/shared/ac/game_struct_defines.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCDialog::GetType() {
|
||||
return "Dialog";
|
||||
}
|
||||
|
||||
size_t CCDialog::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCDialog::Serialize(const void *address, Stream *out) {
|
||||
const ScriptDialog *shh = static_cast<const ScriptDialog *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCDialog::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_GP(scrDialog)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_dialog.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_dialog.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCDialog final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
114
engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
Normal file
114
engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/ac/dynobj/script_string.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const char *CCDynamicArray::TypeName = "CCDynamicArray";
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCDynamicArray::GetType() {
|
||||
return TypeName;
|
||||
}
|
||||
|
||||
int CCDynamicArray::Dispose(void *address, bool force) {
|
||||
// If it's an array of managed objects, release their ref counts;
|
||||
// except if this array is forcefully removed from the managed pool,
|
||||
// in which case just ignore these.
|
||||
if (!force) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
bool is_managed = (hdr.ElemCount & ARRAY_MANAGED_TYPE_FLAG) != 0;
|
||||
const uint32_t el_count = hdr.ElemCount & (~ARRAY_MANAGED_TYPE_FLAG);
|
||||
|
||||
if (is_managed) { // Dynamic array of managed pointers: subref them directly
|
||||
const uint32_t *handles = reinterpret_cast<const uint32_t *>(address);
|
||||
for (uint32_t i = 0; i < el_count; ++i) {
|
||||
if (handles[i] > 0)
|
||||
ccReleaseObjectReference(handles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t CCDynamicArray::CalcSerializeSize(const void *address) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
return hdr.TotalSize + FileHeaderSz;
|
||||
}
|
||||
|
||||
void CCDynamicArray::Serialize(const void *address, Stream *out) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
out->WriteInt32(hdr.ElemCount);
|
||||
out->WriteInt32(hdr.TotalSize);
|
||||
out->Write(address, hdr.TotalSize); // elements
|
||||
}
|
||||
|
||||
void CCDynamicArray::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
uint8_t *new_arr = new uint8_t[(data_sz - FileHeaderSz) + MemHeaderSz];
|
||||
Header &hdr = reinterpret_cast<Header &>(*new_arr);
|
||||
hdr.ElemCount = in->ReadInt32();
|
||||
hdr.TotalSize = in->ReadInt32();
|
||||
in->Read(new_arr + MemHeaderSz, data_sz - FileHeaderSz);
|
||||
ccRegisterUnserializedObject(index, &new_arr[MemHeaderSz], this);
|
||||
}
|
||||
|
||||
/* static */ DynObjectRef CCDynamicArray::Create(int numElements, int elementSize, bool isManagedType) {
|
||||
uint8_t *new_arr = new uint8_t[numElements * elementSize + MemHeaderSz];
|
||||
memset(new_arr, 0, numElements * elementSize + MemHeaderSz);
|
||||
Header &hdr = reinterpret_cast<Header &>(*new_arr);
|
||||
hdr.ElemCount = numElements | (ARRAY_MANAGED_TYPE_FLAG * isManagedType);
|
||||
hdr.TotalSize = elementSize * numElements;
|
||||
void *obj_ptr = &new_arr[MemHeaderSz];
|
||||
int32_t handle = ccRegisterManagedObject(obj_ptr, &_GP(globalDynamicArray));
|
||||
if (handle == 0) {
|
||||
delete[] new_arr;
|
||||
return DynObjectRef();
|
||||
}
|
||||
return DynObjectRef(handle, obj_ptr, &_GP(globalDynamicArray));
|
||||
}
|
||||
|
||||
DynObjectRef DynamicArrayHelpers::CreateStringArray(const std::vector<const char *> items) {
|
||||
// NOTE: we need element size of "handle" for array of managed pointers
|
||||
DynObjectRef arr = _GP(globalDynamicArray).Create(items.size(), sizeof(int32_t), true);
|
||||
if (!arr.Obj)
|
||||
return arr;
|
||||
// Create script strings and put handles into array
|
||||
int32_t *slots = static_cast<int32_t *>(arr.Obj);
|
||||
for (auto s : items) {
|
||||
DynObjectRef str = ScriptString::Create(s);
|
||||
// We must add reference count, because the string is going to be saved
|
||||
// within another object (array), not returned to script directly
|
||||
ccAddObjectReference(str.Handle);
|
||||
*(slots++) = str.Handle;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
80
engines/ags/engine/ac/dynobj/cc_dynamic_array.h
Normal file
80
engines/ags/engine/ac/dynobj/cc_dynamic_array.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define ARRAY_MANAGED_TYPE_FLAG 0x80000000
|
||||
|
||||
struct CCDynamicArray final : AGSCCDynamicObject {
|
||||
public:
|
||||
static const char *TypeName;
|
||||
|
||||
struct Header {
|
||||
// May contain ARRAY_MANAGED_TYPE_FLAG
|
||||
uint32_t ElemCount = 0u;
|
||||
// TODO: refactor and store "elem size" instead
|
||||
uint32_t TotalSize = 0u;
|
||||
};
|
||||
|
||||
CCDynamicArray() = default;
|
||||
~CCDynamicArray() = default;
|
||||
|
||||
inline static const Header &GetHeader(const void *address) {
|
||||
return reinterpret_cast<const Header &>(*(static_cast<const uint8_t *>(address) - MemHeaderSz));
|
||||
}
|
||||
|
||||
// Create managed array object and return a pointer to the beginning of a buffer
|
||||
static DynObjectRef Create(int numElements, int elementSize, bool isManagedType);
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
int Dispose(void *address, bool force) override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
private:
|
||||
// The size of the array's header in memory, prepended to the element data
|
||||
static const size_t MemHeaderSz = sizeof(Header);
|
||||
// The size of the serialized header
|
||||
static const size_t FileHeaderSz = sizeof(uint32_t) * 2;
|
||||
|
||||
// Savegame serialization
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
// Helper functions for setting up dynamic arrays.
|
||||
namespace DynamicArrayHelpers {
|
||||
// Create array of managed strings
|
||||
DynObjectRef CreateStringArray(const std::vector<const char *>);
|
||||
} // namespace DynamicArrayHelpers
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
53
engines/ags/engine/ac/dynobj/cc_gui.cpp
Normal file
53
engines/ags/engine/ac/dynobj/cc_gui.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_gui.h"
|
||||
#include "ags/engine/ac/dynobj/script_gui.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCGUI::GetType() {
|
||||
return "GUI";
|
||||
}
|
||||
|
||||
size_t CCGUI::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCGUI::Serialize(const void *address, Stream *out) {
|
||||
const ScriptGUI *shh = static_cast<const ScriptGUI *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCGUI::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_GP(scrGui)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_gui.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_gui.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CCGUI_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CCGUI_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCGUI final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
57
engines/ags/engine/ac/dynobj/cc_gui_object.cpp
Normal file
57
engines/ags/engine/ac/dynobj/cc_gui_object.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_gui_object.h"
|
||||
#include "ags/engine/ac/dynobj/script_gui.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCGUIObject::GetType() {
|
||||
return "GUIObject";
|
||||
}
|
||||
|
||||
size_t CCGUIObject::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t) * 2;
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCGUIObject::Serialize(const void *address, Stream *out) {
|
||||
const GUIObject *guio = static_cast<const GUIObject *>(address);
|
||||
out->WriteInt32(guio->ParentId);
|
||||
out->WriteInt32(guio->Id);
|
||||
}
|
||||
|
||||
void CCGUIObject::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int guinum = in->ReadInt32();
|
||||
int objnum = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, _GP(guis)[guinum].GetControl(objnum), this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_gui_object.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_gui_object.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCGUIObject final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
55
engines/ags/engine/ac/dynobj/cc_hotspot.cpp
Normal file
55
engines/ags/engine/ac/dynobj/cc_hotspot.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_hotspot.h"
|
||||
#include "ags/engine/ac/dynobj/script_hotspot.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/common_defines.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCHotspot::GetType() {
|
||||
return "Hotspot";
|
||||
}
|
||||
|
||||
size_t CCHotspot::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCHotspot::Serialize(const void *address, Stream *out) {
|
||||
const ScriptHotspot *shh = static_cast<const ScriptHotspot *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCHotspot::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_G(scrHotspot)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_hotspot.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_hotspot.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCHotspot final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
54
engines/ags/engine/ac/dynobj/cc_inventory.cpp
Normal file
54
engines/ags/engine/ac/dynobj/cc_inventory.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_inventory.h"
|
||||
#include "ags/engine/ac/dynobj/script_inv_item.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/character_info.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCInventory::GetType() {
|
||||
return "Inventory";
|
||||
}
|
||||
|
||||
size_t CCInventory::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCInventory::Serialize(const void *address, Stream *out) {
|
||||
const ScriptInvItem *shh = static_cast<const ScriptInvItem *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCInventory::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_G(scrInv)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_inventory.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_inventory.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCInventory final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
55
engines/ags/engine/ac/dynobj/cc_object.cpp
Normal file
55
engines/ags/engine/ac/dynobj/cc_object.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_object.h"
|
||||
#include "ags/engine/ac/dynobj/script_object.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/common_defines.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCObject::GetType() {
|
||||
return "Object";
|
||||
}
|
||||
|
||||
size_t CCObject::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCObject::Serialize(const void *address, Stream *out) {
|
||||
const ScriptObject *shh = static_cast<const ScriptObject *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCObject::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_G(scrObj)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_object.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_object.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCObject final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
55
engines/ags/engine/ac/dynobj/cc_region.cpp
Normal file
55
engines/ags/engine/ac/dynobj/cc_region.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_region.h"
|
||||
#include "ags/engine/ac/dynobj/script_region.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/common_defines.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCRegion::GetType() {
|
||||
return "Region";
|
||||
}
|
||||
|
||||
size_t CCRegion::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void CCRegion::Serialize(const void *address, Stream *out) {
|
||||
const ScriptRegion *shh = static_cast<const ScriptRegion *>(address);
|
||||
out->WriteInt32(shh->id);
|
||||
}
|
||||
|
||||
void CCRegion::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int num = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, &_G(scrRegion)[num], this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/cc_region.h
Normal file
44
engines/ags/engine/ac/dynobj/cc_region.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CCREGION_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CCREGION_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCRegion final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
128
engines/ags/engine/ac/dynobj/cc_script_object.h
Normal file
128
engines/ags/engine/ac/dynobj/cc_script_object.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// IScriptObject: script managed object interface.
|
||||
// Provides interaction with a object which allocation and lifetime is
|
||||
// managed by the engine and/or the managed pool rather than the script VM.
|
||||
// These may be both static objects existing throughout the game, and
|
||||
// dynamic objects allocated by the script command.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_SCRIPT_OBJECT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_SCRIPT_OBJECT_H
|
||||
|
||||
#include "common/std/utility.h"
|
||||
#include "ags/shared/core/types.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
struct IScriptObject;
|
||||
|
||||
// A convenience struct for grouping handle and dynamic object
|
||||
struct DynObjectRef {
|
||||
const int Handle = 0;
|
||||
void *const Obj = nullptr;
|
||||
IScriptObject *const Mgr = nullptr;
|
||||
|
||||
DynObjectRef() = default;
|
||||
DynObjectRef(int handle, void *obj, IScriptObject *mgr)
|
||||
: Handle(handle), Obj(obj), Mgr(mgr) {}
|
||||
};
|
||||
|
||||
struct IScriptObject {
|
||||
// WARNING: The first section of this interface is also a part of the AGS plugin API!
|
||||
|
||||
// when a ref count reaches 0, this is called with the address
|
||||
// of the object. Return 1 to remove the object from memory, 0 to
|
||||
// leave it
|
||||
// The "force" flag tells system to detach the object, breaking any links and references
|
||||
// to other managed objects or game resources (instead of disposing these too).
|
||||
// TODO: it might be better to rewrite the managed pool and remove this flag at all,
|
||||
// because it makes the use of this interface prone to mistakes.
|
||||
virtual int Dispose(void *address, bool force = false) = 0;
|
||||
// return the type name of the object
|
||||
virtual const char *GetType() = 0;
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
// TODO: pass savegame format version
|
||||
virtual int Serialize(void *address, uint8_t *buffer, int bufsize) = 0;
|
||||
|
||||
// WARNING: following section is not a part of plugin API, therefore these methods
|
||||
// should **never** be called for kScValPluginObject script objects!
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset.
|
||||
// These methods allow to "remap" script struct field access, by taking the
|
||||
// legacy offset, and using it rather as a field ID than an address, for example.
|
||||
// Consequently these also let trigger side-effects, such as updating an object
|
||||
// after a field value is written to.
|
||||
// RE: GetFieldPtr() -
|
||||
// According to AGS script specification, when the old-string pointer or char array is passed
|
||||
// as an argument, the byte-code does not include any specific command for the member variable
|
||||
// retrieval and instructs to pass an address of the object itself with certain offset.
|
||||
// This results in functions like StrCopy writing directly over object address.
|
||||
// There may be other implementations, but the big question is: how to detect when this is
|
||||
// necessary, because byte-code does not contain any distinct operation for this case.
|
||||
// The worst thing here is that with the current byte-code structure we can never tell whether
|
||||
// offset 0 means getting pointer to whole object or a pointer to its first field.
|
||||
virtual void *GetFieldPtr(void *address, intptr_t offset) = 0;
|
||||
virtual void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) = 0;
|
||||
virtual uint8_t ReadInt8(void *address, intptr_t offset) = 0;
|
||||
virtual int16_t ReadInt16(void *address, intptr_t offset) = 0;
|
||||
virtual int32_t ReadInt32(void *address, intptr_t offset) = 0;
|
||||
virtual float ReadFloat(void *address, intptr_t offset) = 0;
|
||||
virtual void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) = 0;
|
||||
virtual void WriteInt8(void *address, intptr_t offset, uint8_t val) = 0;
|
||||
virtual void WriteInt16(void *address, intptr_t offset, int16_t val) = 0;
|
||||
virtual void WriteInt32(void *address, intptr_t offset, int32_t val) = 0;
|
||||
virtual void WriteFloat(void *address, intptr_t offset, float val) = 0;
|
||||
|
||||
protected:
|
||||
IScriptObject() {}
|
||||
virtual ~IScriptObject() {}
|
||||
};
|
||||
|
||||
// The interface of a script objects deserializer that handles multiple types.
|
||||
struct ICCObjectCollectionReader {
|
||||
virtual ~ICCObjectCollectionReader() {}
|
||||
// TODO: pass savegame format version
|
||||
virtual void Unserialize(int32_t handle, const char *objectType, const char *serializedData, int dataSize) = 0;
|
||||
};
|
||||
|
||||
// The interface of a script objects deserializer that handles a single type.
|
||||
// WARNING: a part of the plugin API.
|
||||
struct ICCObjectReader {
|
||||
virtual ~ICCObjectReader() {}
|
||||
virtual void Unserialize(int32_t handle, const char *serializedData, int dataSize) = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
140
engines/ags/engine/ac/dynobj/cc_serializer.cpp
Normal file
140
engines/ags/engine/ac/dynobj/cc_serializer.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/util/memory_stream.h"
|
||||
#include "ags/engine/ac/dynobj/cc_serializer.h"
|
||||
#include "ags/engine/ac/dynobj/all_dynamic_classes.h"
|
||||
#include "ags/engine/ac/dynobj/all_script_classes.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
|
||||
#include "ags/engine/ac/dynobj/script_user_object.h"
|
||||
#include "ags/engine/ac/dynobj/script_camera.h"
|
||||
#include "ags/engine/ac/dynobj/script_containers.h"
|
||||
#include "ags/engine/ac/dynobj/script_file.h"
|
||||
#include "ags/engine/ac/dynobj/script_viewport.h"
|
||||
#include "ags/engine/ac/game.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/plugins/plugin_engine.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// *** De-serialization of script objects
|
||||
|
||||
void AGSDeSerializer::Unserialize(int32_t index, const char *objectType, const char *serializedData, int dataSize) {
|
||||
if (dataSize < 0) {
|
||||
quitprintf("Unserialise: invalid data size (%d) for object type '%s'", dataSize, objectType);
|
||||
return; // TODO: don't quit, return error
|
||||
}
|
||||
// Note that while our builtin classes may accept Stream object,
|
||||
// classes registered by plugin cannot, because streams are not (yet)
|
||||
// part of the plugin API.
|
||||
size_t data_sz = static_cast<size_t>(dataSize);
|
||||
assert(data_sz <= INT32_MAX); // dynamic object API does not support size > int32
|
||||
MemoryStream mems(reinterpret_cast<const uint8_t *>(serializedData), dataSize);
|
||||
|
||||
// TODO: consider this: there are object types that are part of the
|
||||
// script's foundation, because they are created by the bytecode ops:
|
||||
// such as DynamicArray and UserObject. *Maybe* these should be moved
|
||||
// to certain "base serializer" class which guarantees their restoration.
|
||||
//
|
||||
// TODO: should we support older save versions here (DynArray, UserObj)?
|
||||
// might have to use older class names to distinguish save formats
|
||||
if (strcmp(objectType, CCDynamicArray::TypeName) == 0) {
|
||||
_GP(globalDynamicArray).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, ScriptUserObject::TypeName) == 0) {
|
||||
ScriptUserObject *suo = new ScriptUserObject();
|
||||
suo->Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "GUIObject") == 0) {
|
||||
_GP(ccDynamicGUIObject).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Character") == 0) {
|
||||
_GP(ccDynamicCharacter).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Hotspot") == 0) {
|
||||
_GP(ccDynamicHotspot).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Region") == 0) {
|
||||
_GP(ccDynamicRegion).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Inventory") == 0) {
|
||||
_GP(ccDynamicInv).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Dialog") == 0) {
|
||||
_GP(ccDynamicDialog).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "GUI") == 0) {
|
||||
_GP(ccDynamicGUI).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Object") == 0) {
|
||||
_GP(ccDynamicObject).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "String") == 0) {
|
||||
_GP(myScriptStringImpl).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "File") == 0) {
|
||||
// files cannot be restored properly -- so just recreate
|
||||
// the object; attempting any operations on it will fail
|
||||
sc_File *scf = new sc_File();
|
||||
ccRegisterUnserializedObject(index, scf, scf);
|
||||
} else if (strcmp(objectType, "Overlay") == 0) {
|
||||
ScriptOverlay *scf = new ScriptOverlay();
|
||||
scf->Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "DateTime") == 0) {
|
||||
ScriptDateTime *scf = new ScriptDateTime();
|
||||
scf->Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "ViewFrame") == 0) {
|
||||
ScriptViewFrame *scf = new ScriptViewFrame();
|
||||
scf->Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "DynamicSprite") == 0) {
|
||||
ScriptDynamicSprite *scf = new ScriptDynamicSprite();
|
||||
scf->Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "DrawingSurface") == 0) {
|
||||
ScriptDrawingSurface *sds = new ScriptDrawingSurface();
|
||||
sds->Unserialize(index, &mems, data_sz);
|
||||
|
||||
if (sds->isLinkedBitmapOnly) {
|
||||
_G(dialogOptionsRenderingSurface) = sds;
|
||||
}
|
||||
} else if (strcmp(objectType, "DialogOptionsRendering") == 0) {
|
||||
_GP(ccDialogOptionsRendering).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "StringDictionary") == 0) {
|
||||
Dict_Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "StringSet") == 0) {
|
||||
Set_Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Viewport2") == 0) {
|
||||
Viewport_Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "Camera2") == 0) {
|
||||
Camera_Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "AudioChannel") == 0) {
|
||||
_GP(ccDynamicAudio).Unserialize(index, &mems, data_sz);
|
||||
} else if (strcmp(objectType, "AudioClip") == 0) {
|
||||
_GP(ccDynamicAudioClip).Unserialize(index, &mems, data_sz);
|
||||
} else {
|
||||
// check if the type is read by a plugin
|
||||
for (const auto &pr : _GP(pluginReaders)) {
|
||||
if (pr.Type == objectType) {
|
||||
if (dataSize == 0) { // avoid unserializing stubbed plugins
|
||||
debug(0, "Skipping %s plugin unserialization (dataSize = 0)", objectType);
|
||||
return;
|
||||
}
|
||||
pr.Reader->Unserialize(index, serializedData, dataSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
quitprintf("Unserialise: unknown object type: '%s'", objectType);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
35
engines/ags/engine/ac/dynobj/cc_serializer.h
Normal file
35
engines/ags/engine/ac/dynobj/cc_serializer.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_script_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct AGSDeSerializer : ICCObjectCollectionReader {
|
||||
void Unserialize(int32_t index, const char *objectType, const char *serializedData, int dataSize) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
88
engines/ags/engine/ac/dynobj/cc_static_array.cpp
Normal file
88
engines/ags/engine/ac/dynobj/cc_static_array.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_static_array.h"
|
||||
#include "ags/engine/ac/dynobj/cc_script_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
void CCStaticArray::Create(IScriptObject *mgr, size_t elem_script_size, size_t elem_mem_size, size_t elem_count) {
|
||||
_mgr = mgr;
|
||||
_elemScriptSize = elem_script_size;
|
||||
_elemMemSize = elem_mem_size;
|
||||
_elemCount = elem_count;
|
||||
}
|
||||
|
||||
void *CCStaticArray::GetFieldPtr(void *address, intptr_t offset) {
|
||||
return GetElementPtr(address, offset);
|
||||
}
|
||||
|
||||
void CCStaticArray::Read(void *address, intptr_t offset, uint8_t *dest, size_t size) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->Read(el_ptr, offset % _elemScriptSize, dest, size);
|
||||
}
|
||||
|
||||
uint8_t CCStaticArray::ReadInt8(void *address, intptr_t offset) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->ReadInt8(el_ptr, offset % _elemScriptSize);
|
||||
}
|
||||
|
||||
int16_t CCStaticArray::ReadInt16(void *address, intptr_t offset) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->ReadInt16(el_ptr, offset % _elemScriptSize);
|
||||
}
|
||||
|
||||
int32_t CCStaticArray::ReadInt32(void *address, intptr_t offset) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->ReadInt32(el_ptr, offset % _elemScriptSize);
|
||||
}
|
||||
|
||||
float CCStaticArray::ReadFloat(void *address, intptr_t offset) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->ReadFloat(el_ptr, offset % _elemScriptSize);
|
||||
}
|
||||
|
||||
void CCStaticArray::Write(void *address, intptr_t offset, const uint8_t *src, size_t size) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->Write(el_ptr, offset % _elemScriptSize, src, size);
|
||||
}
|
||||
|
||||
void CCStaticArray::WriteInt8(void *address, intptr_t offset, uint8_t val) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->WriteInt8(el_ptr, offset % _elemScriptSize, val);
|
||||
}
|
||||
|
||||
void CCStaticArray::WriteInt16(void *address, intptr_t offset, int16_t val) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->WriteInt16(el_ptr, offset % _elemScriptSize, val);
|
||||
}
|
||||
|
||||
void CCStaticArray::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->WriteInt32(el_ptr, offset % _elemScriptSize, val);
|
||||
}
|
||||
|
||||
void CCStaticArray::WriteFloat(void *address, intptr_t offset, float val) {
|
||||
void *el_ptr = GetElementPtr(address, offset);
|
||||
return _mgr->WriteFloat(el_ptr, offset % _elemScriptSize, val);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
96
engines/ags/engine/ac/dynobj/cc_static_array.h
Normal file
96
engines/ags/engine/ac/dynobj/cc_static_array.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CCStaticArray manages access to an array of script objects,
|
||||
// where an element's size counted by script's bytecode may differ from the
|
||||
// real element size in the engine's memory.
|
||||
// The purpose of this is to remove size restriction from the engine's structs
|
||||
// exposed to scripts.
|
||||
//
|
||||
// FIXME: [ivan-mogilko] the above was meant to work, but in reality it doesn't
|
||||
// and won't, at least not without some extra workarounds.
|
||||
// The problem that I missed here is following:
|
||||
// when the script compiler is told to get an Nth element of a global struct
|
||||
// array, such as character[n], it calculates the memory address as
|
||||
// array address + sizeof(Character) * n.
|
||||
// If this address is used for the read/write operations, these ops can be
|
||||
// intercepted by interpreter and remapped into the real fields
|
||||
// (see IScriptObject::ReadN, WriteN interface)
|
||||
// But if this address is used IN POINTER COMPARISON, then we cannot do
|
||||
// anything. And if our real struct in the engine is stored on a different
|
||||
// relative memory offset than one expected by compiler, then this pointer
|
||||
// comparison will fail, e.g. script expression like
|
||||
// if (player == character[n])
|
||||
//
|
||||
// NOTE: on the other hand, similar effect could be achieved by separating
|
||||
// object data into two or more structs, where "base" structs are stored in
|
||||
// the exposed arrays (part of API), while extending structs are stored
|
||||
// separately. This is more an issue of engine data design.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_STATIC_ARRAY_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_STATIC_ARRAY_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
|
||||
struct CCStaticArray : public AGSCCStaticObject {
|
||||
public:
|
||||
~CCStaticArray() override {}
|
||||
|
||||
void Create(IScriptObject *mgr, size_t elem_script_size, size_t elem_mem_size, size_t elem_count = SIZE_MAX /*unknown*/);
|
||||
|
||||
inline IScriptObject *GetObjectManager() const {
|
||||
return _mgr;
|
||||
}
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset
|
||||
inline void *GetElementPtr(void *address, intptr_t legacy_offset) {
|
||||
return static_cast<uint8_t *>(address) + (legacy_offset / _elemScriptSize) * _elemMemSize;
|
||||
}
|
||||
|
||||
void *GetFieldPtr(void *address, intptr_t offset) override;
|
||||
void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) override;
|
||||
uint8_t ReadInt8(void *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(void *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
float ReadFloat(void *address, intptr_t offset) override;
|
||||
void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) override;
|
||||
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(void *address, intptr_t offset, float val) override;
|
||||
|
||||
private:
|
||||
IScriptObject *_mgr = nullptr;
|
||||
size_t _elemScriptSize = 0u;
|
||||
size_t _elemMemSize = 0u;
|
||||
size_t _elemCount = 0u;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
154
engines/ags/engine/ac/dynobj/dynobj_manager.cpp
Normal file
154
engines/ags/engine/ac/dynobj/dynobj_manager.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// C-Script run-time interpreter (c) 2001 Chris Jones
|
||||
//
|
||||
// You must DISABLE OPTIMIZATIONS AND REGISTER VARIABLES in your compiler
|
||||
// when compiling this, or strange results can happen.
|
||||
//
|
||||
// There is a problem with importing functions on 16-bit compilers: the
|
||||
// script system assumes that all parameters are passed as 4 bytes, which
|
||||
// ints are not on 16-bit systems. Be sure to define all parameters as longs,
|
||||
// or join the 21st century and switch to DJGPP or Visual C++.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/core/platform.h"
|
||||
#include "ags/engine/ac/dynobj/managed_object_pool.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/shared/script/cc_internal.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// register a memory handle for the object and allow script
|
||||
// pointers to point to it
|
||||
int32_t ccRegisterManagedObject(void *object, IScriptObject *callback, ScriptValueType obj_type) {
|
||||
int32_t handl = _GP(pool).AddObject(object, callback, obj_type);
|
||||
|
||||
ManagedObjectLog("Register managed object type '%s' handle=%d addr=%08X",
|
||||
((callback == NULL) ? "(unknown)" : callback->GetType()), handl, object);
|
||||
|
||||
return handl;
|
||||
}
|
||||
|
||||
// register a de-serialized object
|
||||
int32_t ccRegisterUnserializedObject(int index, void *object, IScriptObject *callback, ScriptValueType obj_type) {
|
||||
return _GP(pool).AddUnserializedObject(object, callback, obj_type, index);
|
||||
}
|
||||
|
||||
// unregister a particular object
|
||||
int ccUnRegisterManagedObject(void *object) {
|
||||
return _GP(pool).RemoveObject(object);
|
||||
}
|
||||
|
||||
// remove all registered objects
|
||||
void ccUnregisterAllObjects() {
|
||||
_GP(pool).reset();
|
||||
}
|
||||
|
||||
// serialize all objects to disk
|
||||
void ccSerializeAllObjects(Stream *out) {
|
||||
_GP(pool).WriteToDisk(out);
|
||||
}
|
||||
|
||||
// un-serialise all objects (will remove all currently registered ones)
|
||||
int ccUnserializeAllObjects(Stream *in, ICCObjectCollectionReader *callback) {
|
||||
return _GP(pool).ReadFromDisk(in, callback);
|
||||
}
|
||||
|
||||
// dispose the object if RefCount==0
|
||||
void ccAttemptDisposeObject(int32_t handle) {
|
||||
_GP(pool).CheckDispose(handle);
|
||||
}
|
||||
|
||||
// translate between object handles and memory addresses
|
||||
int32_t ccGetObjectHandleFromAddress(void *address) {
|
||||
// set to null
|
||||
if (address == nullptr)
|
||||
return 0;
|
||||
|
||||
int32_t handl = _GP(pool).AddressToHandle(address);
|
||||
|
||||
ManagedObjectLog("Line %d WritePtr: %08X to %d", _G(currentline), address, handl);
|
||||
|
||||
if (handl == 0) {
|
||||
cc_error("Pointer cast failure: the object being pointed to is not in the managed object pool");
|
||||
return -1;
|
||||
}
|
||||
return handl;
|
||||
}
|
||||
|
||||
void *ccGetObjectAddressFromHandle(int32_t handle) {
|
||||
if (handle == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
void *addr = _GP(pool).HandleToAddress(handle);
|
||||
|
||||
ManagedObjectLog("Line %d ReadPtr: %d to %08X", _G(currentline), handle, addr);
|
||||
|
||||
if (addr == nullptr) {
|
||||
cc_error("Error retrieving pointer: invalid handle %d", handle);
|
||||
return nullptr;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
ScriptValueType ccGetObjectAddressAndManagerFromHandle(int32_t handle, void *&object, IScriptObject *&manager) {
|
||||
if (handle == 0) {
|
||||
object = nullptr;
|
||||
manager = nullptr;
|
||||
return kScValUndefined;
|
||||
}
|
||||
ScriptValueType obj_type = _GP(pool).HandleToAddressAndManager(handle, object, manager);
|
||||
if (obj_type == kScValUndefined) {
|
||||
cc_error("Error retrieving pointer: invalid handle %d", handle);
|
||||
}
|
||||
return obj_type;
|
||||
}
|
||||
|
||||
int ccAddObjectReference(int32_t handle) {
|
||||
if (handle == 0)
|
||||
return 0;
|
||||
|
||||
return _GP(pool).AddRef(handle);
|
||||
}
|
||||
|
||||
int ccReleaseObjectReference(int32_t handle) {
|
||||
if (handle == 0)
|
||||
return 0;
|
||||
|
||||
if (_GP(pool).HandleToAddress(handle) == nullptr) {
|
||||
cc_error("Error releasing pointer: invalid handle %d", handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _GP(pool).SubRef(handle);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
73
engines/ags/engine/ac/dynobj/dynobj_manager.h
Normal file
73
engines/ags/engine/ac/dynobj/dynobj_manager.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Dynamic object management utilities.
|
||||
// TODO: frankly, many of these functions could be factored out by a direct
|
||||
// use of ManagedPool class.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_MANAGER_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_MANAGER_H
|
||||
|
||||
#include "ags/shared/core/types.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/engine/ac/dynobj/cc_script_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
// register a memory handle for the object and allow script
|
||||
// pointers to point to it
|
||||
extern int32_t ccRegisterManagedObject(void *object, IScriptObject *, ScriptValueType obj_type = kScValScriptObject);
|
||||
// register a de-serialized object
|
||||
extern int32_t ccRegisterUnserializedObject(int index, void *object, IScriptObject *, ScriptValueType obj_type = kScValScriptObject);
|
||||
// unregister a particular object
|
||||
extern int ccUnRegisterManagedObject(void *object);
|
||||
// remove all registered objects
|
||||
extern void ccUnregisterAllObjects();
|
||||
// serialize all objects to disk
|
||||
extern void ccSerializeAllObjects(Shared::Stream *out);
|
||||
// un-serialise all objects (will remove all currently registered ones)
|
||||
extern int ccUnserializeAllObjects(Shared::Stream *in, ICCObjectCollectionReader *callback);
|
||||
// dispose the object if RefCount==0
|
||||
extern void ccAttemptDisposeObject(int32_t handle);
|
||||
// translate between object handles and memory addresses
|
||||
extern int32_t ccGetObjectHandleFromAddress(void *address);
|
||||
extern void *ccGetObjectAddressFromHandle(int32_t handle);
|
||||
extern ScriptValueType ccGetObjectAddressAndManagerFromHandle(int32_t handle, void *&object, IScriptObject *&manager);
|
||||
|
||||
extern int ccAddObjectReference(int32_t handle);
|
||||
extern int ccReleaseObjectReference(int32_t handle);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
347
engines/ags/engine/ac/dynobj/managed_object_pool.cpp
Normal file
347
engines/ags/engine/ac/dynobj/managed_object_pool.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/engine/ac/dynobj/managed_object_pool.h"
|
||||
#include "ags/shared/debugging/out.h"
|
||||
#include "ags/shared/util/string_utils.h" // fputstring, etc
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/shared/script/cc_internal.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const auto OBJECT_CACHE_MAGIC_NUMBER = 0xa30b;
|
||||
const auto SERIALIZE_BUFFER_SIZE = 10240;
|
||||
const auto GARBAGE_COLLECTION_INTERVAL = 1024;
|
||||
const auto RESERVED_SIZE = 2048;
|
||||
|
||||
int ManagedObjectPool::Remove(ManagedObject &o, bool force) {
|
||||
const bool can_remove = o.callback->Dispose(o.addr, force) != 0;
|
||||
if (!(can_remove || force))
|
||||
return 0;
|
||||
|
||||
available_ids.push(o.handle);
|
||||
handleByAddress.erase(o.addr);
|
||||
ManagedObjectLog("Line %d Disposed managed object handle=%d", currentline, o.handle);
|
||||
o = ManagedObject();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t ManagedObjectPool::AddRef(int32_t handle) {
|
||||
if (handle < 1 || (size_t)handle >= objects.size())
|
||||
return 0;
|
||||
|
||||
auto &o = objects[handle];
|
||||
if (!o.isUsed())
|
||||
return 0;
|
||||
o.refCount++;
|
||||
ManagedObjectLog("Line %d AddRef: handle=%d new refcount=%d", _G(currentline), o.handle, o.refCount);
|
||||
return o.refCount;
|
||||
}
|
||||
|
||||
int ManagedObjectPool::CheckDispose(int32_t handle) {
|
||||
if (handle < 1 || (size_t)handle >= objects.size())
|
||||
return 1;
|
||||
|
||||
auto &o = objects[handle];
|
||||
if (!o.isUsed()) {
|
||||
return 1;
|
||||
}
|
||||
if (o.refCount >= 1) {
|
||||
return 0;
|
||||
}
|
||||
return Remove(o);
|
||||
}
|
||||
|
||||
int32_t ManagedObjectPool::SubRef(int32_t handle) {
|
||||
if (handle < 1 || (size_t)handle >= objects.size()) {
|
||||
return 0;
|
||||
}
|
||||
auto &o = objects[handle];
|
||||
if (!o.isUsed()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
o.refCount--;
|
||||
const auto newRefCount = o.refCount;
|
||||
const auto canBeDisposed = (o.addr != disableDisposeForObject);
|
||||
if (canBeDisposed && o.refCount <= 0) {
|
||||
Remove(o);
|
||||
}
|
||||
// object could be removed at this point, don't use any values.
|
||||
ManagedObjectLog("Line %d SubRef: handle=%d new refcount=%d canBeDisposed=%d", _G(currentline), handle, newRefCount, canBeDisposed);
|
||||
return newRefCount;
|
||||
}
|
||||
|
||||
int32_t ManagedObjectPool::AddressToHandle(void *addr) {
|
||||
if (addr == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
auto it = handleByAddress.find(addr);
|
||||
if (it == handleByAddress.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->_value;
|
||||
}
|
||||
|
||||
// this function is called often (whenever a pointer is used)
|
||||
void *ManagedObjectPool::HandleToAddress(int32_t handle) {
|
||||
if (handle < 1 || (size_t)handle >= objects.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto &o = objects[handle];
|
||||
if (!o.isUsed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return o.addr;
|
||||
}
|
||||
|
||||
// this function is called often (whenever a pointer is used)
|
||||
ScriptValueType ManagedObjectPool::HandleToAddressAndManager(int32_t handle, void *&object, IScriptObject *&manager) {
|
||||
if ((handle < 1 || (size_t)handle >= objects.size()) || !objects[handle].isUsed()) {
|
||||
object = nullptr;
|
||||
manager = nullptr;
|
||||
return kScValUndefined;
|
||||
}
|
||||
auto &o = objects[handle];
|
||||
object = (void *)(o.addr); // WARNING: This strips the const from the char* pointer.
|
||||
manager = o.callback;
|
||||
return o.obj_type;
|
||||
}
|
||||
|
||||
int ManagedObjectPool::RemoveObject(void *address) {
|
||||
if (address == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
auto it = handleByAddress.find(address);
|
||||
if (it == handleByAddress.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto &o = objects[it->_value];
|
||||
return Remove(o, true);
|
||||
}
|
||||
|
||||
void ManagedObjectPool::RunGarbageCollectionIfAppropriate() {
|
||||
if (objectCreationCounter <= GARBAGE_COLLECTION_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
RunGarbageCollection();
|
||||
objectCreationCounter = 0;
|
||||
}
|
||||
|
||||
void ManagedObjectPool::RunGarbageCollection() {
|
||||
for (int i = 1; i < nextHandle; i++) {
|
||||
auto &o = objects[i];
|
||||
if (!o.isUsed()) {
|
||||
continue;
|
||||
}
|
||||
if (o.refCount < 1) {
|
||||
Remove(o);
|
||||
}
|
||||
}
|
||||
ManagedObjectLog("Ran garbage collection");
|
||||
}
|
||||
|
||||
int ManagedObjectPool::Add(int handle, void *address, IScriptObject *callback, ScriptValueType obj_type)
|
||||
{
|
||||
auto &o = objects[handle];
|
||||
assert(!o.isUsed());
|
||||
|
||||
o = ManagedObject(obj_type, handle, address, callback);
|
||||
|
||||
handleByAddress.insert({address, handle});
|
||||
ManagedObjectLog("Allocated managed object type=%s, handle=%d, addr=%08X", callback->GetType(), handle, address);
|
||||
return handle;
|
||||
}
|
||||
|
||||
int ManagedObjectPool::AddObject(void *address, IScriptObject *callback, ScriptValueType obj_type) {
|
||||
int32_t handle;
|
||||
|
||||
if (!available_ids.empty()) {
|
||||
handle = available_ids.front();
|
||||
available_ids.pop();
|
||||
} else {
|
||||
handle = nextHandle++;
|
||||
if ((size_t)handle >= objects.size()) {
|
||||
objects.resize(handle + 1024, ManagedObject());
|
||||
}
|
||||
}
|
||||
|
||||
objectCreationCounter++;
|
||||
return Add(handle, address, callback, obj_type);
|
||||
}
|
||||
|
||||
int ManagedObjectPool::AddUnserializedObject(void *address, IScriptObject *callback, ScriptValueType obj_type, int handle) {
|
||||
if (handle < 1) {
|
||||
cc_error("Attempt to assign invalid handle: %d", handle);
|
||||
return 0;
|
||||
}
|
||||
if ((size_t)handle >= objects.size()) {
|
||||
objects.resize(handle + 1024, ManagedObject());
|
||||
}
|
||||
|
||||
return Add(handle, address, callback, obj_type);
|
||||
}
|
||||
|
||||
void ManagedObjectPool::WriteToDisk(Stream *out) {
|
||||
|
||||
// use this opportunity to clean up any non-referenced pointers
|
||||
RunGarbageCollection();
|
||||
|
||||
std::vector<uint8_t> serializeBuffer;
|
||||
serializeBuffer.resize(SERIALIZE_BUFFER_SIZE);
|
||||
|
||||
out->WriteInt32(OBJECT_CACHE_MAGIC_NUMBER);
|
||||
out->WriteInt32(2); // version
|
||||
|
||||
int size = 0;
|
||||
for (int i = 1; i < nextHandle; i++) {
|
||||
auto const &o = objects[i];
|
||||
if (o.isUsed()) {
|
||||
size += 1;
|
||||
}
|
||||
}
|
||||
out->WriteInt32(size);
|
||||
|
||||
for (int i = 1; i < nextHandle; i++) {
|
||||
auto const &o = objects[i];
|
||||
if (!o.isUsed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle
|
||||
out->WriteInt32(o.handle);
|
||||
// write the type of the object
|
||||
StrUtil::WriteCStr(o.callback->GetType(), out);
|
||||
// now write the object data
|
||||
int bytesWritten = o.callback->Serialize(o.addr, &serializeBuffer.front(), serializeBuffer.size());
|
||||
if ((bytesWritten < 0) && ((size_t)(-bytesWritten) > serializeBuffer.size())) {
|
||||
// buffer not big enough, re-allocate with requested size
|
||||
serializeBuffer.resize(-bytesWritten);
|
||||
bytesWritten = o.callback->Serialize(o.addr, &serializeBuffer.front(), serializeBuffer.size());
|
||||
}
|
||||
assert(bytesWritten >= 0);
|
||||
out->WriteInt32(bytesWritten);
|
||||
out->Write(&serializeBuffer.front(), bytesWritten);
|
||||
out->WriteInt32(o.refCount);
|
||||
|
||||
ManagedObjectLog("Wrote handle = %d", o.handle);
|
||||
}
|
||||
}
|
||||
|
||||
int ManagedObjectPool::ReadFromDisk(Stream *in, ICCObjectCollectionReader *reader) {
|
||||
if (in->ReadInt32() != OBJECT_CACHE_MAGIC_NUMBER) {
|
||||
cc_error("Data was not written by ccSeralize");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char typeNameBuffer[200];
|
||||
std::vector<char> serializeBuffer;
|
||||
serializeBuffer.resize(SERIALIZE_BUFFER_SIZE);
|
||||
|
||||
auto version = in->ReadInt32();
|
||||
|
||||
switch (version) {
|
||||
case 1: {
|
||||
// IMPORTANT: numObjs is "nextHandleId", which is why we iterate from 1 to numObjs-1
|
||||
int numObjs = in->ReadInt32();
|
||||
for (int i = 1; i < numObjs; i++) {
|
||||
StrUtil::ReadCStr(typeNameBuffer, in, sizeof(typeNameBuffer));
|
||||
if (typeNameBuffer[0] != 0) {
|
||||
size_t numBytes = in->ReadInt32();
|
||||
if (numBytes > serializeBuffer.size()) {
|
||||
serializeBuffer.resize(numBytes);
|
||||
}
|
||||
in->Read(&serializeBuffer.front(), numBytes);
|
||||
// Delegate work to ICCObjectReader
|
||||
reader->Unserialize(i, typeNameBuffer, &serializeBuffer.front(), numBytes);
|
||||
objects[i].refCount = in->ReadInt32();
|
||||
ManagedObjectLog("Read handle = %d", objects[i].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
// This is actually number of objects written.
|
||||
int objectsSize = in->ReadInt32();
|
||||
for (int i = 0; i < objectsSize; i++) {
|
||||
auto handle = in->ReadInt32();
|
||||
assert(handle >= 1);
|
||||
StrUtil::ReadCStr(typeNameBuffer, in, sizeof(typeNameBuffer));
|
||||
assert(typeNameBuffer[0] != 0);
|
||||
size_t numBytes = in->ReadInt32();
|
||||
if (numBytes > serializeBuffer.size()) {
|
||||
serializeBuffer.resize(numBytes);
|
||||
}
|
||||
in->Read(&serializeBuffer.front(), numBytes);
|
||||
// Delegate work to ICCObjectReader
|
||||
reader->Unserialize(handle, typeNameBuffer, &serializeBuffer.front(), numBytes);
|
||||
objects[handle].refCount = in->ReadInt32();
|
||||
ManagedObjectLog("Read handle = %d", objects[i].handle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cc_error("Invalid data version: %d", version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// re-adjust next handles. (in case saved in random order)
|
||||
available_ids = std::queue<int32_t>();
|
||||
nextHandle = 1;
|
||||
|
||||
for (const auto &o : objects) {
|
||||
if (o.isUsed()) {
|
||||
nextHandle = o.handle + 1;
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < nextHandle; i++) {
|
||||
if (!objects[i].isUsed()) {
|
||||
available_ids.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// de-allocate all objects
|
||||
void ManagedObjectPool::reset() {
|
||||
for (int i = 1; i < nextHandle; i++) {
|
||||
auto &o = objects[i];
|
||||
if (!o.isUsed()) {
|
||||
continue;
|
||||
}
|
||||
Remove(o, true);
|
||||
}
|
||||
available_ids = std::queue<int32_t>();
|
||||
nextHandle = 1;
|
||||
}
|
||||
|
||||
ManagedObjectPool::ManagedObjectPool() : objectCreationCounter(0), nextHandle(1), available_ids(), objects(RESERVED_SIZE, ManagedObject()), handleByAddress() {
|
||||
handleByAddress.reserve(RESERVED_SIZE);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
113
engines/ags/engine/ac/dynobj/managed_object_pool.h
Normal file
113
engines/ags/engine/ac/dynobj/managed_object_pool.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "common/std/queue.h"
|
||||
#include "common/std/map.h"
|
||||
|
||||
#include "ags/shared/core/platform.h"
|
||||
#include "ags/engine/script/runtime_script_value.h"
|
||||
#include "ags/engine/ac/dynobj/cc_script_object.h" // IScriptObject
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
struct Pointer_Hash {
|
||||
uint operator()(void *v) const {
|
||||
return static_cast<uint>(reinterpret_cast<uintptr>(v));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ManagedObjectPool final {
|
||||
private:
|
||||
// TODO: find out if we can make handle size_t
|
||||
struct ManagedObject {
|
||||
ScriptValueType obj_type;
|
||||
int32_t handle;
|
||||
void *addr;
|
||||
IScriptObject *callback;
|
||||
int refCount;
|
||||
|
||||
bool isUsed() const {
|
||||
return obj_type != kScValUndefined;
|
||||
}
|
||||
|
||||
ManagedObject() : obj_type(kScValUndefined), handle(0), addr(nullptr),
|
||||
callback(nullptr), refCount(0) {}
|
||||
ManagedObject(ScriptValueType theType, int32_t theHandle,
|
||||
void *theAddr, IScriptObject *theCallback)
|
||||
: obj_type(theType), handle(theHandle), addr(theAddr),
|
||||
callback(theCallback), refCount(0) {
|
||||
}
|
||||
};
|
||||
|
||||
int objectCreationCounter; // used to do garbage collection every so often
|
||||
|
||||
int32_t nextHandle{}; // TODO: manage nextHandle's going over INT32_MAX !
|
||||
std::queue<int32_t> available_ids;
|
||||
std::vector<ManagedObject> objects;
|
||||
std::unordered_map<void *, int32_t, Pointer_Hash> handleByAddress;
|
||||
|
||||
int Add(int handle, void *address, IScriptObject *callback, ScriptValueType obj_type);
|
||||
int Remove(ManagedObject &o, bool force = false);
|
||||
void RunGarbageCollection();
|
||||
|
||||
public:
|
||||
|
||||
int32_t AddRef(int32_t handle);
|
||||
int CheckDispose(int32_t handle);
|
||||
int32_t SubRef(int32_t handle);
|
||||
int32_t AddressToHandle(void *addr);
|
||||
void *HandleToAddress(int32_t handle);
|
||||
ScriptValueType HandleToAddressAndManager(int32_t handle, void *&object, IScriptObject *&manager);
|
||||
int RemoveObject(void *address);
|
||||
void RunGarbageCollectionIfAppropriate();
|
||||
int AddObject(void *address, IScriptObject *callback, ScriptValueType obj_type);
|
||||
int AddUnserializedObject(void *address, IScriptObject *callback, ScriptValueType obj_type, int handle);
|
||||
void WriteToDisk(Shared::Stream *out);
|
||||
int ReadFromDisk(Shared::Stream *in, ICCObjectCollectionReader *reader);
|
||||
void reset();
|
||||
ManagedObjectPool();
|
||||
|
||||
void *disableDisposeForObject{ nullptr };
|
||||
};
|
||||
|
||||
// Extreme(!!) verbosity managed memory pool log
|
||||
#if DEBUG_MANAGED_OBJECTS
|
||||
#define ManagedObjectLog(...) Debug::Printf(kDbgGroup_ManObj, kDbgMsg_Debug, __VA_ARGS__)
|
||||
#else
|
||||
#define ManagedObjectLog(...)
|
||||
#endif
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
34
engines/ags/engine/ac/dynobj/script_audio_channel.h
Normal file
34
engines/ags/engine/ac/dynobj/script_audio_channel.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptAudioChannel {
|
||||
int id = 0;
|
||||
int reserved = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
74
engines/ags/engine/ac/dynobj/script_camera.cpp
Normal file
74
engines/ags/engine/ac/dynobj/script_camera.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_camera.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/shared/util/bbop.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
ScriptCamera::ScriptCamera(int id) : _id(id) {
|
||||
}
|
||||
|
||||
const char *ScriptCamera::GetType() {
|
||||
return "Camera2";
|
||||
}
|
||||
|
||||
int ScriptCamera::Dispose(void *address, bool force) {
|
||||
// Note that ScriptCamera is a reference to actual Camera object,
|
||||
// and this deletes the reference, while camera may remain in GameState.
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t ScriptCamera::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
void ScriptCamera::Serialize(const void *address, Stream *out) {
|
||||
out->WriteInt32(_id);
|
||||
}
|
||||
|
||||
void ScriptCamera::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
_id = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptCamera *Camera_Unserialize(int handle, Stream *in, size_t data_sz) {
|
||||
// The way it works now, we must not create a new script object,
|
||||
// but acquire one from the GameState, which keeps the first reference.
|
||||
// This is essential because GameState should be able to invalidate any
|
||||
// script references when Camera gets removed.
|
||||
const int id = in->ReadInt32();
|
||||
if (id >= 0) {
|
||||
auto scam = _GP(play).RegisterRoomCamera(id, handle);
|
||||
if (scam)
|
||||
return scam;
|
||||
}
|
||||
return new ScriptCamera(-1); // make invalid reference
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
64
engines/ags/engine/ac/dynobj/script_camera.h
Normal file
64
engines/ags/engine/ac/dynobj/script_camera.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_CAMERA_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_CAMERA_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// ScriptCamera keeps a reference to actual room Camera in script.
|
||||
struct ScriptCamera final : AGSCCDynamicObject {
|
||||
public:
|
||||
ScriptCamera(int id);
|
||||
|
||||
// Get camera index; negative means the camera was deleted
|
||||
int GetID() const {
|
||||
return _id;
|
||||
}
|
||||
void SetID(int id) {
|
||||
_id = id;
|
||||
}
|
||||
// Reset camera index to indicate that this reference is no longer valid
|
||||
void Invalidate() {
|
||||
_id = -1;
|
||||
}
|
||||
|
||||
const char *GetType() override;
|
||||
int Dispose(void *address, bool force) override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
|
||||
private:
|
||||
int _id = -1; // index of camera in the game state array
|
||||
};
|
||||
|
||||
// Unserialize camera from the memory stream
|
||||
ScriptCamera *Camera_Unserialize(int handle, AGS::Shared::Stream *in, size_t data_sz);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
41
engines/ags/engine/ac/dynobj/script_containers.h
Normal file
41
engines/ags/engine/ac/dynobj/script_containers.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTCONTAINERS_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTCONTAINERS_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
class ScriptDictBase;
|
||||
class ScriptSetBase;
|
||||
|
||||
// Create and register new dictionary
|
||||
ScriptDictBase *Dict_Create(bool sorted, bool case_sensitive);
|
||||
// Unserialize dictionary from the memory stream
|
||||
ScriptDictBase *Dict_Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz);
|
||||
// Create and register new set
|
||||
ScriptSetBase *Set_Create(bool sorted, bool case_sensitive);
|
||||
// Unserialize set from the memory stream
|
||||
ScriptSetBase *Set_Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
71
engines/ags/engine/ac/dynobj/script_date_time.cpp
Normal file
71
engines/ags/engine/ac/dynobj/script_date_time.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_date_time.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int ScriptDateTime::Dispose(void *address, bool force) {
|
||||
// always dispose a DateTime
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDateTime::GetType() {
|
||||
return "DateTime";
|
||||
}
|
||||
|
||||
size_t ScriptDateTime::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t) * 7;
|
||||
}
|
||||
|
||||
void ScriptDateTime::Serialize(const void *address, Stream *out) {
|
||||
out->WriteInt32(year);
|
||||
out->WriteInt32(month);
|
||||
out->WriteInt32(day);
|
||||
out->WriteInt32(hour);
|
||||
out->WriteInt32(minute);
|
||||
out->WriteInt32(second);
|
||||
out->WriteInt32(rawUnixTime);
|
||||
}
|
||||
|
||||
void ScriptDateTime::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
year = in->ReadInt32();
|
||||
month = in->ReadInt32();
|
||||
day = in->ReadInt32();
|
||||
hour = in->ReadInt32();
|
||||
minute = in->ReadInt32();
|
||||
second = in->ReadInt32();
|
||||
rawUnixTime = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDateTime::ScriptDateTime() {
|
||||
year = month = day = 0;
|
||||
hour = minute = second = 0;
|
||||
rawUnixTime = 0;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
49
engines/ags/engine/ac/dynobj/script_date_time.h
Normal file
49
engines/ags/engine/ac/dynobj/script_date_time.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
|
||||
#define AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptDateTime final : AGSCCDynamicObject {
|
||||
int year, month, day;
|
||||
int hour, minute, second;
|
||||
int rawUnixTime;
|
||||
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
ScriptDateTime();
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
34
engines/ags/engine/ac/dynobj/script_dialog.h
Normal file
34
engines/ags/engine/ac/dynobj/script_dialog.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptDialog {
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
// return the type name of the object
|
||||
const char *ScriptDialogOptionsRendering::GetType() {
|
||||
return "DialogOptionsRendering";
|
||||
}
|
||||
|
||||
size_t ScriptDialogOptionsRendering::CalcSerializeSize(const void * /*address*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
void ScriptDialogOptionsRendering::Serialize(const void *address, Stream *out) {
|
||||
}
|
||||
|
||||
void ScriptDialogOptionsRendering::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
void ScriptDialogOptionsRendering::Reset() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
hasAlphaChannel = false;
|
||||
parserTextboxX = 0;
|
||||
parserTextboxY = 0;
|
||||
parserTextboxWidth = 0;
|
||||
dialogID = 0;
|
||||
surfaceToRenderTo = nullptr;
|
||||
surfaceAccessed = false;
|
||||
activeOptionID = -1;
|
||||
chosenOptionID = -1;
|
||||
needRepaint = false;
|
||||
}
|
||||
|
||||
ScriptDialogOptionsRendering::ScriptDialogOptionsRendering() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptDialogOptionsRendering final : AGSCCDynamicObject {
|
||||
int x, y, width, height;
|
||||
bool hasAlphaChannel;
|
||||
int parserTextboxX, parserTextboxY;
|
||||
int parserTextboxWidth;
|
||||
int dialogID;
|
||||
int activeOptionID;
|
||||
int chosenOptionID;
|
||||
ScriptDrawingSurface *surfaceToRenderTo;
|
||||
bool surfaceAccessed;
|
||||
bool needRepaint;
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
void Reset();
|
||||
|
||||
ScriptDialogOptionsRendering();
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
54
engines/ags/engine/ac/dynobj/script_dict.cpp
Normal file
54
engines/ags/engine/ac/dynobj/script_dict.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_dict.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int ScriptDictBase::Dispose(void *address, bool force) {
|
||||
Clear();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDictBase::GetType() {
|
||||
return "StringDictionary";
|
||||
}
|
||||
|
||||
size_t ScriptDictBase::CalcSerializeSize(const void * /*address*/) {
|
||||
return CalcContainerSize();
|
||||
}
|
||||
|
||||
void ScriptDictBase::Serialize(const void *address, Stream *out) {
|
||||
out->WriteInt32(IsSorted());
|
||||
out->WriteInt32(IsCaseSensitive());
|
||||
SerializeContainer(out);
|
||||
}
|
||||
|
||||
void ScriptDictBase::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
// NOTE: we expect sorted/case flags are read by external reader;
|
||||
// this is awkward, but I did not find better design solution atm
|
||||
UnserializeContainer(in);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
193
engines/ags/engine/ac/dynobj/script_dict.h
Normal file
193
engines/ags/engine/ac/dynobj/script_dict.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Managed script object wrapping std::map<String, String> and
|
||||
// unordered_map<String, String>.
|
||||
//
|
||||
// TODO: support wrapping non-owned Dictionary, passed by the reference, -
|
||||
// that would let expose internal engine's dicts using same interface.
|
||||
// TODO: maybe optimize key lookup operations further by not creating a String
|
||||
// object from const char*. It seems, C++14 standard allows to use convertible
|
||||
// types as keys; need to research what performance impact that would make.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
|
||||
|
||||
#include "common/std/map.h"
|
||||
#include "common/std/map.h"
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
#include "ags/shared/util/string_types.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
class ScriptDictBase : public AGSCCDynamicObject {
|
||||
public:
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
virtual bool IsCaseSensitive() const = 0;
|
||||
virtual bool IsSorted() const = 0;
|
||||
|
||||
virtual void Clear() = 0;
|
||||
virtual bool Contains(const char *key) = 0;
|
||||
virtual const char *Get(const char *key) = 0;
|
||||
virtual bool Remove(const char *key) = 0;
|
||||
virtual bool Set(const char *key, const char *value) = 0;
|
||||
virtual int GetItemCount() = 0;
|
||||
virtual void GetKeys(std::vector<const char *> &buf) const = 0;
|
||||
virtual void GetValues(std::vector<const char *> &buf) const = 0;
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
|
||||
private:
|
||||
virtual size_t CalcContainerSize() = 0;
|
||||
virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
|
||||
virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
|
||||
};
|
||||
|
||||
template <typename TDict, bool is_sorted, bool is_casesensitive>
|
||||
class ScriptDictImpl final : public ScriptDictBase {
|
||||
public:
|
||||
typedef typename TDict::const_iterator ConstIterator;
|
||||
|
||||
ScriptDictImpl() {}
|
||||
|
||||
bool IsCaseSensitive() const override {
|
||||
return is_casesensitive;
|
||||
}
|
||||
bool IsSorted() const override {
|
||||
return is_sorted;
|
||||
}
|
||||
|
||||
void Clear() override {
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
DeleteItem(it);
|
||||
_dic.clear();
|
||||
}
|
||||
bool Contains(const char *key) override {
|
||||
#ifdef AGS_PLATFORM_SCUMMVM
|
||||
return _dic.find(String::Wrapper(key)) != _dic.end();
|
||||
#else
|
||||
return _dic.count(String::Wrapper(key)) != 0;
|
||||
#endif
|
||||
}
|
||||
const char *Get(const char *key) override {
|
||||
auto it = _dic.find(String::Wrapper(key));
|
||||
if (it == _dic.end()) return nullptr;
|
||||
return it->_value.GetCStr();
|
||||
}
|
||||
bool Remove(const char *key) override {
|
||||
auto it = _dic.find(String::Wrapper(key));
|
||||
if (it == _dic.end()) return false;
|
||||
DeleteItem(it);
|
||||
_dic.erase(it);
|
||||
return true;
|
||||
}
|
||||
bool Set(const char *key, const char *value) override {
|
||||
if (!key)
|
||||
return false;
|
||||
if (!value) {
|
||||
// Remove keys with null value
|
||||
Remove(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
return TryAddItem(String(key), String(value));
|
||||
}
|
||||
int GetItemCount() override {
|
||||
return _dic.size();
|
||||
}
|
||||
void GetKeys(std::vector<const char *> &buf) const override {
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
buf.push_back(it->_key.GetCStr());
|
||||
}
|
||||
void GetValues(std::vector<const char *> &buf) const override {
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
buf.push_back(it->_value.GetCStr());
|
||||
}
|
||||
|
||||
private:
|
||||
bool TryAddItem(const String &key, const String &value) {
|
||||
_dic[key] = value;
|
||||
return true;
|
||||
}
|
||||
void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
|
||||
|
||||
size_t CalcContainerSize() override {
|
||||
// 2 class properties + item count
|
||||
size_t total_sz = sizeof(int32_t) * 3;
|
||||
// (int32 + string buffer) per item
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it) {
|
||||
total_sz += sizeof(int32_t) + it->_key.GetLength();
|
||||
total_sz += sizeof(int32_t) + it->_value.GetLength();
|
||||
}
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
void SerializeContainer(AGS::Shared::Stream *out) override
|
||||
{
|
||||
out->WriteInt32((int)_dic.size());
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
{
|
||||
out->WriteInt32((int)it->_key.GetLength());
|
||||
out->Write(it->_key.GetCStr(), it->_key.GetLength());
|
||||
out->WriteInt32((int)it->_value.GetLength());
|
||||
out->Write(it->_value.GetCStr(), it->_value.GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
void UnserializeContainer(AGS::Shared::Stream *in) override {
|
||||
size_t item_count = in->ReadInt32();
|
||||
for (size_t i = 0; i < item_count; ++i) {
|
||||
size_t key_len = in->ReadInt32();
|
||||
String key = String::FromStreamCount(in, key_len);
|
||||
size_t value_len = in->ReadInt32();
|
||||
if (value_len != (size_t)-1) // do not restore keys with null value (old format)
|
||||
{
|
||||
String value = String::FromStreamCount(in, value_len);
|
||||
TryAddItem(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TDict _dic;
|
||||
};
|
||||
|
||||
typedef ScriptDictImpl< std::map<String, String>, true, true > ScriptDict;
|
||||
typedef ScriptDictImpl< std::map<String, String, IgnoreCase_LessThan>, true, false > ScriptDictCI;
|
||||
typedef ScriptDictImpl< std::unordered_map<String, String>, false, true > ScriptHashDict;
|
||||
typedef ScriptDictImpl< std::unordered_map<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo>, false, false > ScriptHashDictCI;
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
138
engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
Normal file
138
engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/engine/ac/runtime_defines.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/engine/ac/draw.h"
|
||||
#include "ags/engine/ac/drawing_surface.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
Bitmap *ScriptDrawingSurface::GetBitmapSurface() {
|
||||
// TODO: consider creating weak_ptr here, and store one in the DrawingSurface!
|
||||
if (roomBackgroundNumber >= 0)
|
||||
return _GP(thisroom).BgFrames[roomBackgroundNumber].Graphic.get();
|
||||
else if (dynamicSpriteNumber >= 0)
|
||||
return _GP(spriteset)[dynamicSpriteNumber];
|
||||
else if (dynamicSurfaceNumber >= 0)
|
||||
return _G(dynamicallyCreatedSurfaces)[dynamicSurfaceNumber].get();
|
||||
else if (linkedBitmapOnly != nullptr)
|
||||
return linkedBitmapOnly;
|
||||
else if (roomMaskType > kRoomAreaNone)
|
||||
return _GP(thisroom).GetMask(roomMaskType);
|
||||
quit("!DrawingSurface: attempted to use surface after Release was called");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bitmap *ScriptDrawingSurface::StartDrawing() {
|
||||
return this->GetBitmapSurface();
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::FinishedDrawingReadOnly() {
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::FinishedDrawing() {
|
||||
FinishedDrawingReadOnly();
|
||||
modified = 1;
|
||||
}
|
||||
|
||||
int ScriptDrawingSurface::Dispose(void *address, bool force) {
|
||||
|
||||
// dispose the drawing surface
|
||||
DrawingSurface_Release(this);
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDrawingSurface::GetType() {
|
||||
return "DrawingSurface";
|
||||
}
|
||||
|
||||
size_t ScriptDrawingSurface::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t) * 9;
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::Serialize(const void *address, Stream *out) {
|
||||
// pack mask type in the last byte of a negative integer
|
||||
// note: (-1) is reserved for "unused", for backward compatibility
|
||||
if (roomMaskType > 0)
|
||||
out->WriteInt32(0xFFFFFF00 | roomMaskType);
|
||||
else
|
||||
out->WriteInt32(roomBackgroundNumber);
|
||||
out->WriteInt32(dynamicSpriteNumber);
|
||||
out->WriteInt32(dynamicSurfaceNumber);
|
||||
out->WriteInt32(currentColour);
|
||||
out->WriteInt32(currentColourScript);
|
||||
out->WriteInt32(highResCoordinates);
|
||||
out->WriteInt32(modified);
|
||||
out->WriteInt32(hasAlphaChannel);
|
||||
out->WriteInt32(isLinkedBitmapOnly ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
int room_ds = in->ReadInt32();
|
||||
if (room_ds >= 0)
|
||||
roomBackgroundNumber = room_ds;
|
||||
// negative value may contain a mask type
|
||||
else if ((room_ds & 0xFF) != 0xFF)
|
||||
roomMaskType = (RoomAreaMask)(room_ds & 0xFF);
|
||||
dynamicSpriteNumber = in->ReadInt32();
|
||||
dynamicSurfaceNumber = in->ReadInt32();
|
||||
currentColour = in->ReadInt32();
|
||||
currentColourScript = in->ReadInt32();
|
||||
highResCoordinates = in->ReadInt32();
|
||||
modified = in->ReadInt32();
|
||||
hasAlphaChannel = in->ReadInt32();
|
||||
isLinkedBitmapOnly = (in->ReadInt32() != 0);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDrawingSurface::ScriptDrawingSurface() {
|
||||
roomBackgroundNumber = -1;
|
||||
roomMaskType = kRoomAreaNone;
|
||||
dynamicSpriteNumber = -1;
|
||||
dynamicSurfaceNumber = -1;
|
||||
isLinkedBitmapOnly = false;
|
||||
linkedBitmapOnly = nullptr;
|
||||
currentColour = _GP(play).raw_color;
|
||||
currentColourScript = 0;
|
||||
modified = 0;
|
||||
hasAlphaChannel = 0;
|
||||
highResCoordinates = 0;
|
||||
// NOTE: Normally in contemporary games coordinates ratio will always be 1:1.
|
||||
// But we still support legacy drawing, so have to set this up even for modern games,
|
||||
// otherwise we'd have to complicate conversion conditions further.
|
||||
if (_GP(game).IsLegacyHiRes() && _GP(game).IsDataInNativeCoordinates()) {
|
||||
highResCoordinates = 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
71
engines/ags/engine/ac/dynobj/script_drawing_surface.h
Normal file
71
engines/ags/engine/ac/dynobj/script_drawing_surface.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptDrawingSurface final : AGSCCDynamicObject {
|
||||
// These numbers and types are used to determine the source of this drawing surface;
|
||||
// only one of them can be valid for this surface.
|
||||
int roomBackgroundNumber;
|
||||
RoomAreaMask roomMaskType;
|
||||
int dynamicSpriteNumber;
|
||||
int dynamicSurfaceNumber;
|
||||
bool isLinkedBitmapOnly;
|
||||
AGS::Shared::Bitmap *linkedBitmapOnly;
|
||||
int currentColour;
|
||||
int currentColourScript;
|
||||
int highResCoordinates;
|
||||
int modified;
|
||||
int hasAlphaChannel;
|
||||
//Shared::Bitmap* abufBackup;
|
||||
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
AGS::Shared::Bitmap *GetBitmapSurface();
|
||||
AGS::Shared::Bitmap *StartDrawing();
|
||||
void PointToGameResolution(int *xcoord, int *ycoord);
|
||||
void SizeToGameResolution(int *width, int *height);
|
||||
void SizeToGameResolution(int *adjustValue);
|
||||
void SizeToDataResolution(int *adjustValue);
|
||||
void FinishedDrawing();
|
||||
void FinishedDrawingReadOnly();
|
||||
|
||||
ScriptDrawingSurface();
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
67
engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
Normal file
67
engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/engine/ac/dynamic_sprite.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int ScriptDynamicSprite::Dispose(void *address, bool force) {
|
||||
// always dispose
|
||||
if ((slot) && (!force))
|
||||
free_dynamic_sprite(slot);
|
||||
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDynamicSprite::GetType() {
|
||||
return "DynamicSprite";
|
||||
}
|
||||
|
||||
size_t ScriptDynamicSprite::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
void ScriptDynamicSprite::Serialize(const void *address, Stream *out) {
|
||||
out->WriteInt32(slot);
|
||||
}
|
||||
|
||||
|
||||
void ScriptDynamicSprite::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
slot = in->ReadInt32();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite::ScriptDynamicSprite(int theSlot) {
|
||||
slot = theSlot;
|
||||
ccRegisterManagedObject(this, this);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite::ScriptDynamicSprite() {
|
||||
slot = 0;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
48
engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
Normal file
48
engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptDynamicSprite final : AGSCCDynamicObject {
|
||||
int slot;
|
||||
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
ScriptDynamicSprite(int slot);
|
||||
ScriptDynamicSprite();
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
66
engines/ags/engine/ac/dynobj/script_file.cpp
Normal file
66
engines/ags/engine/ac/dynobj/script_file.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_file.h"
|
||||
#include "ags/engine/ac/global_file.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// CHECKME: actually NULLs here will be equal to kFile_Open & kFile_Read
|
||||
const Shared::FileOpenMode sc_File::fopenModes[] =
|
||||
{ Shared::kFile_Open/*CHECKME, was undefined*/, Shared::kFile_Open, Shared::kFile_CreateAlways, Shared::kFile_Create };
|
||||
const Shared::FileWorkMode sc_File::fworkModes[] =
|
||||
{ Shared::kFile_Read/*CHECKME, was undefined*/, Shared::kFile_Read, Shared::kFile_Write, Shared::kFile_Write };
|
||||
|
||||
int sc_File::Dispose(void *address, bool force) {
|
||||
Close();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *sc_File::GetType() {
|
||||
return "File";
|
||||
}
|
||||
|
||||
int sc_File::Serialize(void *address, uint8_t *buffer, int bufsize) {
|
||||
// we cannot serialize an open file, so it will get closed
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc_File::OpenFile(const char *filename, int mode) {
|
||||
handle = FileOpen(filename, fopenModes[mode], fworkModes[mode]);
|
||||
if (handle <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sc_File::Close() {
|
||||
if (handle > 0) {
|
||||
FileClose(handle);
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sc_File::sc_File() {
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
56
engines/ags/engine/ac/dynobj/script_file.h
Normal file
56
engines/ags/engine/ac/dynobj/script_file.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/util/file.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
#define scFileRead 1
|
||||
#define scFileWrite 2
|
||||
#define scFileAppend 3
|
||||
|
||||
struct sc_File final : CCBasicObject {
|
||||
int32_t handle;
|
||||
|
||||
static const Shared::FileOpenMode fopenModes[];
|
||||
static const Shared::FileWorkMode fworkModes[];
|
||||
|
||||
int Dispose(void *address, bool force) override;
|
||||
|
||||
const char *GetType() override;
|
||||
|
||||
int Serialize(void *address, uint8_t *buffer, int bufsize) override;
|
||||
|
||||
int OpenFile(const char *filename, int mode);
|
||||
void Close();
|
||||
|
||||
sc_File();
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
442
engines/ags/engine/ac/dynobj/script_game.cpp
Normal file
442
engines/ags/engine/ac/dynobj/script_game.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/ac/dynobj/script_game.h"
|
||||
#include "ags/engine/ac/game.h"
|
||||
#include "ags/engine/ac/game_state.h"
|
||||
#include "ags/shared/ac/game_setup_struct.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/script/cc_common.h" // cc_error
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int32_t CCScriptGame::ReadInt32(void *address, intptr_t offset) {
|
||||
const int index = offset / sizeof(int32_t);
|
||||
if (index >= 5 && index < 5 + MAXGLOBALVARS)
|
||||
return _GP(play).globalvars[index - 5];
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
return _GP(play).score;
|
||||
case 1:
|
||||
return _GP(play).usedmode;
|
||||
case 2:
|
||||
return _GP(play).disabled_user_interface;
|
||||
case 3:
|
||||
return _GP(play).gscript_timer;
|
||||
case 4:
|
||||
return _GP(play).debug_mode;
|
||||
// 5 -> 54: _GP(play).globalvars
|
||||
case 55:
|
||||
return _GP(play).messagetime;
|
||||
case 56:
|
||||
return _GP(play).usedinv;
|
||||
case 57:
|
||||
return _GP(play).inv_top;
|
||||
case 58:
|
||||
return _GP(play).inv_numdisp;
|
||||
case 59:
|
||||
return _GP(play).inv_numorder;
|
||||
case 60:
|
||||
return _GP(play).inv_numinline;
|
||||
case 61:
|
||||
return _GP(play).text_speed;
|
||||
case 62:
|
||||
return _GP(play).sierra_inv_color;
|
||||
case 63:
|
||||
return _GP(play).talkanim_speed;
|
||||
case 64:
|
||||
return _GP(play).inv_item_wid;
|
||||
case 65:
|
||||
return _GP(play).inv_item_hit;
|
||||
case 66:
|
||||
return _GP(play).speech_text_shadow;
|
||||
case 67:
|
||||
return _GP(play).swap_portrait_side;
|
||||
case 68:
|
||||
return _GP(play).speech_textwindow_gui;
|
||||
case 69:
|
||||
return _GP(play).follow_change_room_timer;
|
||||
case 70:
|
||||
return _GP(play).totalscore;
|
||||
case 71:
|
||||
return _GP(play).skip_display;
|
||||
case 72:
|
||||
return _GP(play).no_multiloop_repeat;
|
||||
case 73:
|
||||
return _GP(play).roomscript_finished;
|
||||
case 74:
|
||||
return _GP(play).used_inv_on;
|
||||
case 75:
|
||||
return _GP(play).no_textbg_when_voice;
|
||||
case 76:
|
||||
return _GP(play).max_dialogoption_width;
|
||||
case 77:
|
||||
return _GP(play).no_hicolor_fadein;
|
||||
case 78:
|
||||
return _GP(play).bgspeech_game_speed;
|
||||
case 79:
|
||||
return _GP(play).bgspeech_stay_on_display;
|
||||
case 80:
|
||||
return _GP(play).unfactor_speech_from_textlength;
|
||||
case 81:
|
||||
return _GP(play).mp3_loop_before_end;
|
||||
case 82:
|
||||
return _GP(play).speech_music_drop;
|
||||
case 83:
|
||||
return _GP(play).in_cutscene;
|
||||
case 84:
|
||||
return _GP(play).fast_forward;
|
||||
case 85:
|
||||
return _GP(play).room_width;
|
||||
case 86:
|
||||
return _GP(play).room_height;
|
||||
case 87:
|
||||
return _GP(play).game_speed_modifier;
|
||||
case 88:
|
||||
return _GP(play).score_sound;
|
||||
case 89:
|
||||
return _GP(play).takeover_data;
|
||||
case 90:
|
||||
return 0; // _GP(play).replay_hotkey
|
||||
case 91:
|
||||
return _GP(play).dialog_options_x;
|
||||
case 92:
|
||||
return _GP(play).dialog_options_y;
|
||||
case 93:
|
||||
return _GP(play).narrator_speech;
|
||||
case 94:
|
||||
return _GP(play).ambient_sounds_persist;
|
||||
case 95:
|
||||
return _GP(play).lipsync_speed;
|
||||
case 96:
|
||||
return _GP(play).close_mouth_speech_time;
|
||||
case 97:
|
||||
return _GP(play).disable_antialiasing;
|
||||
case 98:
|
||||
return _GP(play).text_speed_modifier;
|
||||
case 99:
|
||||
return _GP(play).text_align;
|
||||
case 100:
|
||||
return _GP(play).speech_bubble_width;
|
||||
case 101:
|
||||
return _GP(play).min_dialogoption_width;
|
||||
case 102:
|
||||
return _GP(play).disable_dialog_parser;
|
||||
case 103:
|
||||
return _GP(play).anim_background_speed;
|
||||
case 104:
|
||||
return _GP(play).top_bar_backcolor;
|
||||
case 105:
|
||||
return _GP(play).top_bar_textcolor;
|
||||
case 106:
|
||||
return _GP(play).top_bar_bordercolor;
|
||||
case 107:
|
||||
return _GP(play).top_bar_borderwidth;
|
||||
case 108:
|
||||
return _GP(play).top_bar_ypos;
|
||||
case 109:
|
||||
return _GP(play).screenshot_width;
|
||||
case 110:
|
||||
return _GP(play).screenshot_height;
|
||||
case 111:
|
||||
return _GP(play).top_bar_font;
|
||||
case 112:
|
||||
return _GP(play).speech_text_align;
|
||||
case 113:
|
||||
return _GP(play).auto_use_walkto_points;
|
||||
case 114:
|
||||
return _GP(play).inventory_greys_out;
|
||||
case 115:
|
||||
return _GP(play).skip_speech_specific_key;
|
||||
case 116:
|
||||
return _GP(play).abort_key;
|
||||
case 117:
|
||||
return _GP(play).fade_to_red;
|
||||
case 118:
|
||||
return _GP(play).fade_to_green;
|
||||
case 119:
|
||||
return _GP(play).fade_to_blue;
|
||||
case 120:
|
||||
return _GP(play).show_single_dialog_option;
|
||||
case 121:
|
||||
return _GP(play).keep_screen_during_instant_transition;
|
||||
case 122:
|
||||
return _GP(play).read_dialog_option_colour;
|
||||
case 123:
|
||||
return _GP(play).stop_dialog_at_end;
|
||||
case 124:
|
||||
return _GP(play).speech_portrait_placement;
|
||||
case 125:
|
||||
return _GP(play).speech_portrait_x;
|
||||
case 126:
|
||||
return _GP(play).speech_portrait_y;
|
||||
case 127:
|
||||
return _GP(play).speech_display_post_time_ms;
|
||||
case 128:
|
||||
return _GP(play).dialog_options_highlight_color;
|
||||
default:
|
||||
cc_error("ScriptGame: unsupported variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCScriptGame::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
const int index = offset / sizeof(int32_t);
|
||||
if (index >= 5 && index < 5 + MAXGLOBALVARS) {
|
||||
_GP(play).globalvars[index - 5] = val;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
_GP(play).score = val;
|
||||
break;
|
||||
case 1:
|
||||
_GP(play).usedmode = val;
|
||||
break;
|
||||
case 2:
|
||||
_GP(play).disabled_user_interface = val;
|
||||
break;
|
||||
case 3:
|
||||
_GP(play).gscript_timer = val;
|
||||
break;
|
||||
case 4:
|
||||
set_debug_mode(val != 0);
|
||||
break; // _GP(play).debug_mode
|
||||
// 5 -> 54: _GP(play).globalvars
|
||||
case 55:
|
||||
_GP(play).messagetime = val;
|
||||
break;
|
||||
case 56:
|
||||
_GP(play).usedinv = val;
|
||||
break;
|
||||
case 57:
|
||||
_GP(play).inv_top = val;
|
||||
GUI::MarkInventoryForUpdate(_GP(game).playercharacter, true);
|
||||
break;
|
||||
case 58: // play.inv_numdisp
|
||||
case 59: // play.inv_numorder
|
||||
case 60: // play.inv_numinline
|
||||
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
|
||||
break;
|
||||
case 61:
|
||||
_GP(play).text_speed = val;
|
||||
break;
|
||||
case 62:
|
||||
_GP(play).sierra_inv_color = val;
|
||||
break;
|
||||
case 63:
|
||||
_GP(play).talkanim_speed = val;
|
||||
break;
|
||||
case 64:
|
||||
_GP(play).inv_item_wid = val;
|
||||
break;
|
||||
case 65:
|
||||
_GP(play).inv_item_hit = val;
|
||||
break;
|
||||
case 66:
|
||||
_GP(play).speech_text_shadow = val;
|
||||
break;
|
||||
case 67:
|
||||
_GP(play).swap_portrait_side = val;
|
||||
break;
|
||||
case 68:
|
||||
_GP(play).speech_textwindow_gui = val;
|
||||
break;
|
||||
case 69:
|
||||
_GP(play).follow_change_room_timer = val;
|
||||
break;
|
||||
case 70:
|
||||
_GP(play).totalscore = val;
|
||||
break;
|
||||
case 71:
|
||||
_GP(play).skip_display = val;
|
||||
break;
|
||||
case 72:
|
||||
_GP(play).no_multiloop_repeat = val;
|
||||
break;
|
||||
case 73:
|
||||
_GP(play).roomscript_finished = val;
|
||||
break;
|
||||
case 74:
|
||||
_GP(play).used_inv_on = val;
|
||||
break;
|
||||
case 75:
|
||||
_GP(play).no_textbg_when_voice = val;
|
||||
break;
|
||||
case 76:
|
||||
_GP(play).max_dialogoption_width = val;
|
||||
break;
|
||||
case 77:
|
||||
_GP(play).no_hicolor_fadein = val;
|
||||
break;
|
||||
case 78:
|
||||
_GP(play).bgspeech_game_speed = val;
|
||||
break;
|
||||
case 79:
|
||||
_GP(play).bgspeech_stay_on_display = val;
|
||||
break;
|
||||
case 80:
|
||||
_GP(play).unfactor_speech_from_textlength = val;
|
||||
break;
|
||||
case 81:
|
||||
_GP(play).mp3_loop_before_end = val;
|
||||
break;
|
||||
case 82:
|
||||
_GP(play).speech_music_drop = val;
|
||||
break;
|
||||
case 83: // _GP(play).in_cutscene
|
||||
case 84: // _GP(play).fast_forward;
|
||||
case 85: // _GP(play).room_width;
|
||||
case 86: // _GP(play).room_height;
|
||||
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
|
||||
break;
|
||||
case 87:
|
||||
_GP(play).game_speed_modifier = val;
|
||||
break;
|
||||
case 88:
|
||||
_GP(play).score_sound = val;
|
||||
break;
|
||||
case 89:
|
||||
_GP(play).takeover_data = val;
|
||||
break;
|
||||
case 90:
|
||||
break; // _GP(play).replay_hotkey
|
||||
case 91:
|
||||
_GP(play).dialog_options_x = val;
|
||||
break;
|
||||
case 92:
|
||||
_GP(play).dialog_options_y = val;
|
||||
break;
|
||||
case 93:
|
||||
_GP(play).narrator_speech = val;
|
||||
break;
|
||||
case 94:
|
||||
_GP(play).ambient_sounds_persist = val;
|
||||
break;
|
||||
case 95:
|
||||
_GP(play).lipsync_speed = val;
|
||||
break;
|
||||
case 96:
|
||||
_GP(play).close_mouth_speech_time = val;
|
||||
break;
|
||||
case 97:
|
||||
_GP(play).disable_antialiasing = val;
|
||||
break;
|
||||
case 98:
|
||||
_GP(play).text_speed_modifier = val;
|
||||
break;
|
||||
case 99:
|
||||
_GP(play).text_align = ReadScriptAlignment(val);
|
||||
break;
|
||||
case 100:
|
||||
_GP(play).speech_bubble_width = val;
|
||||
break;
|
||||
case 101:
|
||||
_GP(play).min_dialogoption_width = val;
|
||||
break;
|
||||
case 102:
|
||||
_GP(play).disable_dialog_parser = val;
|
||||
break;
|
||||
case 103:
|
||||
_GP(play).anim_background_speed = val;
|
||||
break;
|
||||
case 104:
|
||||
_GP(play).top_bar_backcolor = val;
|
||||
break;
|
||||
case 105:
|
||||
_GP(play).top_bar_textcolor = val;
|
||||
break;
|
||||
case 106:
|
||||
_GP(play).top_bar_bordercolor = val;
|
||||
break;
|
||||
case 107:
|
||||
_GP(play).top_bar_borderwidth = val;
|
||||
break;
|
||||
case 108:
|
||||
_GP(play).top_bar_ypos = val;
|
||||
break;
|
||||
case 109:
|
||||
_GP(play).screenshot_width = val;
|
||||
break;
|
||||
case 110:
|
||||
_GP(play).screenshot_height = val;
|
||||
break;
|
||||
case 111:
|
||||
_GP(play).top_bar_font = val;
|
||||
break;
|
||||
case 112:
|
||||
_GP(play).speech_text_align = ReadScriptAlignment(val);
|
||||
break;
|
||||
case 113:
|
||||
_GP(play).auto_use_walkto_points = val;
|
||||
break;
|
||||
case 114:
|
||||
_GP(play).inventory_greys_out = val;
|
||||
break;
|
||||
case 115:
|
||||
_GP(play).skip_speech_specific_key = val;
|
||||
break;
|
||||
case 116:
|
||||
_GP(play).abort_key = val;
|
||||
break;
|
||||
case 117: // _GP(play).fade_to_red;
|
||||
case 118: // _GP(play).fade_to_green;
|
||||
case 119: // _GP(play).fade_to_blue;
|
||||
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
|
||||
break;
|
||||
case 120:
|
||||
_GP(play).show_single_dialog_option = val;
|
||||
break;
|
||||
case 121:
|
||||
_GP(play).keep_screen_during_instant_transition = val;
|
||||
break;
|
||||
case 122:
|
||||
_GP(play).read_dialog_option_colour = val;
|
||||
break;
|
||||
case 123:
|
||||
_GP(play).stop_dialog_at_end = val;
|
||||
break;
|
||||
case 124:
|
||||
_GP(play).speech_portrait_placement = val;
|
||||
break;
|
||||
case 125:
|
||||
_GP(play).speech_portrait_x = val;
|
||||
break;
|
||||
case 126:
|
||||
_GP(play).speech_portrait_y = val;
|
||||
break;
|
||||
case 127:
|
||||
_GP(play).speech_display_post_time_ms = val;
|
||||
break;
|
||||
case 128:
|
||||
_GP(play).dialog_options_highlight_color = val;
|
||||
break;
|
||||
default:
|
||||
cc_error("ScriptGame: unsupported variable offset %d", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
42
engines/ags/engine/ac/dynobj/script_game.h
Normal file
42
engines/ags/engine/ac/dynobj/script_game.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Wrapper around script "GameState" struct, managing access to its variables.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_AGS_SCRIPT_GAME_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_AGS_SCRIPT_GAME_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct CCScriptGame : public AGSCCStaticObject {
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
35
engines/ags/engine/ac/dynobj/script_gui.h
Normal file
35
engines/ags/engine/ac/dynobj/script_gui.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// 64 bit: This struct must be 8 byte long
|
||||
struct ScriptGUI {
|
||||
int id;
|
||||
int __padding;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
34
engines/ags/engine/ac/dynobj/script_hotspot.h
Normal file
34
engines/ags/engine/ac/dynobj/script_hotspot.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptHotspot {
|
||||
int id = 0;
|
||||
int reserved = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
34
engines/ags/engine/ac/dynobj/script_inv_item.h
Normal file
34
engines/ags/engine/ac/dynobj/script_inv_item.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptInvItem {
|
||||
int id = 0;
|
||||
int reserved = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
52
engines/ags/engine/ac/dynobj/script_mouse.cpp
Normal file
52
engines/ags/engine/ac/dynobj/script_mouse.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/ac/dynobj/script_mouse.h"
|
||||
#include "ags/shared/script/cc_common.h" // cc_error
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int32_t ScriptMouse::ReadInt32(void *address, intptr_t offset) {
|
||||
switch (offset) {
|
||||
case 0:
|
||||
return x;
|
||||
case 4:
|
||||
return y;
|
||||
default:
|
||||
cc_error("ScriptMouse: unsupported variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptMouse::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
switch (offset) {
|
||||
case 0:
|
||||
case 4:
|
||||
debug_script_warn("ScriptMouse: attempt to write in readonly variable at offset %d, value", offset, val);
|
||||
break;
|
||||
default:
|
||||
cc_error("ScriptMouse: unsupported variable offset %d", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
44
engines/ags/engine/ac/dynobj/script_mouse.h
Normal file
44
engines/ags/engine/ac/dynobj/script_mouse.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Wrapper around script "Mouse" struct, managing access to its variables.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptMouse : public AGSCCStaticObject {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
37
engines/ags/engine/ac/dynobj/script_object.h
Normal file
37
engines/ags/engine/ac/dynobj/script_object.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
|
||||
#define AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
|
||||
|
||||
#include "ags/engine/ac/room_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// WARNING: struct size must be 8 byte for old scripts to work
|
||||
struct ScriptObject {
|
||||
int id = -1;
|
||||
int __padding = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
90
engines/ags/engine/ac/dynobj/script_overlay.cpp
Normal file
90
engines/ags/engine/ac/dynobj/script_overlay.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_overlay.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/engine/ac/overlay.h"
|
||||
#include "ags/engine/ac/runtime_defines.h"
|
||||
#include "ags/engine/ac/screen_overlay.h"
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
int ScriptOverlay::Dispose(void * /*address*/, bool force) {
|
||||
// since the managed object is being deleted, remove the
|
||||
// reference so it doesn't try and dispose something else
|
||||
// with that handle later
|
||||
if (overlayId >= 0) {
|
||||
auto *over = get_overlay(overlayId);
|
||||
if (over) {
|
||||
over->associatedOverlayHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is being removed voluntarily (ie. pointer out of
|
||||
// scope) then remove the associateed overlay
|
||||
// Otherwise, it's a Restore Game or something so don't
|
||||
if ((!force) && (Overlay_GetValid(this))) {
|
||||
Remove();
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptOverlay::GetType() {
|
||||
return "Overlay";
|
||||
}
|
||||
|
||||
size_t ScriptOverlay::CalcSerializeSize(const void * /*address*/) {
|
||||
return sizeof(int32_t) * 4;
|
||||
}
|
||||
|
||||
void ScriptOverlay::Serialize(const void * /*address*/, Stream *out) {
|
||||
out->WriteInt32(overlayId);
|
||||
out->WriteInt32(0); // unused (was text window x padding)
|
||||
out->WriteInt32(0); // unused (was text window y padding)
|
||||
out->WriteInt32(0); // unused (was internal ref flag)
|
||||
}
|
||||
|
||||
void ScriptOverlay::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
overlayId = in->ReadInt32();
|
||||
in->ReadInt32(); // unused (was text window x padding)
|
||||
in->ReadInt32(); // unused (was text window y padding)
|
||||
in->ReadInt32(); // unused (was internal ref flag)
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
void ScriptOverlay::Remove() {
|
||||
if (overlayId < 0) {
|
||||
debug_script_warn("Overlay.Remove: overlay is invalid, could have been removed earlier.");
|
||||
return;
|
||||
}
|
||||
remove_screen_overlay(overlayId);
|
||||
overlayId = -1;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
47
engines/ags/engine/ac/dynobj/script_overlay.h
Normal file
47
engines/ags/engine/ac/dynobj/script_overlay.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_OVERLAY_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_OVERLAY_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptOverlay final : AGSCCDynamicObject {
|
||||
int overlayId = -1;
|
||||
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
void Remove();
|
||||
ScriptOverlay() = default;
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
34
engines/ags/engine/ac/dynobj/script_region.h
Normal file
34
engines/ags/engine/ac/dynobj/script_region.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
|
||||
#define AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptRegion {
|
||||
int id = 0;
|
||||
int reserved = 0;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
55
engines/ags/engine/ac/dynobj/script_set.cpp
Normal file
55
engines/ags/engine/ac/dynobj/script_set.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_set.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int ScriptSetBase::Dispose(void * /*address*/, bool force) {
|
||||
Clear();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptSetBase::GetType() {
|
||||
return "StringSet";
|
||||
}
|
||||
|
||||
size_t ScriptSetBase::CalcSerializeSize(const void * /*address*/) {
|
||||
return CalcContainerSize();
|
||||
}
|
||||
|
||||
void ScriptSetBase::Serialize(const void * /*address*/, Stream *out) {
|
||||
out->WriteInt32(IsSorted());
|
||||
out->WriteInt32(IsCaseSensitive());
|
||||
SerializeContainer(out);
|
||||
}
|
||||
|
||||
void ScriptSetBase::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
// NOTE: we expect sorted/case flags are read by external reader;
|
||||
// this is awkward, but I did not find better design solution atm
|
||||
UnserializeContainer(in);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
159
engines/ags/engine/ac/dynobj/script_set.h
Normal file
159
engines/ags/engine/ac/dynobj/script_set.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Managed script object wrapping std::set<String> and unordered_set<String>.
|
||||
//
|
||||
// TODO: support wrapping non-owned Set, passed by the reference, -
|
||||
// that would let expose internal engine's sets using same interface.
|
||||
// TODO: maybe optimize key lookup operations further by not creating a String
|
||||
// object from const char*. It seems, C++14 standard allows to use convertible
|
||||
// types as keys; need to research what performance impact that would make.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTSET_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTSET_H
|
||||
|
||||
#include "common/std/set.h"
|
||||
#include "common/std/unordered_set.h"
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
#include "ags/shared/util/string_types.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
class ScriptSetBase : public AGSCCDynamicObject {
|
||||
public:
|
||||
int Dispose(void *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
virtual bool IsCaseSensitive() const = 0;
|
||||
virtual bool IsSorted() const = 0;
|
||||
|
||||
virtual bool Add(const char *item) = 0;
|
||||
virtual void Clear() = 0;
|
||||
virtual bool Contains(const char *item) const = 0;
|
||||
virtual bool Remove(const char *item) = 0;
|
||||
virtual int GetItemCount() const = 0;
|
||||
virtual void GetItems(std::vector<const char *> &buf) const = 0;
|
||||
|
||||
protected:
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
virtual size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
|
||||
private:
|
||||
virtual size_t CalcContainerSize() = 0;
|
||||
virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
|
||||
virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
|
||||
};
|
||||
|
||||
template <typename TSet, bool is_sorted, bool is_casesensitive>
|
||||
class ScriptSetImpl final : public ScriptSetBase {
|
||||
public:
|
||||
typedef typename TSet::const_iterator ConstIterator;
|
||||
|
||||
ScriptSetImpl() {}
|
||||
|
||||
bool IsCaseSensitive() const override {
|
||||
return is_casesensitive;
|
||||
}
|
||||
bool IsSorted() const override {
|
||||
return is_sorted;
|
||||
}
|
||||
|
||||
bool Add(const char *item) override {
|
||||
if (!item) return false;
|
||||
return TryAddItem(String(item));
|
||||
}
|
||||
void Clear() override {
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it)
|
||||
DeleteItem(it);
|
||||
_set.clear();
|
||||
}
|
||||
bool Contains(const char *item) const override {
|
||||
return _set.count(String::Wrapper(item)) != 0;
|
||||
}
|
||||
bool Remove(const char *item) override {
|
||||
auto it = _set.find(String::Wrapper(item));
|
||||
if (it == _set.end()) return false;
|
||||
DeleteItem(it);
|
||||
_set.erase(it);
|
||||
return true;
|
||||
}
|
||||
int GetItemCount() const override {
|
||||
return _set.size();
|
||||
}
|
||||
void GetItems(std::vector<const char *> &buf) const override {
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it)
|
||||
buf.push_back(it->GetCStr());
|
||||
}
|
||||
|
||||
private:
|
||||
bool TryAddItem(const String &s) {
|
||||
return _set.insert(s)._value;
|
||||
}
|
||||
void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
|
||||
|
||||
size_t CalcContainerSize() override {
|
||||
// 2 class properties + item count
|
||||
size_t total_sz = sizeof(int32_t) * 3;
|
||||
// (int32 + string buffer) per item
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it)
|
||||
total_sz += sizeof(int32_t) + it->GetLength();
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
void SerializeContainer(AGS::Shared::Stream *out) override {
|
||||
out->WriteInt32((int)_set.size());
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it) {
|
||||
out->WriteInt32((int)it->GetLength());
|
||||
out->Write(it->GetCStr(), it->GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
void UnserializeContainer(AGS::Shared::Stream *in) override {
|
||||
size_t item_count = in->ReadInt32();
|
||||
for (size_t i = 0; i < item_count; ++i) {
|
||||
size_t len = in->ReadInt32();
|
||||
String item = String::FromStreamCount(in, len);
|
||||
TryAddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
TSet _set;
|
||||
};
|
||||
|
||||
typedef ScriptSetImpl< std::set<String>, true, true > ScriptSet;
|
||||
typedef ScriptSetImpl< std::set<String, IgnoreCase_LessThan>, true, false > ScriptSetCI;
|
||||
typedef ScriptSetImpl< std::unordered_set<String>, false, true > ScriptHashSet;
|
||||
typedef ScriptSetImpl< std::unordered_set<String, IgnoreCase_Hash, IgnoreCase_EqualTo>, false, false > ScriptHashSetCI;
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
79
engines/ags/engine/ac/dynobj/script_string.cpp
Normal file
79
engines/ags/engine/ac/dynobj/script_string.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/ac/dynobj/script_string.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/engine/ac/string.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const char *ScriptString::GetType() {
|
||||
return "String";
|
||||
}
|
||||
|
||||
int ScriptString::Dispose(void *address, bool /*force*/) {
|
||||
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t ScriptString::CalcSerializeSize(const void *address) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
return hdr.Length + 1 + FileHeaderSz;
|
||||
}
|
||||
|
||||
void ScriptString::Serialize(const void *address, Stream *out) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
out->WriteInt32(hdr.Length);
|
||||
out->Write(address, hdr.Length + 1); // it was writing trailing 0 for some reason
|
||||
}
|
||||
|
||||
void ScriptString::Unserialize(int index, Stream *in, size_t /*data_sz*/) {
|
||||
size_t len = in->ReadInt32();
|
||||
uint8_t *buf = new uint8_t[len + 1 + MemHeaderSz];
|
||||
Header &hdr = reinterpret_cast<Header &>(*buf);
|
||||
hdr.Length = len;
|
||||
char *text_ptr = reinterpret_cast<char *>(buf + MemHeaderSz);
|
||||
in->Read(text_ptr, len + 1); // it was writing trailing 0 for some reason
|
||||
text_ptr[len] = 0; // for safety
|
||||
ccRegisterUnserializedObject(index, text_ptr, this);
|
||||
}
|
||||
|
||||
DynObjectRef ScriptString::CreateImpl(const char *text, size_t buf_len) {
|
||||
size_t len = text ? strlen(text) : buf_len;
|
||||
uint8_t *buf = new uint8_t[len + 1 + MemHeaderSz];
|
||||
Header &hdr = reinterpret_cast<Header &>(*buf);
|
||||
hdr.Length = len;
|
||||
char *text_ptr = reinterpret_cast<char *>(buf + MemHeaderSz);
|
||||
if (text)
|
||||
memcpy(text_ptr, text, len + 1);
|
||||
int32_t handle = ccRegisterManagedObject(text_ptr, &_GP(myScriptStringImpl));
|
||||
if (handle == 0) {
|
||||
delete[] buf;
|
||||
return DynObjectRef();
|
||||
}
|
||||
return DynObjectRef(handle, text_ptr, &_GP(myScriptStringImpl));
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
68
engines/ags/engine/ac/dynobj/script_string.h
Normal file
68
engines/ags/engine/ac/dynobj/script_string.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_STRING_H
|
||||
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_STRING_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptString final : AGSCCDynamicObject {
|
||||
public:
|
||||
struct Header {
|
||||
uint32_t Length = 0u;
|
||||
};
|
||||
|
||||
ScriptString() = default;
|
||||
~ScriptString() = default;
|
||||
|
||||
inline static const Header &GetHeader(const void *address) {
|
||||
return reinterpret_cast<const Header &>(*(static_cast<const uint8_t *>(address) - MemHeaderSz));
|
||||
}
|
||||
|
||||
// Create a new script string by copying the given text
|
||||
static DynObjectRef Create(const char *text) { return CreateImpl(text, 0); }
|
||||
// Create a new script string with a buffer of at least the given text length
|
||||
static DynObjectRef Create(size_t buf_len) { return CreateImpl(nullptr, buf_len); }
|
||||
|
||||
const char *GetType() override;
|
||||
int Dispose(void *address, bool force) override;
|
||||
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
|
||||
|
||||
private:
|
||||
// The size of the array's header in memory, prepended to the element data
|
||||
static const size_t MemHeaderSz = sizeof(Header);
|
||||
// The size of the serialized header
|
||||
static const size_t FileHeaderSz = sizeof(uint32_t);
|
||||
|
||||
static DynObjectRef CreateImpl(const char *text, size_t buf_len);
|
||||
|
||||
// Savegame serialization
|
||||
// Calculate and return required space for serialization, in bytes
|
||||
size_t CalcSerializeSize(const void *address) override;
|
||||
// Write object data into the provided stream
|
||||
void Serialize(const void *address, AGS::Shared::Stream *out) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
74
engines/ags/engine/ac/dynobj/script_system.cpp
Normal file
74
engines/ags/engine/ac/dynobj/script_system.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/engine/debugging/debug_log.h"
|
||||
#include "ags/engine/ac/dynobj/script_system.h"
|
||||
#include "ags/shared/script/cc_common.h" // cc_error
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
int32_t ScriptSystem::ReadInt32(void *address, intptr_t offset) {
|
||||
const int index = offset / sizeof(int32_t);
|
||||
switch (index) {
|
||||
case 0:
|
||||
return width;
|
||||
case 1:
|
||||
return height;
|
||||
case 2:
|
||||
return coldepth;
|
||||
case 3:
|
||||
return os;
|
||||
case 4:
|
||||
return windowed;
|
||||
case 5:
|
||||
return vsync;
|
||||
case 6:
|
||||
return viewport_width;
|
||||
case 7:
|
||||
return viewport_height;
|
||||
default:
|
||||
cc_error("ScriptSystem: unsupported variable offset %d", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptSystem::WriteInt32(void *address, intptr_t offset, int32_t val) {
|
||||
const int index = offset / sizeof(int32_t);
|
||||
switch (index) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
debug_script_warn("ScriptSystem: attempt to write in readonly variable at offset %d, value %d", offset, val);
|
||||
break;
|
||||
case 5:
|
||||
vsync = val;
|
||||
break;
|
||||
default:
|
||||
cc_error("ScriptSystem: unsupported variable offset %d", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
55
engines/ags/engine/ac/dynobj/script_system.h
Normal file
55
engines/ags/engine/ac/dynobj/script_system.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Wrapper around script "System" struct, managing access to its variables.
|
||||
// ScriptSystem is a readable/writeable struct which had been exposed to
|
||||
// script in older versions of API (deprecated).
|
||||
// WARNING: it *MUST* keep its size exact to avoid breaking address offsets
|
||||
// when running old scripts. In case of emergency you may use its reserved
|
||||
// fields, but it's not recommended to do, as this struct is not a part of
|
||||
// the modern API anymore.
|
||||
|
||||
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
|
||||
#define AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
|
||||
|
||||
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct ScriptSystem : AGSCCStaticObject {
|
||||
int width = 0; // game screen width
|
||||
int height = 0; // game screen height
|
||||
int coldepth = 0; // game's color depth, in bits per pixel (8, 16, 32)
|
||||
int os = 0; // operating system's code (see eScriptSystemOSID)
|
||||
int windowed = 0; // windowed/fullscreen flag
|
||||
int vsync = 0; // vertical sync flag
|
||||
int viewport_width = 0; // game viewport width (normal or letterboxed)
|
||||
int viewport_height = 0; // game viewport height (normal or letterboxed)
|
||||
char aci_version[10]{}; // engine version string (informational)
|
||||
int reserved[5]{}; // reserved fields
|
||||
|
||||
int32_t ReadInt32(void *address, intptr_t offset) override;
|
||||
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
|
||||
};
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
85
engines/ags/engine/ac/dynobj/script_user_object.cpp
Normal file
85
engines/ags/engine/ac/dynobj/script_user_object.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/memory.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/engine/ac/dynobj/script_user_object.h"
|
||||
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
const char *ScriptUserObject::TypeName = "UserObject";
|
||||
|
||||
// return the type name of the object
|
||||
const char *ScriptUserObject::GetType() {
|
||||
return TypeName;
|
||||
}
|
||||
|
||||
/* static */ DynObjectRef ScriptUserObject::Create(size_t size) {
|
||||
uint8_t *new_data = new uint8_t[size + MemHeaderSz];
|
||||
memset(new_data, 0, size + MemHeaderSz);
|
||||
Header &hdr = reinterpret_cast<Header &>(*new_data);
|
||||
hdr.Size = size;
|
||||
void *obj_ptr = &new_data[MemHeaderSz];
|
||||
int32_t handle = ccRegisterManagedObject(obj_ptr, &_G(globalDynamicStruct));
|
||||
if (handle == 0) {
|
||||
delete[] new_data;
|
||||
return DynObjectRef();
|
||||
}
|
||||
return DynObjectRef(handle, obj_ptr, &_G(globalDynamicStruct));
|
||||
}
|
||||
|
||||
int ScriptUserObject::Dispose(void *address, bool /*force*/) {
|
||||
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t ScriptUserObject::CalcSerializeSize(const void *address) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
return hdr.Size + FileHeaderSz;
|
||||
}
|
||||
|
||||
void ScriptUserObject::Serialize(const void *address, AGS::Shared::Stream *out) {
|
||||
const Header &hdr = GetHeader(address);
|
||||
// NOTE: we only write the data, no header at the moment
|
||||
out->Write(address, hdr.Size);
|
||||
}
|
||||
|
||||
void ScriptUserObject::Unserialize(int index, Stream *in, size_t data_sz) {
|
||||
uint8_t *new_data = new uint8_t[(data_sz - FileHeaderSz) + MemHeaderSz];
|
||||
Header &hdr = reinterpret_cast<Header &>(*new_data);
|
||||
hdr.Size = data_sz - FileHeaderSz;
|
||||
in->Read(new_data + MemHeaderSz, data_sz - FileHeaderSz);
|
||||
ccRegisterUnserializedObject(index, &new_data[MemHeaderSz], this);
|
||||
}
|
||||
|
||||
// Allocates managed struct containing two ints: X and Y
|
||||
ScriptUserObject *ScriptStructHelpers::CreatePoint(int x, int y) {
|
||||
DynObjectRef ref = ScriptUserObject::Create(sizeof(int32_t) * 2);
|
||||
ref.Mgr->WriteInt32(ref.Obj, 0, x);
|
||||
ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t), y);
|
||||
return static_cast<ScriptUserObject *>(ref.Obj);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user