AGS: Initial addition of engine/ and shared/ folders
This commit is contained in:
parent
df58db6659
commit
a60d290a08
642 changed files with 123412 additions and 0 deletions
67
engines/ags/engine/ac/asset_helper.h
Normal file
67
engines/ags/engine/ac/asset_helper.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// Functions related to finding and opening game assets.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__ASSETHELPER_H
|
||||
#define __AGS_EE_AC__ASSETHELPER_H
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "util/string.h"
|
||||
|
||||
namespace AGS { namespace Common {class Stream;}}
|
||||
using AGS::Common::Stream;
|
||||
using AGS::Common::String;
|
||||
|
||||
// Looks for valid asset library everywhere and returns path, or empty string if failed
|
||||
String find_assetlib(const String &filename);
|
||||
// Looks up for known valid asset library and returns path, or empty string if failed
|
||||
String get_known_assetlib(const String &filename);
|
||||
// Looks for asset everywhere and returns opened stream, or NULL if failed
|
||||
Stream *find_open_asset(const String &filename);
|
||||
|
||||
extern "C" {
|
||||
struct PACKFILE; // Allegro 4's own stream type
|
||||
struct DUMBFILE; // DUMB stream type
|
||||
}
|
||||
|
||||
// AssetPath combines asset library and item names
|
||||
// TODO: implement support for registering multiple libraries at once for
|
||||
// the AssetManager, then we could remove assetlib parameter.
|
||||
typedef std::pair<String, String> AssetPath;
|
||||
|
||||
// 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, size_t &asset_size);
|
||||
// Creates DUMBFILE stream from AGS asset. Used for creating DUMB objects
|
||||
DUMBFILE *DUMBfileFromAsset(const AssetPath &path, size_t &asset_size);
|
||||
bool DoesAssetExistInLib(const AssetPath &assetname);
|
||||
|
||||
#endif // __AGS_EE_AC__ASSETHELPER_H
|
353
engines/ags/engine/ac/audiochannel.cpp
Normal file
353
engines/ags/engine/ac/audiochannel.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/audiochannel.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "ac/global_audio.h"
|
||||
#include "ac/dynobj/cc_audioclip.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "game/roomstruct.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "media/audio/audio_system.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
extern GameState play;
|
||||
extern RoomStruct thisroom;
|
||||
extern CCAudioClip ccDynamicAudioClip;
|
||||
|
||||
int AudioChannel_GetID(ScriptAudioChannel *channel)
|
||||
{
|
||||
return channel->id;
|
||||
}
|
||||
|
||||
int AudioChannel_GetIsPlaying(ScriptAudioChannel *channel)
|
||||
{
|
||||
if (play.fast_forward)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return channel_is_playing(channel->id) ? 1 : 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPanning(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
return ch->panningAsPercentage;
|
||||
}
|
||||
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);
|
||||
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
ch->set_panning(((newPanning + 100) * 255) / 200);
|
||||
ch->panningAsPercentage = newPanning;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptAudioClip* AudioChannel_GetPlayingClip(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
return (ScriptAudioClip*)ch->sourceClip;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPosition(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
if (play.fast_forward)
|
||||
return 999999999;
|
||||
|
||||
return ch->get_pos();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetPositionMs(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
if (play.fast_forward)
|
||||
return 999999999;
|
||||
|
||||
return ch->get_pos_ms();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetLengthMs(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
return ch->get_length_ms();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetVolume(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
return ch->get_volume();
|
||||
}
|
||||
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);
|
||||
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
ch->set_volume_percent(newVolume);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioChannel_GetSpeed(ScriptAudioChannel *channel)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
return ch->get_speed();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioChannel_SetSpeed(ScriptAudioChannel *channel, int new_speed)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
ch->set_speed(new_speed);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioChannel_Stop(ScriptAudioChannel *channel)
|
||||
{
|
||||
if (channel->id == SCHAN_SPEECH && play.IsNonBlockingVoiceSpeech())
|
||||
stop_voice_nonblocking();
|
||||
else
|
||||
stop_or_fade_out_channel(channel->id, -1, nullptr);
|
||||
}
|
||||
|
||||
void AudioChannel_Seek(ScriptAudioChannel *channel, int newPosition)
|
||||
{
|
||||
if (newPosition < 0)
|
||||
quitprintf("!AudioChannel.Seek: invalid seek position %d", newPosition);
|
||||
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
ch->seek(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioChannel_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
auto* ch = lock.GetChannelIfPlaying(channel->id);
|
||||
|
||||
if (ch)
|
||||
{
|
||||
int maxDist = ((xPos > thisroom.Width / 2) ? xPos : (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
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
// 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, 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void RegisterAudioChannelAPI()
|
||||
{
|
||||
ccAddExternalObjectFunction("AudioChannel::Seek^1", Sc_AudioChannel_Seek);
|
||||
ccAddExternalObjectFunction("AudioChannel::SetRoomLocation^2", Sc_AudioChannel_SetRoomLocation);
|
||||
ccAddExternalObjectFunction("AudioChannel::Stop^0", Sc_AudioChannel_Stop);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_ID", Sc_AudioChannel_GetID);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_IsPlaying", Sc_AudioChannel_GetIsPlaying);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_LengthMs", Sc_AudioChannel_GetLengthMs);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_Panning", Sc_AudioChannel_GetPanning);
|
||||
ccAddExternalObjectFunction("AudioChannel::set_Panning", Sc_AudioChannel_SetPanning);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_PlayingClip", Sc_AudioChannel_GetPlayingClip);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_Position", Sc_AudioChannel_GetPosition);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_PositionMs", Sc_AudioChannel_GetPositionMs);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_Volume", Sc_AudioChannel_GetVolume);
|
||||
ccAddExternalObjectFunction("AudioChannel::set_Volume", Sc_AudioChannel_SetVolume);
|
||||
ccAddExternalObjectFunction("AudioChannel::get_Speed", Sc_AudioChannel_GetSpeed);
|
||||
ccAddExternalObjectFunction("AudioChannel::set_Speed", Sc_AudioChannel_SetSpeed);
|
||||
// For compatibility with Ahmet Kamil's (aka Gord10) custom engine
|
||||
ccAddExternalObjectFunction("AudioChannel::SetSpeed^1", Sc_AudioChannel_SetSpeed);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::Seek^1", (void*)AudioChannel_Seek);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::SetRoomLocation^2", (void*)AudioChannel_SetRoomLocation);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::Stop^0", (void*)AudioChannel_Stop);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_ID", (void*)AudioChannel_GetID);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_IsPlaying", (void*)AudioChannel_GetIsPlaying);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_LengthMs", (void*)AudioChannel_GetLengthMs);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_Panning", (void*)AudioChannel_GetPanning);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::set_Panning", (void*)AudioChannel_SetPanning);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_PlayingClip", (void*)AudioChannel_GetPlayingClip);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_Position", (void*)AudioChannel_GetPosition);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_PositionMs", (void*)AudioChannel_GetPositionMs);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::get_Volume", (void*)AudioChannel_GetVolume);
|
||||
ccAddExternalFunctionForPlugin("AudioChannel::set_Volume", (void*)AudioChannel_SetVolume);
|
||||
}
|
38
engines/ags/engine/ac/audiochannel.h
Normal file
38
engines/ags/engine/ac/audiochannel.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__AUDIOCHANNEL_H
|
||||
#define __AGS_EE_AC__AUDIOCHANNEL_H
|
||||
|
||||
#include "ac/dynobj/scriptaudioclip.h"
|
||||
#include "ac/dynobj/scriptaudiochannel.h"
|
||||
|
||||
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_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos);
|
||||
|
||||
#endif // __AGS_EE_AC__AUDIOCHANNEL_H
|
154
engines/ags/engine/ac/audioclip.cpp
Normal file
154
engines/ags/engine/ac/audioclip.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/asset_helper.h"
|
||||
#include "ac/audioclip.h"
|
||||
#include "ac/audiochannel.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "ac/dynobj/cc_audiochannel.h"
|
||||
#include "media/audio/audio_system.h"
|
||||
|
||||
extern GameSetupStruct game;
|
||||
extern ScriptAudioChannel scrAudioChannel[MAX_SOUND_CHANNELS + 1];
|
||||
extern CCAudioChannel ccDynamicAudio;
|
||||
|
||||
int AudioClip_GetID(ScriptAudioClip *clip)
|
||||
{
|
||||
return clip->id;
|
||||
}
|
||||
|
||||
int AudioClip_GetFileType(ScriptAudioClip *clip)
|
||||
{
|
||||
return clip->fileType;
|
||||
}
|
||||
|
||||
int AudioClip_GetType(ScriptAudioClip *clip)
|
||||
{
|
||||
return clip->type;
|
||||
}
|
||||
int AudioClip_GetIsAvailable(ScriptAudioClip *clip)
|
||||
{
|
||||
return DoesAssetExistInLib(get_audio_clip_assetpath(clip->bundlingType, clip->fileName)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void AudioClip_Stop(ScriptAudioClip *clip)
|
||||
{
|
||||
AudioChannelsLock lock;
|
||||
for (int i = 0; i < MAX_SOUND_CHANNELS; i++)
|
||||
{
|
||||
auto* ch = lock.GetChannelIfPlaying(i);
|
||||
if ((ch != nullptr) && (ch->sourceClip == clip))
|
||||
{
|
||||
AudioChannel_Stop(&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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
RuntimeScriptValue Sc_AudioClip_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetID);
|
||||
}
|
||||
|
||||
// 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, 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, 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, ccDynamicAudio, AudioClip_PlayQueued);
|
||||
}
|
||||
|
||||
void RegisterAudioClipAPI()
|
||||
{
|
||||
ccAddExternalObjectFunction("AudioClip::Play^2", Sc_AudioClip_Play);
|
||||
ccAddExternalObjectFunction("AudioClip::PlayFrom^3", Sc_AudioClip_PlayFrom);
|
||||
ccAddExternalObjectFunction("AudioClip::PlayQueued^2", Sc_AudioClip_PlayQueued);
|
||||
ccAddExternalObjectFunction("AudioClip::Stop^0", Sc_AudioClip_Stop);
|
||||
ccAddExternalObjectFunction("AudioClip::get_ID", Sc_AudioClip_GetID);
|
||||
ccAddExternalObjectFunction("AudioClip::get_FileType", Sc_AudioClip_GetFileType);
|
||||
ccAddExternalObjectFunction("AudioClip::get_IsAvailable", Sc_AudioClip_GetIsAvailable);
|
||||
ccAddExternalObjectFunction("AudioClip::get_Type", Sc_AudioClip_GetType);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("AudioClip::Play^2", (void*)AudioClip_Play);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::PlayFrom^3", (void*)AudioClip_PlayFrom);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::PlayQueued^2", (void*)AudioClip_PlayQueued);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::Stop^0", (void*)AudioClip_Stop);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::get_FileType", (void*)AudioClip_GetFileType);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::get_IsAvailable", (void*)AudioClip_GetIsAvailable);
|
||||
ccAddExternalFunctionForPlugin("AudioClip::get_Type", (void*)AudioClip_GetType);
|
||||
}
|
32
engines/ags/engine/ac/audioclip.h
Normal file
32
engines/ags/engine/ac/audioclip.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__AUDIOCLIP_H
|
||||
#define __AGS_EE_AC__AUDIOCLIP_H
|
||||
|
||||
#include "ac/dynobj/scriptaudioclip.h"
|
||||
#include "ac/dynobj/scriptaudiochannel.h"
|
||||
|
||||
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);
|
||||
|
||||
#endif // __AGS_EE_AC__AUDIOCLIP_H
|
501
engines/ags/engine/ac/button.cpp
Normal file
501
engines/ags/engine/ac/button.cpp
Normal file
|
@ -0,0 +1,501 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/button.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/gui.h"
|
||||
#include "ac/view.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/global_translation.h"
|
||||
#include "ac/string.h"
|
||||
#include "ac/viewframe.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "gui/animatingguibutton.h"
|
||||
#include "gui/guimain.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
extern GameSetupStruct game;
|
||||
extern ViewStruct*views;
|
||||
|
||||
// *** BUTTON FUNCTIONS
|
||||
|
||||
AnimatingGUIButton animbuts[MAX_ANIMATING_BUTTONS];
|
||||
int numAnimButs;
|
||||
|
||||
void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat) {
|
||||
int guin = butt->ParentId;
|
||||
int objn = butt->Id;
|
||||
|
||||
if ((view < 1) || (view > game.numviews))
|
||||
quit("!AnimateButton: invalid view specified");
|
||||
view--;
|
||||
|
||||
if ((loop < 0) || (loop >= views[view].numLoops))
|
||||
quit("!AnimateButton: invalid loop specified for view");
|
||||
|
||||
// if it's already animating, stop it
|
||||
FindAndRemoveButtonAnimation(guin, objn);
|
||||
|
||||
if (numAnimButs >= MAX_ANIMATING_BUTTONS)
|
||||
quit("!AnimateButton: too many animating GUI buttons at once");
|
||||
|
||||
int buttonId = guis[guin].GetControlID(objn);
|
||||
|
||||
guibuts[buttonId].PushedImage = 0;
|
||||
guibuts[buttonId].MouseOverImage = 0;
|
||||
|
||||
animbuts[numAnimButs].ongui = guin;
|
||||
animbuts[numAnimButs].onguibut = objn;
|
||||
animbuts[numAnimButs].buttonid = buttonId;
|
||||
animbuts[numAnimButs].view = view;
|
||||
animbuts[numAnimButs].loop = loop;
|
||||
animbuts[numAnimButs].speed = speed;
|
||||
animbuts[numAnimButs].repeat = repeat;
|
||||
animbuts[numAnimButs].frame = -1;
|
||||
animbuts[numAnimButs].wait = 0;
|
||||
numAnimButs++;
|
||||
// launch into the first frame
|
||||
if (UpdateAnimatingButton(numAnimButs - 1))
|
||||
{
|
||||
debug_script_warn("AnimateButton: no frames to animate");
|
||||
StopButtonAnimation(numAnimButs - 1);
|
||||
}
|
||||
}
|
||||
|
||||
const char* Button_GetText_New(GUIButton *butt) {
|
||||
return CreateNewScriptString(butt->GetText());
|
||||
}
|
||||
|
||||
void Button_GetText(GUIButton *butt, char *buffer) {
|
||||
strcpy(buffer, butt->GetText());
|
||||
}
|
||||
|
||||
void Button_SetText(GUIButton *butt, const char *newtx) {
|
||||
newtx = get_translation(newtx);
|
||||
|
||||
if (strcmp(butt->GetText(), newtx)) {
|
||||
guis_need_update = 1;
|
||||
butt->SetText(newtx);
|
||||
}
|
||||
}
|
||||
|
||||
void Button_SetFont(GUIButton *butt, int newFont) {
|
||||
if ((newFont < 0) || (newFont >= game.numfonts))
|
||||
quit("!Button.Font: invalid font number.");
|
||||
|
||||
if (butt->Font != newFont) {
|
||||
butt->Font = newFont;
|
||||
guis_need_update = 1;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
guis_need_update = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Button_GetGraphic(GUIButton *butt) {
|
||||
// return currently displayed pic
|
||||
if (butt->CurrentImage < 0)
|
||||
return butt->Image;
|
||||
return butt->CurrentImage;
|
||||
}
|
||||
|
||||
int Button_GetMouseOverGraphic(GUIButton *butt) {
|
||||
return butt->MouseOverImage;
|
||||
}
|
||||
|
||||
void Button_SetMouseOverGraphic(GUIButton *guil, int slotn) {
|
||||
debug_script_log("GUI %d Button %d mouseover set to slot %d", guil->ParentId, guil->Id, slotn);
|
||||
|
||||
if ((guil->IsMouseOver != 0) && (guil->IsPushed == 0))
|
||||
guil->CurrentImage = slotn;
|
||||
guil->MouseOverImage = slotn;
|
||||
|
||||
guis_need_update = 1;
|
||||
FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
|
||||
}
|
||||
|
||||
int Button_GetNormalGraphic(GUIButton *butt) {
|
||||
return butt->Image;
|
||||
}
|
||||
|
||||
void Button_SetNormalGraphic(GUIButton *guil, int slotn) {
|
||||
debug_script_log("GUI %d Button %d normal set to slot %d", guil->ParentId, guil->Id, slotn);
|
||||
// normal pic - update if mouse is not over, or if there's no MouseOverImage
|
||||
if (((guil->IsMouseOver == 0) || (guil->MouseOverImage < 1)) && (guil->IsPushed == 0))
|
||||
guil->CurrentImage = slotn;
|
||||
guil->Image = slotn;
|
||||
// update the clickable area to the same size as the graphic
|
||||
guil->Width = game.SpriteInfos[slotn].Width;
|
||||
guil->Height = game.SpriteInfos[slotn].Height;
|
||||
|
||||
guis_need_update = 1;
|
||||
FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
|
||||
}
|
||||
|
||||
int Button_GetPushedGraphic(GUIButton *butt) {
|
||||
return butt->PushedImage;
|
||||
}
|
||||
|
||||
void Button_SetPushedGraphic(GUIButton *guil, int slotn) {
|
||||
debug_script_log("GUI %d Button %d pushed set to slot %d", guil->ParentId, guil->Id, slotn);
|
||||
|
||||
if (guil->IsPushed)
|
||||
guil->CurrentImage = slotn;
|
||||
guil->PushedImage = slotn;
|
||||
|
||||
guis_need_update = 1;
|
||||
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;
|
||||
guis_need_update = 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern AnimatingGUIButton animbuts[MAX_ANIMATING_BUTTONS];
|
||||
extern int numAnimButs;
|
||||
|
||||
// ** start animating buttons code
|
||||
|
||||
// returns 1 if animation finished
|
||||
int UpdateAnimatingButton(int bu) {
|
||||
if (animbuts[bu].wait > 0) {
|
||||
animbuts[bu].wait--;
|
||||
return 0;
|
||||
}
|
||||
ViewStruct *tview = &views[animbuts[bu].view];
|
||||
|
||||
animbuts[bu].frame++;
|
||||
|
||||
if (animbuts[bu].frame >= tview->loops[animbuts[bu].loop].numFrames)
|
||||
{
|
||||
if (tview->loops[animbuts[bu].loop].RunNextLoop()) {
|
||||
// go to next loop
|
||||
animbuts[bu].loop++;
|
||||
animbuts[bu].frame = 0;
|
||||
}
|
||||
else if (animbuts[bu].repeat) {
|
||||
animbuts[bu].frame = 0;
|
||||
// multi-loop anim, go back
|
||||
while ((animbuts[bu].loop > 0) &&
|
||||
(tview->loops[animbuts[bu].loop - 1].RunNextLoop()))
|
||||
animbuts[bu].loop--;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
CheckViewFrame(animbuts[bu].view, animbuts[bu].loop, animbuts[bu].frame);
|
||||
|
||||
// update the button's image
|
||||
guibuts[animbuts[bu].buttonid].Image = tview->loops[animbuts[bu].loop].frames[animbuts[bu].frame].pic;
|
||||
guibuts[animbuts[bu].buttonid].CurrentImage = guibuts[animbuts[bu].buttonid].Image;
|
||||
guibuts[animbuts[bu].buttonid].PushedImage = 0;
|
||||
guibuts[animbuts[bu].buttonid].MouseOverImage = 0;
|
||||
guis_need_update = 1;
|
||||
|
||||
animbuts[bu].wait = animbuts[bu].speed + tview->loops[animbuts[bu].loop].frames[animbuts[bu].frame].speed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StopButtonAnimation(int idxn) {
|
||||
numAnimButs--;
|
||||
for (int aa = idxn; aa < numAnimButs; aa++) {
|
||||
animbuts[aa] = animbuts[aa + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the index of the AnimatingGUIButton object corresponding to the
|
||||
// given button ID; returns -1 if no such animation exists
|
||||
int FindAnimatedButton(int guin, int objn)
|
||||
{
|
||||
for (int i = 0; i < numAnimButs; ++i)
|
||||
{
|
||||
if (animbuts[i].ongui == guin && animbuts[i].onguibut == objn)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FindAndRemoveButtonAnimation(int guin, int objn)
|
||||
{
|
||||
int idx = FindAnimatedButton(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 FindAnimatedButton(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 = FindAnimatedButton(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? animbuts[idx].view + 1 : 0;
|
||||
}
|
||||
|
||||
int Button_GetAnimLoop(GUIButton *butt)
|
||||
{
|
||||
int idx = FindAnimatedButton(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? animbuts[idx].loop : 0;
|
||||
}
|
||||
|
||||
int Button_GetAnimFrame(GUIButton *butt)
|
||||
{
|
||||
int idx = FindAnimatedButton(butt->ParentId, butt->Id);
|
||||
return idx >= 0 ? 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;
|
||||
guis_need_update = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
#include "ac/dynobj/scriptstring.h"
|
||||
|
||||
extern ScriptString myScriptStringImpl;
|
||||
|
||||
// void | GUIButton *butt, int view, int loop, int speed, int repeat
|
||||
RuntimeScriptValue Sc_Button_Animate(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_VOID_PINT4(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, 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_GetAnimating(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_GetFrame(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimFrame);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetLoop(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimLoop);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_Button_GetView(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_INT(GUIButton, Button_GetAnimView);
|
||||
}
|
||||
|
||||
void RegisterButtonAPI()
|
||||
{
|
||||
ccAddExternalObjectFunction("Button::Animate^4", Sc_Button_Animate);
|
||||
ccAddExternalObjectFunction("Button::Click^1", Sc_Button_Click);
|
||||
ccAddExternalObjectFunction("Button::GetText^1", Sc_Button_GetText);
|
||||
ccAddExternalObjectFunction("Button::SetText^1", Sc_Button_SetText);
|
||||
ccAddExternalObjectFunction("Button::get_TextAlignment", Sc_Button_GetTextAlignment);
|
||||
ccAddExternalObjectFunction("Button::set_TextAlignment", Sc_Button_SetTextAlignment);
|
||||
ccAddExternalObjectFunction("Button::get_Animating", Sc_Button_GetAnimating);
|
||||
ccAddExternalObjectFunction("Button::get_ClipImage", Sc_Button_GetClipImage);
|
||||
ccAddExternalObjectFunction("Button::set_ClipImage", Sc_Button_SetClipImage);
|
||||
ccAddExternalObjectFunction("Button::get_Font", Sc_Button_GetFont);
|
||||
ccAddExternalObjectFunction("Button::set_Font", Sc_Button_SetFont);
|
||||
ccAddExternalObjectFunction("Button::get_Frame", Sc_Button_GetFrame);
|
||||
ccAddExternalObjectFunction("Button::get_Graphic", Sc_Button_GetGraphic);
|
||||
ccAddExternalObjectFunction("Button::get_Loop", Sc_Button_GetLoop);
|
||||
ccAddExternalObjectFunction("Button::get_MouseOverGraphic", Sc_Button_GetMouseOverGraphic);
|
||||
ccAddExternalObjectFunction("Button::set_MouseOverGraphic", Sc_Button_SetMouseOverGraphic);
|
||||
ccAddExternalObjectFunction("Button::get_NormalGraphic", Sc_Button_GetNormalGraphic);
|
||||
ccAddExternalObjectFunction("Button::set_NormalGraphic", Sc_Button_SetNormalGraphic);
|
||||
ccAddExternalObjectFunction("Button::get_PushedGraphic", Sc_Button_GetPushedGraphic);
|
||||
ccAddExternalObjectFunction("Button::set_PushedGraphic", Sc_Button_SetPushedGraphic);
|
||||
ccAddExternalObjectFunction("Button::get_Text", Sc_Button_GetText_New);
|
||||
ccAddExternalObjectFunction("Button::set_Text", Sc_Button_SetText);
|
||||
ccAddExternalObjectFunction("Button::get_TextColor", Sc_Button_GetTextColor);
|
||||
ccAddExternalObjectFunction("Button::set_TextColor", Sc_Button_SetTextColor);
|
||||
ccAddExternalObjectFunction("Button::get_View", Sc_Button_GetView);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("Button::Animate^4", (void*)Button_Animate);
|
||||
ccAddExternalFunctionForPlugin("Button::GetText^1", (void*)Button_GetText);
|
||||
ccAddExternalFunctionForPlugin("Button::SetText^1", (void*)Button_SetText);
|
||||
ccAddExternalFunctionForPlugin("Button::get_ClipImage", (void*)Button_GetClipImage);
|
||||
ccAddExternalFunctionForPlugin("Button::set_ClipImage", (void*)Button_SetClipImage);
|
||||
ccAddExternalFunctionForPlugin("Button::get_Font", (void*)Button_GetFont);
|
||||
ccAddExternalFunctionForPlugin("Button::set_Font", (void*)Button_SetFont);
|
||||
ccAddExternalFunctionForPlugin("Button::get_Graphic", (void*)Button_GetGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::get_MouseOverGraphic", (void*)Button_GetMouseOverGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::set_MouseOverGraphic", (void*)Button_SetMouseOverGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::get_NormalGraphic", (void*)Button_GetNormalGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::set_NormalGraphic", (void*)Button_SetNormalGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::get_PushedGraphic", (void*)Button_GetPushedGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::set_PushedGraphic", (void*)Button_SetPushedGraphic);
|
||||
ccAddExternalFunctionForPlugin("Button::get_Text", (void*)Button_GetText_New);
|
||||
ccAddExternalFunctionForPlugin("Button::set_Text", (void*)Button_SetText);
|
||||
ccAddExternalFunctionForPlugin("Button::get_TextColor", (void*)Button_GetTextColor);
|
||||
ccAddExternalFunctionForPlugin("Button::set_TextColor", (void*)Button_SetTextColor);
|
||||
}
|
47
engines/ags/engine/ac/button.h
Normal file
47
engines/ags/engine/ac/button.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__BUTTON_H
|
||||
#define __AGS_EE_AC__BUTTON_H
|
||||
|
||||
#include "gui/guibutton.h"
|
||||
|
||||
using AGS::Common::GUIButton;
|
||||
|
||||
void Button_Animate(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);
|
||||
|
||||
int UpdateAnimatingButton(int bu);
|
||||
void StopButtonAnimation(int idxn);
|
||||
void FindAndRemoveButtonAnimation(int guin, int objn);
|
||||
|
||||
#endif // __AGS_EE_AC__BUTTON_H
|
39
engines/ags/engine/ac/cdaudio.cpp
Normal file
39
engines/ags/engine/ac/cdaudio.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/cdaudio.h"
|
||||
#include "platform/base/agsplatformdriver.h"
|
||||
|
||||
int use_cdplayer=0;
|
||||
bool triedToUseCdAudioCommand = false;
|
||||
int need_to_stop_cd=0;
|
||||
|
||||
int init_cd_player()
|
||||
{
|
||||
use_cdplayer=0;
|
||||
return platform->InitializeCDPlayer();
|
||||
}
|
||||
|
||||
int cd_manager(int cmdd,int datt)
|
||||
{
|
||||
if (!triedToUseCdAudioCommand)
|
||||
{
|
||||
triedToUseCdAudioCommand = true;
|
||||
init_cd_player();
|
||||
}
|
||||
if (cmdd==0) return use_cdplayer;
|
||||
if (use_cdplayer==0) return 0; // ignore other commands
|
||||
|
||||
return platform->CDPlayerCommand(cmdd, datt);
|
||||
}
|
31
engines/ags/engine/ac/cdaudio.h
Normal file
31
engines/ags/engine/ac/cdaudio.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__CDAUDIO_H
|
||||
#define __AGS_EE_AC__CDAUDIO_H
|
||||
|
||||
// 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) ;
|
||||
|
||||
#endif // __AGS_EE_AC__CDAUDIO_H
|
4122
engines/ags/engine/ac/character.cpp
Normal file
4122
engines/ags/engine/ac/character.cpp
Normal file
File diff suppressed because it is too large
Load diff
219
engines/ags/engine/ac/character.h
Normal file
219
engines/ags/engine/ac/character.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__CHARACTER_H
|
||||
#define __AGS_EE_AC__CHARACTER_H
|
||||
|
||||
#include "ac/characterinfo.h"
|
||||
#include "ac/characterextras.h"
|
||||
#include "ac/dynobj/scriptobject.h"
|
||||
#include "ac/dynobj/scriptinvitem.h"
|
||||
#include "ac/dynobj/scriptoverlay.h"
|
||||
#include "game/viewport.h"
|
||||
#include "util/geometry.h"
|
||||
|
||||
// **** CHARACTER: FUNCTIONS ****
|
||||
|
||||
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);
|
||||
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_LockViewAlignedEx(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);
|
||||
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);
|
||||
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_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 Common { class Bitmap; } }
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
void animate_character(CharacterInfo *chap, int loopn,int sppd,int rept, int noidleoverride = 0, int direction = 0, int sframe = 0);
|
||||
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);
|
||||
int find_nearest_walkable_area_within(int *xx, int *yy, int range, int step);
|
||||
void find_nearest_walkable_area (int *xx, int *yy);
|
||||
void walk_character(int chac,int tox,int toy,int ignwal, bool autoWalkAnims);
|
||||
void FindReasonableLoopForCharacter(CharacterInfo *chap);
|
||||
void walk_or_move_character(CharacterInfo *chaa, int x, int y, int blocking, int direct, bool isWalk);
|
||||
int is_valid_character(int newchar);
|
||||
int wantMoveNow (CharacterInfo *chi, CharacterExtras *chex);
|
||||
void setup_player_character(int charid);
|
||||
void CheckViewFrameForCharacter(CharacterInfo *chi);
|
||||
Common::Bitmap *GetCharacterImage(int charid, int *isFlipped);
|
||||
CharacterInfo *GetCharacterAtScreen(int xx, int yy);
|
||||
// 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 has walked onto character ww
|
||||
int is_char_on_another (int sourceChar, int ww, int*fromxptr, int*cwidptr);
|
||||
int my_getpixel(Common::Bitmap *blk, int x, int y);
|
||||
// X and Y co-ordinates must be in 320x200 format
|
||||
int check_click_on_character(int xx,int yy,int mood);
|
||||
int is_pos_on_character(int xx,int yy);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
extern CharacterInfo*playerchar;
|
||||
extern CharacterExtras *charextra;
|
||||
extern MoveList *mls;
|
||||
extern int32_t _sc_PlayerCharPtr;
|
||||
|
||||
// order of loops to turn character in circle from down to down
|
||||
extern int turnlooporder[8];
|
||||
|
||||
#endif // __AGS_EE_AC__CHARACTER_H
|
35
engines/ags/engine/ac/charactercache.h
Normal file
35
engines/ags/engine/ac/charactercache.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__CHARACTERCACHE_H
|
||||
#define __AGS_EE_AC__CHARACTERCACHE_H
|
||||
|
||||
namespace AGS { namespace Common { class Bitmap; } }
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
// stores cached info about the character
|
||||
struct CharacterCache {
|
||||
Common::Bitmap *image;
|
||||
int sppic;
|
||||
int scaling;
|
||||
int inUse;
|
||||
short tintredwas, tintgrnwas, tintbluwas, tintamntwas;
|
||||
short lightlevwas, tintlightwas;
|
||||
// no mirroredWas is required, since the code inverts the sprite number
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_AC__CHARACTERCACHE_H
|
56
engines/ags/engine/ac/characterextras.cpp
Normal file
56
engines/ags/engine/ac/characterextras.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/characterextras.h"
|
||||
#include "util/stream.h"
|
||||
|
||||
using AGS::Common::Stream;
|
||||
|
||||
void CharacterExtras::ReadFromFile(Stream *in)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
void CharacterExtras::WriteToFile(Stream *out)
|
||||
{
|
||||
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);
|
||||
}
|
52
engines/ags/engine/ac/characterextras.h
Normal file
52
engines/ags/engine/ac/characterextras.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__CHARACTEREXTRAS_H
|
||||
#define __AGS_EE_AC__CHARACTEREXTRAS_H
|
||||
|
||||
#include "ac/runtime_defines.h"
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS { namespace Common { class Stream; } }
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
struct CharacterExtras {
|
||||
// UGLY UGLY UGLY!! The CharacterInfo struct size is fixed because it's
|
||||
// used in the scripts, therefore overflowing stuff has to go here
|
||||
short invorder[MAX_INVORDER];
|
||||
short invorder_count;
|
||||
// TODO: implement full AABB and keep updated, so that engine could rely on these cached values all time;
|
||||
// TODO: consider having both fixed AABB and volatile one that changes with animation frame (unless you change how anims work)
|
||||
short width;
|
||||
short height;
|
||||
short zoom;
|
||||
short xwas;
|
||||
short ywas;
|
||||
short tint_r;
|
||||
short tint_g;
|
||||
short tint_b;
|
||||
short tint_level;
|
||||
short tint_light;
|
||||
char process_idle_this_time;
|
||||
char slow_move_counter;
|
||||
short animwait;
|
||||
|
||||
void ReadFromFile(Common::Stream *in);
|
||||
void WriteToFile(Common::Stream *out);
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_AC__CHARACTEREXTRAS_H
|
508
engines/ags/engine/ac/characterinfo_engine.cpp
Normal file
508
engines/ags/engine/ac/characterinfo_engine.cpp
Normal file
|
@ -0,0 +1,508 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/characterinfo.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/character.h"
|
||||
#include "ac/characterextras.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "ac/global_character.h"
|
||||
#include "ac/math.h"
|
||||
#include "ac/viewframe.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "game/roomstruct.h"
|
||||
#include "main/maindefines_ex.h" // RETURN_CONTINUE
|
||||
#include "main/update.h"
|
||||
#include "media/audio/audio_system.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
extern ViewStruct*views;
|
||||
extern GameSetupStruct game;
|
||||
extern int displayed_room;
|
||||
extern GameState play;
|
||||
extern int char_speaking;
|
||||
extern RoomStruct thisroom;
|
||||
extern unsigned int loopcounter;
|
||||
|
||||
#define Random __Rand
|
||||
|
||||
int CharacterInfo::get_effective_y() {
|
||||
return y - z;
|
||||
}
|
||||
int CharacterInfo::get_baseline() {
|
||||
if (baseline < 1)
|
||||
return y;
|
||||
return baseline;
|
||||
}
|
||||
int CharacterInfo::get_blocking_top() {
|
||||
if (blocking_height > 0)
|
||||
return y - blocking_height / 2;
|
||||
return y - 2;
|
||||
}
|
||||
int CharacterInfo::get_blocking_bottom() {
|
||||
// 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::UpdateMoveAndAnim(int &char_index, CharacterExtras *chex, int &numSheep, int *followingAsSheep)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (on != 1) return;
|
||||
|
||||
// walking
|
||||
res = update_character_walking(chex);
|
||||
// [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
|
||||
}
|
||||
|
||||
// Make sure it doesn't flash up a blue cup
|
||||
if (view < 0) ;
|
||||
else if (loop >= views[view].numLoops)
|
||||
loop = 0;
|
||||
|
||||
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, numSheep, followingAsSheep, doing_nothing);
|
||||
|
||||
update_character_idle(chex, doing_nothing);
|
||||
|
||||
chex->process_idle_this_time = 0;
|
||||
}
|
||||
|
||||
void CharacterInfo::UpdateFollowingExactlyCharacter()
|
||||
{
|
||||
x = game.chars[following].x;
|
||||
y = game.chars[following].y;
|
||||
z = game.chars[following].z;
|
||||
room = game.chars[following].room;
|
||||
prevroom = game.chars[following].prevroom;
|
||||
|
||||
int usebase = game.chars[following].get_baseline();
|
||||
|
||||
if (flags & CHF_BEHINDSHEPHERD)
|
||||
baseline = usebase - 1;
|
||||
else
|
||||
baseline = usebase + 1;
|
||||
}
|
||||
|
||||
int CharacterInfo::update_character_walking(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] >= views[view].numLoops) ||
|
||||
(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 == 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++;
|
||||
}
|
||||
|
||||
if (loop >= views[view].numLoops)
|
||||
quitprintf("Unable to render character %d (%s) because loop %d does not exist in view %d", index_id, name, loop, view + 1);
|
||||
|
||||
// check don't overflow loop
|
||||
int framesInLoop = views[view].loops[loop].numFrames;
|
||||
if (frame > framesInLoop)
|
||||
{
|
||||
frame = 1;
|
||||
|
||||
if (framesInLoop < 2)
|
||||
frame = 0;
|
||||
|
||||
if (framesInLoop < 1)
|
||||
quitprintf("Unable to render character %d (%s) because there are no frames in loop %d", index_id, name, loop);
|
||||
}
|
||||
|
||||
if (walking<1) {
|
||||
chex->process_idle_this_time = 1;
|
||||
doing_nothing=1;
|
||||
walkwait=0;
|
||||
chex->animwait = 0;
|
||||
// use standing pic
|
||||
Character_StopMoving(this);
|
||||
frame = 0;
|
||||
CheckViewFrameForCharacter(this);
|
||||
}
|
||||
else if (chex->animwait > 0) chex->animwait--;
|
||||
else {
|
||||
if (flags & CHF_ANTIGLIDE)
|
||||
walkwaitcounter++;
|
||||
|
||||
if ((flags & CHF_MOVENOTWALK) == 0)
|
||||
{
|
||||
frame++;
|
||||
if (frame >= views[view].loops[loop].numFrames)
|
||||
{
|
||||
// end of loop, so loop back round skipping the standing frame
|
||||
frame = 1;
|
||||
|
||||
if (views[view].loops[loop].numFrames < 2)
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
chex->animwait = views[view].loops[loop].frames[frame].speed + animspeed;
|
||||
|
||||
if (flags & CHF_ANTIGLIDE)
|
||||
walkwait = chex->animwait;
|
||||
else
|
||||
walkwait = 0;
|
||||
|
||||
CheckViewFrameForCharacter(this);
|
||||
}
|
||||
}
|
||||
doing_nothing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CharacterInfo::update_character_animating(int &aa, int &doing_nothing)
|
||||
{
|
||||
// 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 == 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 ((char_speaking == aa) && (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 (play.speech_in_post_state ||
|
||||
((play.messagetime >= 0) && (play.messagetime < play.close_mouth_speech_time)))
|
||||
frame = 0;
|
||||
|
||||
if (frame != fraa) {
|
||||
frame = fraa;
|
||||
CheckViewFrameForCharacter(this);
|
||||
}
|
||||
|
||||
//continue;
|
||||
return RETURN_CONTINUE;
|
||||
}
|
||||
else {
|
||||
int oldframe = frame;
|
||||
if (animating & CHANIM_BACKWARDS) {
|
||||
frame--;
|
||||
if (frame < 0) {
|
||||
// if the previous loop is a Run Next Loop one, go back to it
|
||||
if ((loop > 0) &&
|
||||
(views[view].loops[loop - 1].RunNextLoop())) {
|
||||
|
||||
loop --;
|
||||
frame = views[view].loops[loop].numFrames - 1;
|
||||
}
|
||||
else if (animating & CHANIM_REPEAT) {
|
||||
|
||||
frame = views[view].loops[loop].numFrames - 1;
|
||||
|
||||
while (views[view].loops[loop].RunNextLoop()) {
|
||||
loop++;
|
||||
frame = views[view].loops[loop].numFrames - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame++;
|
||||
animating = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
frame++;
|
||||
|
||||
if ((aa == char_speaking) &&
|
||||
(play.speech_in_post_state ||
|
||||
((!play.speech_has_voice) &&
|
||||
(play.close_mouth_speech_time > 0) &&
|
||||
(play.messagetime < play.close_mouth_speech_time)))) {
|
||||
// finished talking - stop animation
|
||||
animating = 0;
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
if (frame >= views[view].loops[loop].numFrames) {
|
||||
|
||||
if (views[view].loops[loop].RunNextLoop())
|
||||
{
|
||||
if (loop+1 >= views[view].numLoops)
|
||||
quit("!Animating character tried to overrun last loop in view");
|
||||
loop++;
|
||||
frame=0;
|
||||
}
|
||||
else if ((animating & CHANIM_REPEAT)==0) {
|
||||
animating=0;
|
||||
frame--;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame=0;
|
||||
// if it's a multi-loop animation, go back to start
|
||||
if (play.no_multiloop_repeat == 0) {
|
||||
while ((loop > 0) &&
|
||||
(views[view].loops[loop - 1].RunNextLoop()))
|
||||
loop--;
|
||||
}
|
||||
}
|
||||
}
|
||||
wait = views[view].loops[loop].frames[frame].speed;
|
||||
// idle anim doesn't have speed stored cos animating==0
|
||||
if (idleleft < 0)
|
||||
wait += animspeed+5;
|
||||
else
|
||||
wait += (animating >> 8) & 0x00ff;
|
||||
|
||||
if (frame != oldframe)
|
||||
CheckViewFrameForCharacter(this);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CharacterInfo::update_character_follower(int &aa, int &numSheep, int *followingAsSheep, int &doing_nothing)
|
||||
{
|
||||
if ((following >= 0) && (followinfo == FOLLOW_ALWAYSONTOP)) {
|
||||
// an always-on-top follow
|
||||
if (numSheep >= MAX_SHEEP)
|
||||
quit("too many sheep");
|
||||
followingAsSheep[numSheep] = aa;
|
||||
numSheep++;
|
||||
}
|
||||
// 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 ((game.chars[following].on == 0) || (on == 0)) ;
|
||||
else if (room < 0) {
|
||||
room ++;
|
||||
if (room == 0) {
|
||||
// appear in the new room
|
||||
room = game.chars[following].room;
|
||||
x = play.entered_at_x;
|
||||
y = 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 != game.chars[following].room)
|
||||
&& (game.chars[following].on == 0))
|
||||
; // do nothing if the player isn't visible
|
||||
else if (room != game.chars[following].room) {
|
||||
prevroom = room;
|
||||
room = game.chars[following].room;
|
||||
|
||||
if (room == displayed_room) {
|
||||
// only move to the room-entered position if coming into
|
||||
// the current room
|
||||
if (play.entered_at_x > (thisroom.Width - 8)) {
|
||||
x = thisroom.Width+8;
|
||||
y = play.entered_at_y;
|
||||
}
|
||||
else if (play.entered_at_x < 8) {
|
||||
x = -8;
|
||||
y = play.entered_at_y;
|
||||
}
|
||||
else if (play.entered_at_y > (thisroom.Height - 8)) {
|
||||
y = thisroom.Height+8;
|
||||
x = play.entered_at_x;
|
||||
}
|
||||
else if (play.entered_at_y < thisroom.Edges.Top+8) {
|
||||
y = thisroom.Edges.Top+1;
|
||||
x = play.entered_at_x;
|
||||
}
|
||||
else {
|
||||
// not at one of the edges
|
||||
// delay for a few seconds to let the player move
|
||||
room = -play.follow_change_room_timer;
|
||||
}
|
||||
if (room >= 0) {
|
||||
walk_character(aa,play.entered_at_x,play.entered_at_y,1, true);
|
||||
doing_nothing = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (room != displayed_room) {
|
||||
// if the characetr is following another character and
|
||||
// neither is in the current room, don't try to move
|
||||
}
|
||||
else if ((abs(game.chars[following].x - x) > distaway+30) |
|
||||
(abs(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,game.chars[following].x + goxoffs,
|
||||
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 != 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 ((loopcounter%40==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 = 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 = rand() % maxLoops;
|
||||
// don't select a loop which is a continuation of a previous one
|
||||
} while ((useloop > 0) && (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,
|
||||
animspeed+5,(idletime == 0) ? 1 : 0, 1);
|
||||
|
||||
// don't set Animating while the idle anim plays
|
||||
animating = 0;
|
||||
}
|
||||
} // end do idle animation
|
||||
}
|
141
engines/ags/engine/ac/datetime.cpp
Normal file
141
engines/ags/engine/ac/datetime.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <time.h>
|
||||
#include "ac/datetime.h"
|
||||
#include "platform/base/agsplatformdriver.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
|
||||
ScriptDateTime* DateTime_Now_Core() {
|
||||
ScriptDateTime *sdt = new ScriptDateTime();
|
||||
|
||||
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
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
// 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()
|
||||
{
|
||||
ccAddExternalStaticFunction("DateTime::get_Now", Sc_DateTime_Now);
|
||||
ccAddExternalObjectFunction("DateTime::get_DayOfMonth", Sc_DateTime_GetDayOfMonth);
|
||||
ccAddExternalObjectFunction("DateTime::get_Hour", Sc_DateTime_GetHour);
|
||||
ccAddExternalObjectFunction("DateTime::get_Minute", Sc_DateTime_GetMinute);
|
||||
ccAddExternalObjectFunction("DateTime::get_Month", Sc_DateTime_GetMonth);
|
||||
ccAddExternalObjectFunction("DateTime::get_RawTime", Sc_DateTime_GetRawTime);
|
||||
ccAddExternalObjectFunction("DateTime::get_Second", Sc_DateTime_GetSecond);
|
||||
ccAddExternalObjectFunction("DateTime::get_Year", Sc_DateTime_GetYear);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Now", (void*)DateTime_Now);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_DayOfMonth", (void*)DateTime_GetDayOfMonth);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Hour", (void*)DateTime_GetHour);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Minute", (void*)DateTime_GetMinute);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Month", (void*)DateTime_GetMonth);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_RawTime", (void*)DateTime_GetRawTime);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Second", (void*)DateTime_GetSecond);
|
||||
ccAddExternalFunctionForPlugin("DateTime::get_Year", (void*)DateTime_GetYear);
|
||||
}
|
33
engines/ags/engine/ac/datetime.h
Normal file
33
engines/ags/engine/ac/datetime.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DATETIME_H
|
||||
#define __AGS_EE_AC__DATETIME_H
|
||||
|
||||
#include "ac/dynobj/scriptdatetime.h"
|
||||
|
||||
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);
|
||||
|
||||
#endif // __AGS_EE_AC__DATETIME_H
|
1324
engines/ags/engine/ac/dialog.cpp
Normal file
1324
engines/ags/engine/ac/dialog.cpp
Normal file
File diff suppressed because it is too large
Load diff
39
engines/ags/engine/ac/dialog.h
Normal file
39
engines/ags/engine/ac/dialog.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DIALOG_H
|
||||
#define __AGS_EE_AC__DIALOG_H
|
||||
|
||||
#include <vector>
|
||||
#include "ac/dynobj/scriptdialog.h"
|
||||
|
||||
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) ;
|
||||
|
||||
extern ScriptDialog *scrDialog;
|
||||
|
||||
#endif // __AGS_EE_AC__DIALOG_H
|
332
engines/ags/engine/ac/dialogoptionsrendering.cpp
Normal file
332
engines/ags/engine/ac/dialogoptionsrendering.cpp
Normal file
|
@ -0,0 +1,332 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dialog.h"
|
||||
#include "ac/dialogtopic.h"
|
||||
#include "ac/dialogoptionsrendering.h"
|
||||
#include "ac/gamestructdefines.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "ac/dynobj/cc_dialog.h"
|
||||
|
||||
extern DialogTopic *dialog;
|
||||
extern CCDialog ccDynamicDialog;
|
||||
|
||||
// ** 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 &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 = dialog[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
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
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, 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()
|
||||
{
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::Update^0", Sc_DialogOptionsRendering_Update);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::RunActiveOption^0", Sc_DialogOptionsRendering_RunActiveOption);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_ActiveOptionID", Sc_DialogOptionsRendering_GetActiveOptionID);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_ActiveOptionID", Sc_DialogOptionsRendering_SetActiveOptionID);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_DialogToRender", Sc_DialogOptionsRendering_GetDialogToRender);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_Height", Sc_DialogOptionsRendering_GetHeight);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_Height", Sc_DialogOptionsRendering_SetHeight);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_ParserTextBoxX", Sc_DialogOptionsRendering_GetParserTextboxX);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_ParserTextBoxX", Sc_DialogOptionsRendering_SetParserTextboxX);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_ParserTextBoxY", Sc_DialogOptionsRendering_GetParserTextboxY);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_ParserTextBoxY", Sc_DialogOptionsRendering_SetParserTextboxY);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_ParserTextBoxWidth", Sc_DialogOptionsRendering_GetParserTextboxWidth);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_ParserTextBoxWidth", Sc_DialogOptionsRendering_SetParserTextboxWidth);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_Surface", Sc_DialogOptionsRendering_GetSurface);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_Width", Sc_DialogOptionsRendering_GetWidth);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_Width", Sc_DialogOptionsRendering_SetWidth);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_X", Sc_DialogOptionsRendering_GetX);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_X", Sc_DialogOptionsRendering_SetX);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_Y", Sc_DialogOptionsRendering_GetY);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_Y", Sc_DialogOptionsRendering_SetY);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::get_HasAlphaChannel", Sc_DialogOptionsRendering_GetHasAlphaChannel);
|
||||
ccAddExternalObjectFunction("DialogOptionsRenderingInfo::set_HasAlphaChannel", Sc_DialogOptionsRendering_SetHasAlphaChannel);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_ActiveOptionID", (void*)DialogOptionsRendering_GetActiveOptionID);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_ActiveOptionID", (void*)DialogOptionsRendering_SetActiveOptionID);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_DialogToRender", (void*)DialogOptionsRendering_GetDialogToRender);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_Height", (void*)DialogOptionsRendering_GetHeight);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_Height", (void*)DialogOptionsRendering_SetHeight);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_ParserTextBoxX", (void*)DialogOptionsRendering_GetParserTextboxX);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_ParserTextBoxX", (void*)DialogOptionsRendering_SetParserTextboxX);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_ParserTextBoxY", (void*)DialogOptionsRendering_GetParserTextboxY);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_ParserTextBoxY", (void*)DialogOptionsRendering_SetParserTextboxY);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_ParserTextBoxWidth", (void*)DialogOptionsRendering_GetParserTextboxWidth);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_ParserTextBoxWidth", (void*)DialogOptionsRendering_SetParserTextboxWidth);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_Surface", (void*)DialogOptionsRendering_GetSurface);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_Width", (void*)DialogOptionsRendering_GetWidth);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_Width", (void*)DialogOptionsRendering_SetWidth);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_X", (void*)DialogOptionsRendering_GetX);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_X", (void*)DialogOptionsRendering_SetX);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::get_Y", (void*)DialogOptionsRendering_GetY);
|
||||
ccAddExternalFunctionForPlugin("DialogOptionsRenderingInfo::set_Y", (void*)DialogOptionsRendering_SetY);
|
||||
}
|
45
engines/ags/engine/ac/dialogoptionsrendering.h
Normal file
45
engines/ags/engine/ac/dialogoptionsrendering.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DIALOGOPTIONSRENDERING_H
|
||||
#define __AGS_EE_AC__DIALOGOPTIONSRENDERING_H
|
||||
|
||||
#include "ac/dynobj/scriptdialog.h"
|
||||
#include "ac/dynobj/scriptdialogoptionsrendering.h"
|
||||
|
||||
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);
|
||||
|
||||
#endif // __AGS_EE_AC__DIALOGOPTIONSRENDERING_H
|
832
engines/ags/engine/ac/display.cpp
Normal file
832
engines/ags/engine/ac/display.cpp
Normal file
|
@ -0,0 +1,832 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "ac/display.h"
|
||||
#include "ac/common.h"
|
||||
#include "font/agsfontrenderer.h"
|
||||
#include "font/fonts.h"
|
||||
#include "ac/character.h"
|
||||
#include "ac/draw.h"
|
||||
#include "ac/game.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "ac/global_audio.h"
|
||||
#include "ac/global_game.h"
|
||||
#include "ac/gui.h"
|
||||
#include "ac/mouse.h"
|
||||
#include "ac/overlay.h"
|
||||
#include "ac/sys_events.h"
|
||||
#include "ac/screenoverlay.h"
|
||||
#include "ac/speech.h"
|
||||
#include "ac/string.h"
|
||||
#include "ac/system.h"
|
||||
#include "ac/topbarsettings.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "gfx/blender.h"
|
||||
#include "gui/guibutton.h"
|
||||
#include "gui/guimain.h"
|
||||
#include "main/game_run.h"
|
||||
#include "platform/base/agsplatformdriver.h"
|
||||
#include "ac/spritecache.h"
|
||||
#include "gfx/gfx_util.h"
|
||||
#include "util/string_utils.h"
|
||||
#include "ac/mouse.h"
|
||||
#include "media/audio/audio_system.h"
|
||||
#include "ac/timer.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
using namespace AGS::Common::BitmapHelper;
|
||||
|
||||
extern GameState play;
|
||||
extern GameSetupStruct game;
|
||||
extern int longestline;
|
||||
extern AGSPlatformDriver *platform;
|
||||
extern int loops_per_character;
|
||||
extern SpriteCache spriteset;
|
||||
|
||||
int display_message_aschar=0;
|
||||
|
||||
|
||||
TopBarSettings topBar;
|
||||
struct DisplayVars
|
||||
{
|
||||
int lineheight; // font's height of single line
|
||||
int linespacing; // font's line spacing
|
||||
int fulltxtheight; // total height of all the text
|
||||
} disp;
|
||||
|
||||
// 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
|
||||
int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed)
|
||||
{
|
||||
const bool use_speech_textwindow = (asspch < 0) && (game.options[OPT_SPEECHTYPE] >= 2);
|
||||
const bool use_thought_gui = (isThought) && (game.options[OPT_THOUGHTGUI] > 0);
|
||||
|
||||
bool alphaChannel = false;
|
||||
char todis[STD_BUFFER_SIZE];
|
||||
snprintf(todis, STD_BUFFER_SIZE - 1, "%s", text);
|
||||
int usingGui = -1;
|
||||
if (use_speech_textwindow)
|
||||
usingGui = play.speech_textwindow_gui;
|
||||
else if (use_thought_gui)
|
||||
usingGui = game.options[OPT_THOUGHTGUI];
|
||||
|
||||
int padding = get_textwindow_padding(usingGui);
|
||||
int paddingScaled = get_fixed_pixel_size(padding);
|
||||
int paddingDoubledScaled = get_fixed_pixel_size(padding * 2); // Just in case screen size does is not neatly divisible by 320x200
|
||||
|
||||
ensure_text_valid_for_font(todis, usingfont);
|
||||
break_up_text_into_lines(todis, Lines, wii-2*padding, usingfont);
|
||||
disp.lineheight = getfontheight_outlined(usingfont);
|
||||
disp.linespacing= getfontspacing_outlined(usingfont);
|
||||
disp.fulltxtheight = getheightoflines(usingfont, Lines.Count());
|
||||
|
||||
// AGS 2.x: If the screen is faded out, fade in again when displaying a message box.
|
||||
if (!asspch && (loaded_game_file_version <= kGameVersion_272))
|
||||
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 ((play.skip_until_char_stops >= 0) && (disp_type == DISPLAYTEXT_MESSAGEBOX))
|
||||
render_graphics();
|
||||
|
||||
EndSkippingUntilCharStops();
|
||||
|
||||
if (topBar.wantIt) {
|
||||
// ensure that the window is wide enough to display
|
||||
// any top bar text
|
||||
int topBarWid = wgettextwidth_compensate(topBar.text, topBar.font);
|
||||
topBarWid += data_to_game_coord(play.top_bar_borderwidth + 2) * 2;
|
||||
if (longestline < topBarWid)
|
||||
longestline = topBarWid;
|
||||
// the top bar should behave like DisplaySpeech wrt blocking
|
||||
disp_type = DISPLAYTEXT_SPEECH;
|
||||
}
|
||||
|
||||
if (asspch > 0) {
|
||||
// update the all_buttons_disabled variable in advance
|
||||
// of the adjust_x/y_for_guis calls
|
||||
play.disabled_user_interface++;
|
||||
update_gui_disabled_status();
|
||||
play.disabled_user_interface--;
|
||||
}
|
||||
|
||||
const Rect &ui_view = 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 (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 = 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;
|
||||
|
||||
int extraHeight = paddingDoubledScaled;
|
||||
color_t text_color = MakeColor(15);
|
||||
if (disp_type < DISPLAYTEXT_NORMALOVERLAY)
|
||||
remove_screen_overlay(OVER_TEXTMSG); // remove any previous blocking texts
|
||||
|
||||
Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap((wii > 0) ? wii : 2, disp.fulltxtheight + extraHeight, game.GetColorDepth());
|
||||
|
||||
// inform draw_text_window to free the old bitmap
|
||||
const bool wantFreeScreenop = true;
|
||||
|
||||
//
|
||||
// Creating displayed graphic
|
||||
//
|
||||
// may later change if usingGUI, needed to avoid changing original coordinates
|
||||
int adjustedXX = xx;
|
||||
int 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 = guis[usingGui].HasAlphaChannel();
|
||||
}
|
||||
}
|
||||
else if ((ShouldAntiAliasText()) && (game.GetColorDepth() >= 24))
|
||||
alphaChannel = true;
|
||||
|
||||
for (size_t ee=0;ee<Lines.Count();ee++) {
|
||||
//int ttxp=wii/2 - wgettextwidth_compensate(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) &&
|
||||
((game.options[OPT_SPEECHTYPE] >= 2) || (isThought)))
|
||||
text_color = text_window_ds->GetCompatibleColor(guis[usingGui].FgColor);
|
||||
else
|
||||
text_color = text_window_ds->GetCompatibleColor(-asspch);
|
||||
|
||||
wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, Lines[ee], play.text_align);
|
||||
}
|
||||
else {
|
||||
text_color = text_window_ds->GetCompatibleColor(asspch);
|
||||
wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, Lines[ee], play.speech_text_align);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int xoffs,yoffs, oriwid = wii - padding * 2;
|
||||
draw_text_window_and_bar(&text_window_ds, wantFreeScreenop, &xoffs,&yoffs,&xx,&yy,&wii,&text_color);
|
||||
|
||||
if (game.options[OPT_TWCUSTOM] > 0)
|
||||
{
|
||||
alphaChannel = guis[game.options[OPT_TWCUSTOM]].HasAlphaChannel();
|
||||
}
|
||||
|
||||
adjust_y_coordinate_for_text(&yoffs, usingfont);
|
||||
|
||||
for (size_t ee=0;ee<Lines.Count();ee++)
|
||||
wouttext_aligned (text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, Lines[ee], play.text_align);
|
||||
}
|
||||
|
||||
int ovrtype = OVER_TEXTMSG;
|
||||
if (disp_type == DISPLAYTEXT_NORMALOVERLAY) ovrtype=OVER_CUSTOM;
|
||||
else if (disp_type >= OVER_CUSTOM) ovrtype = disp_type;
|
||||
|
||||
int nse = add_screen_overlay(xx, yy, ovrtype, text_window_ds, adjustedXX - xx, adjustedYY - yy, alphaChannel);
|
||||
// we should not delete text_window_ds here, because it is now owned by Overlay
|
||||
|
||||
if (disp_type >= DISPLAYTEXT_NORMALOVERLAY) {
|
||||
return screenover[nse].type;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for the blocking text to timeout or until skipped by another command
|
||||
//
|
||||
if (disp_type == DISPLAYTEXT_MESSAGEBOX) {
|
||||
// If fast-forwarding, then skip immediately
|
||||
if (play.fast_forward) {
|
||||
remove_screen_overlay(OVER_TEXTMSG);
|
||||
play.messagetime=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!play.mouse_cursor_hidden)
|
||||
ags_domouse(DOMOUSE_ENABLE);
|
||||
int countdown = GetTextDisplayTime (todis);
|
||||
int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)play.skip_display);
|
||||
// Loop until skipped
|
||||
while (true) {
|
||||
update_audio_system_on_game_loop();
|
||||
render_graphics();
|
||||
int mbut, mwheelz;
|
||||
if (run_service_mb_controls(mbut, mwheelz) && mbut >= 0) {
|
||||
check_skip_cutscene_mclick(mbut);
|
||||
if (play.fast_forward)
|
||||
break;
|
||||
if (skip_setting & SKIP_MOUSECLICK && !play.IsIgnoringInput())
|
||||
break;
|
||||
}
|
||||
int kp;
|
||||
if (run_service_key_controls(kp)) {
|
||||
check_skip_cutscene_keypress (kp);
|
||||
if (play.fast_forward)
|
||||
break;
|
||||
if ((skip_setting & SKIP_KEYPRESS) && !play.IsIgnoringInput())
|
||||
break;
|
||||
}
|
||||
|
||||
update_polled_stuff_if_runtime();
|
||||
|
||||
if (play.fast_forward == 0)
|
||||
{
|
||||
WaitForNextFrame();
|
||||
}
|
||||
|
||||
countdown--;
|
||||
|
||||
// Special behavior when coupled with a voice-over
|
||||
if (play.speech_has_voice) {
|
||||
// extend life of text if the voice hasn't finished yet
|
||||
if (channel_is_playing(SCHAN_SPEECH) && (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))
|
||||
{
|
||||
play.SetIgnoreInput(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) && (play.fast_forward))
|
||||
break;
|
||||
}
|
||||
if (!play.mouse_cursor_hidden)
|
||||
ags_domouse(DOMOUSE_DISABLE);
|
||||
remove_screen_overlay(OVER_TEXTMSG);
|
||||
invalidate_screen();
|
||||
}
|
||||
else {
|
||||
// if the speech does not time out, but we are skipping a cutscene,
|
||||
// allow it to time out
|
||||
if ((play.messagetime < 0) && (play.fast_forward))
|
||||
play.messagetime = 2;
|
||||
|
||||
if (!overlayPositionFixed)
|
||||
{
|
||||
screenover[nse].positionRelativeToScreen = false;
|
||||
VpPoint vpt = play.GetRoomViewport(0)->ScreenToRoom(screenover[nse].x, screenover[nse].y, false);
|
||||
screenover[nse].x = vpt.first.X;
|
||||
screenover[nse].y = vpt.first.Y;
|
||||
}
|
||||
|
||||
GameLoopUntilNoOverlay();
|
||||
}
|
||||
|
||||
play.messagetime=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int asspch, int isThought, int allowShrink, bool overlayPositionFixed) {
|
||||
int usingfont=FONT_NORMAL;
|
||||
if (asspch) usingfont=FONT_SPEECH;
|
||||
// TODO: _display_at may be called from _displayspeech, which can start
|
||||
// and finalize voice speech on its own. Find out if we really need to
|
||||
// keep track of this and not just stop voice regardless.
|
||||
bool need_stop_speech = false;
|
||||
|
||||
EndSkippingUntilCharStops();
|
||||
|
||||
if (try_auto_play_speech(text, text, play.narrator_speech, true))
|
||||
{// TODO: is there any need for this flag?
|
||||
need_stop_speech = true;
|
||||
}
|
||||
_display_main(xx, yy, wii, text, disp_type, usingfont, asspch, isThought, allowShrink, overlayPositionFixed);
|
||||
|
||||
if (need_stop_speech)
|
||||
stop_voice_speech();
|
||||
}
|
||||
|
||||
bool try_auto_play_speech(const char *text, const char *&replace_text, int charid, bool blocking)
|
||||
{
|
||||
const char *src = text;
|
||||
if (src[0] != '&')
|
||||
return false;
|
||||
|
||||
int sndid = atoi(&src[1]);
|
||||
while ((src[0] != ' ') & (src[0] != 0)) src++;
|
||||
if (src[0] == ' ') src++;
|
||||
if (sndid <= 0)
|
||||
quit("DisplaySpeech: auto-voice symbol '&' not followed by valid integer");
|
||||
|
||||
replace_text = src; // skip voice tag
|
||||
if (play_voice_speech(charid, sndid))
|
||||
{
|
||||
// if Voice Only, then blank out the text
|
||||
if (play.want_speech == 2)
|
||||
replace_text = " ";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: refactor this global variable out; currently it is set at the every get_translation call.
|
||||
// Be careful: a number of Say/Display functions expect it to be set beforehand.
|
||||
int source_text_length = -1;
|
||||
|
||||
int GetTextDisplayLength(const char *text)
|
||||
{
|
||||
int len = (int)strlen(text);
|
||||
if ((text[0] == '&') && (play.unfactor_speech_from_textlength != 0))
|
||||
{
|
||||
// if there's an "&12 text" type line, remove "&12 " from the source length
|
||||
size_t j = 0;
|
||||
while ((text[j] != ' ') && (text[j] != 0))
|
||||
j++;
|
||||
j++;
|
||||
len -= j;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int GetTextDisplayTime(const char *text, int canberel) {
|
||||
int uselen = 0;
|
||||
auto fpstimer = ::lround(get_current_fps());
|
||||
|
||||
// if it's background speech, make it stay relative to game speed
|
||||
if ((canberel == 1) && (play.bgspeech_game_speed == 1))
|
||||
fpstimer = 40;
|
||||
|
||||
if (source_text_length >= 0) {
|
||||
// sync to length of original text, to make sure any animations
|
||||
// and music sync up correctly
|
||||
uselen = source_text_length;
|
||||
source_text_length = -1;
|
||||
}
|
||||
else {
|
||||
uselen = GetTextDisplayLength(text);
|
||||
}
|
||||
|
||||
if (uselen <= 0)
|
||||
return 0;
|
||||
|
||||
if (play.text_speed + play.text_speed_modifier <= 0)
|
||||
quit("!Text speed is zero; unable to display text. Check your game.text_speed settings.");
|
||||
|
||||
// Store how many game loops per character of text
|
||||
// This is calculated using a hard-coded 15 for the text speed,
|
||||
// so that it's always the same no matter how fast the user
|
||||
// can read.
|
||||
loops_per_character = (((uselen/play.lipsync_speed)+1) * fpstimer) / uselen;
|
||||
|
||||
int textDisplayTimeInMS = ((uselen / (play.text_speed + play.text_speed_modifier)) + 1) * 1000;
|
||||
if (textDisplayTimeInMS < play.text_min_display_time_ms)
|
||||
textDisplayTimeInMS = play.text_min_display_time_ms;
|
||||
|
||||
return (textDisplayTimeInMS * fpstimer) / 1000;
|
||||
}
|
||||
|
||||
bool ShouldAntiAliasText() {
|
||||
return (game.options[OPT_ANTIALIASFONTS] != 0);
|
||||
}
|
||||
|
||||
#if defined (AGS_FONTOUTLINE_MOREOPAQUE)
|
||||
// TODO: was suggested by fernewelten, but it's unclear whether is necessary
|
||||
// Make semi-transparent bits much more opaque
|
||||
void wouttextxy_AutoOutline_Semitransparent2Opaque(Bitmap *map)
|
||||
{
|
||||
if (map->GetColorDepth() < 32)
|
||||
return; // such maps don't feature partial transparency
|
||||
size_t const width = map->GetWidth();
|
||||
size_t const height = map->GetHeight();
|
||||
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
int32 *sc_line = reinterpret_cast<int32 *>(map->GetScanLineForWriting(y));
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
int32 &px = sc_line[x];
|
||||
int const transparency = geta(px);
|
||||
if (0 < transparency && transparency < 255)
|
||||
px = makeacol32(
|
||||
getr32(px),
|
||||
getg32(px),
|
||||
getb32(px),
|
||||
std::min(85 + transparency * 2, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Draw outline that is calculated from the text font, not derived from an outline font
|
||||
void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *texx, int &xxp, int &yyp)
|
||||
{
|
||||
int const thickness = game.fonts.at(font).AutoOutlineThickness;
|
||||
auto const style = game.fonts.at(font).AutoOutlineStyle;
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
// 16-bit games should use 32-bit stencils to keep anti-aliasing working
|
||||
int const ds_cd = ds->GetColorDepth();
|
||||
bool const antialias = ds_cd >= 16 && 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);
|
||||
|
||||
size_t const t_width = wgettextwidth(texx, font);
|
||||
size_t const t_height = wgettextheight(texx, font);
|
||||
if (t_width == 0 || t_height == 0)
|
||||
return;
|
||||
Bitmap texx_stencil, outline_stencil;
|
||||
texx_stencil.CreateTransparent(t_width, t_height, stencil_cd);
|
||||
outline_stencil.CreateTransparent(t_width, t_height + 2 * thickness, stencil_cd);
|
||||
if (outline_stencil.IsNull() || texx_stencil.IsNull())
|
||||
return;
|
||||
wouttextxy(&texx_stencil, 0, 0, font, color, texx);
|
||||
#if defined (AGS_FONTOUTLINE_MOREOPAQUE)
|
||||
wouttextxy_AutoOutline_Semitransparent2Opaque(texx_stencil);
|
||||
#endif
|
||||
|
||||
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;
|
||||
yyp += thickness;
|
||||
|
||||
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(Common::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(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) - (wgettextwidth_compensate(text, usingfont) / 2);
|
||||
else if (align & kMAlignRight)
|
||||
usexp = usexp + (oriwid - wgettextwidth_compensate(text, usingfont));
|
||||
|
||||
wouttext_outline(ds, usexp, yy, usingfont, text_color, (char *)text);
|
||||
}
|
||||
|
||||
// Get outline's thickness addition to the font's width or height
|
||||
int get_outline_padding(int font)
|
||||
{
|
||||
if (get_font_outline(font) == FONT_OUTLINE_AUTO) {
|
||||
return get_font_outline_thickness(font) * 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getfontheight_outlined(int font)
|
||||
{
|
||||
return getfontheight(font) + get_outline_padding(font);
|
||||
}
|
||||
|
||||
int getfontspacing_outlined(int font)
|
||||
{
|
||||
return use_default_linespacing(font) ?
|
||||
getfontheight_outlined(font) :
|
||||
getfontlinespacing(font);
|
||||
}
|
||||
|
||||
int getfontlinegap(int font)
|
||||
{
|
||||
return getfontspacing_outlined(font) - getfontheight_outlined(font);
|
||||
}
|
||||
|
||||
int getheightoflines(int font, int numlines)
|
||||
{
|
||||
return getfontspacing_outlined(font) * (numlines - 1) + getfontheight_outlined(font);
|
||||
}
|
||||
|
||||
int wgettextwidth_compensate(const char *tex, int font)
|
||||
{
|
||||
return wgettextwidth(tex, font) + get_outline_padding(font);
|
||||
}
|
||||
|
||||
void do_corner(Bitmap *ds, int sprn, int x, int y, int offx, int offy) {
|
||||
if (sprn<0) return;
|
||||
if (spriteset[sprn] == nullptr)
|
||||
{
|
||||
sprn = 0;
|
||||
}
|
||||
|
||||
x = x + offx * game.SpriteInfos[sprn].Width;
|
||||
y = y + offy * 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 ? guibuts[butid].Image : 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);
|
||||
/* draw_color = ds->GetCompatibleColor(opts.tws.backcol); ds->FillRect(Rect(xx1,yy1,xx2,yy2);
|
||||
draw_color = ds->GetCompatibleColor(opts.tws.ds->GetTextColor()); ds->DrawRect(Rect(xx1+1,yy1+1,xx2-1,yy2-1);*/
|
||||
}
|
||||
else {
|
||||
if (loaded_game_file_version < kGameVersion_262) // < 2.62
|
||||
{
|
||||
// Color 0 wrongly shows as transparent instead of black
|
||||
// From the changelog of 2.62:
|
||||
// - Fixed text windows getting a black background if colour 0 was
|
||||
// specified, rather than being transparent.
|
||||
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);
|
||||
|
||||
int leftRightWidth = game.SpriteInfos[get_but_pic(iep,4)].Width;
|
||||
int topBottomHeight = game.SpriteInfos[get_but_pic(iep,6)].Height;
|
||||
if (iep->BgImage>0) {
|
||||
if ((loaded_game_file_version <= kGameVersion_272) // 2.xx
|
||||
&& (spriteset[iep->BgImage]->GetWidth() == 1)
|
||||
&& (spriteset[iep->BgImage]->GetHeight() == 1)
|
||||
&& (*((unsigned int*)spriteset[iep->BgImage]->GetData()) == 0x00FF00FF))
|
||||
{
|
||||
// Don't draw fully transparent dummy GUI backgrounds
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 += game.SpriteInfos[iep->BgImage].Height;
|
||||
}
|
||||
bgoffsx += game.SpriteInfos[iep->BgImage].Width;
|
||||
}
|
||||
// return to normal clipping rectangle
|
||||
ds->SetClip(Rect(0, 0, ds->GetWidth() - 1, ds->GetHeight() - 1));
|
||||
}
|
||||
}
|
||||
int uu;
|
||||
for (uu=yy1;uu <= yy2;uu+= 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
|
||||
}
|
||||
for (uu=xx1;uu <= xx2;uu+=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
|
||||
}
|
||||
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 (!guis[twgui].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
int borwid = game.SpriteInfos[get_but_pic(&guis[twgui], 4)].Width +
|
||||
game.SpriteInfos[get_but_pic(&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 (!guis[twgui].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
return game.SpriteInfos[get_but_pic(&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 = game.options[OPT_TWCUSTOM];
|
||||
if (ifnum > 0 && ifnum < game.numgui)
|
||||
result = 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) {
|
||||
|
||||
Bitmap *ds = *text_window_ds;
|
||||
if (ifnum < 0)
|
||||
ifnum = 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 >= game.numgui)
|
||||
quitprintf("!Invalid GUI %d specified as text window (total GUIs: %d)", ifnum, game.numgui);
|
||||
if (!guis[ifnum].IsTextWindow())
|
||||
quit("!GUI set as text window but is not actually a text window GUI");
|
||||
|
||||
int tbnum = get_but_pic(&guis[ifnum], 0);
|
||||
|
||||
wii[0] += get_textwindow_border_width (ifnum);
|
||||
xx[0]-=game.SpriteInfos[tbnum].Width;
|
||||
yy[0]-=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)+ game.SpriteInfos[tbnum].Height*2,game.GetColorDepth());
|
||||
ds = *text_window_ds;
|
||||
int xoffs=game.SpriteInfos[tbnum].Width,yoffs= game.SpriteInfos[tbnum].Height;
|
||||
draw_button_background(ds, xoffs,yoffs,(ds->GetWidth() - xoffs) - 1,(ds->GetHeight() - yoffs) - 1,&guis[ifnum]);
|
||||
if (set_text_color)
|
||||
*set_text_color = ds->GetCompatibleColor(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) {
|
||||
|
||||
draw_text_window(text_window_ds, should_free_ds, xins, yins, xx, yy, wii, set_text_color, ovrheight, ifnum);
|
||||
|
||||
if ((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() + topBar.height, game.GetColorDepth());
|
||||
newScreenop->Blit(ds, 0, 0, 0, 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(play.top_bar_backcolor);
|
||||
ds->FillRect(Rect(0, 0, ds->GetWidth() - 1, topBar.height - 1), draw_color);
|
||||
if (play.top_bar_backcolor != play.top_bar_bordercolor) {
|
||||
// draw the border
|
||||
draw_color = ds->GetCompatibleColor(play.top_bar_bordercolor);
|
||||
for (int j = 0; j < data_to_game_coord(play.top_bar_borderwidth); j++)
|
||||
ds->DrawRect(Rect(j, j, ds->GetWidth() - (j + 1), topBar.height - (j + 1)), draw_color);
|
||||
}
|
||||
|
||||
// draw the text
|
||||
int textx = (ds->GetWidth() / 2) - wgettextwidth_compensate(topBar.text, topBar.font) / 2;
|
||||
color_t text_color = ds->GetCompatibleColor(play.top_bar_textcolor);
|
||||
wouttext_outline(ds, textx, play.top_bar_borderwidth + get_fixed_pixel_size(1), topBar.font, text_color, topBar.text);
|
||||
|
||||
// don't draw it next time
|
||||
topBar.wantIt = 0;
|
||||
// adjust the text Y position
|
||||
yins[0] += topBar.height;
|
||||
}
|
||||
else if (topBar.wantIt)
|
||||
topBar.wantIt = 0;
|
||||
}
|
80
engines/ags/engine/ac/display.h
Normal file
80
engines/ags/engine/ac/display.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DISPLAY_H
|
||||
#define __AGS_EE_AC__DISPLAY_H
|
||||
|
||||
#include "gui/guimain.h"
|
||||
|
||||
using AGS::Common::GUIMain;
|
||||
|
||||
// options for 'disp_type' parameter
|
||||
#define DISPLAYTEXT_SPEECH 0
|
||||
#define DISPLAYTEXT_MESSAGEBOX 1
|
||||
#define DISPLAYTEXT_NORMALOVERLAY 2
|
||||
// also accepts explicit overlay ID >= OVER_CUSTOM
|
||||
|
||||
int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int usingfont, int asspch, int isThought, int allowShrink, bool overlayPositionFixed);
|
||||
void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int asspch, int isThought, int allowShrink, bool overlayPositionFixed);
|
||||
// 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, bool blocking);
|
||||
bool ShouldAntiAliasText();
|
||||
// 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(Common::Bitmap *ds, int xxp, int yyp, int usingfont, color_t text_color, const char *texx);
|
||||
void wouttext_aligned (Common::Bitmap *ds, int usexp, int yy, int oriwid, int usingfont, color_t text_color, const char *text, HorAlignment align);
|
||||
// TODO: GUI classes located in Common library do not make use of outlining,
|
||||
// need to find a way to make all code use same functions.
|
||||
// Get the maximal height of the given font, with corresponding outlining
|
||||
int getfontheight_outlined(int font);
|
||||
// Get line spacing for the given font, with possible outlining in mind
|
||||
int getfontspacing_outlined(int font);
|
||||
// Get the distance between bottom one one line and top of the next line (may be negative!)
|
||||
int getfontlinegap(int font);
|
||||
// Gets the total maximal height of the given number of lines printed with the given font
|
||||
int getheightoflines(int font, int numlines);
|
||||
// Get the maximal width of the given font, with corresponding outlining
|
||||
int wgettextwidth_compensate(const char *tex, int font);
|
||||
void do_corner(Common::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(Common::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(Common::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(Common::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);
|
||||
|
||||
// The efficient length of the last source text prepared for display
|
||||
extern int source_text_length;
|
||||
|
||||
#endif // __AGS_EE_AC__DISPLAY_H
|
2563
engines/ags/engine/ac/draw.cpp
Normal file
2563
engines/ags/engine/ac/draw.cpp
Normal file
File diff suppressed because it is too large
Load diff
175
engines/ags/engine/ac/draw.h
Normal file
175
engines/ags/engine/ac/draw.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DRAW_H
|
||||
#define __AGS_EE_AC__DRAW_H
|
||||
|
||||
#include <memory>
|
||||
#include "core/types.h"
|
||||
#include "ac/common_defines.h"
|
||||
#include "gfx/gfx_def.h"
|
||||
#include "util/wgt2allg.h"
|
||||
|
||||
namespace AGS
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
class Bitmap;
|
||||
typedef std::shared_ptr<Common::Bitmap> PBitmap;
|
||||
}
|
||||
namespace Engine { class IDriverDependantBitmap; }
|
||||
}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
#define IS_ANTIALIAS_SPRITES usetup.enable_antialiasing && (play.disable_antialiasing == 0)
|
||||
|
||||
// [IKM] WARNING: these definitions has to be made AFTER Allegro headers
|
||||
// were included, because they override few Allegro function names;
|
||||
// otherwise Allegro headers should not be included at all to the same
|
||||
// code unit which uses these defines.
|
||||
#define getr32(xx) ((xx >> _rgb_r_shift_32) & 0xFF)
|
||||
#define getg32(xx) ((xx >> _rgb_g_shift_32) & 0xFF)
|
||||
#define getb32(xx) ((xx >> _rgb_b_shift_32) & 0xFF)
|
||||
#define geta32(xx) ((xx >> _rgb_a_shift_32) & 0xFF)
|
||||
#define makeacol32(r,g,b,a) ((r << _rgb_r_shift_32) | (g << _rgb_g_shift_32) | (b << _rgb_b_shift_32) | (a << _rgb_a_shift_32))
|
||||
|
||||
|
||||
struct CachedActSpsData {
|
||||
int xWas, yWas;
|
||||
int baselineWas;
|
||||
int isWalkBehindHere;
|
||||
int valid;
|
||||
};
|
||||
|
||||
// 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 drawing resources upon entering new room
|
||||
void init_room_drawdata();
|
||||
// Disposes resources related to the current drawing methods
|
||||
void dispose_draw_method();
|
||||
// Disposes any temporary resources on leaving current room
|
||||
void dispose_room_drawdata();
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
void invalidate_cached_walkbehinds();
|
||||
// Avoid freeing and reallocating the memory if possible
|
||||
Common::Bitmap *recycle_bitmap(Common::Bitmap *bimp, int coldep, int wid, int hit, bool make_transparent = false);
|
||||
Engine::IDriverDependantBitmap* recycle_ddb_bitmap(Engine::IDriverDependantBitmap *bimp, Common::Bitmap *source, bool hasAlpha = false, bool opaque = false);
|
||||
// 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();
|
||||
void add_to_sprite_list(Engine::IDriverDependantBitmap* spp, int xx, int yy, int baseline, int trans, int sprNum, bool isWalkBehind = false);
|
||||
void tint_image (Common::Bitmap *g, Common::Bitmap *source, int red, int grn, int blu, int light_level, int luminance=255);
|
||||
void draw_sprite_support_alpha(Common::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Common::Bitmap *image, bool src_has_alpha,
|
||||
Common::BlendMode blend_mode = Common::kBlendMode_Alpha, int alpha = 0xFF);
|
||||
void draw_sprite_slot_support_alpha(Common::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, int src_slot,
|
||||
Common::BlendMode blend_mode = Common::kBlendMode_Alpha, int alpha = 0xFF);
|
||||
void draw_gui_sprite(Common::Bitmap *ds, int pic, int x, int y, bool use_alpha, Common::BlendMode blend_mode);
|
||||
void draw_gui_sprite_v330(Common::Bitmap *ds, int pic, int x, int y, bool use_alpha = true, Common::BlendMode blend_mode = Common::kBlendMode_Alpha);
|
||||
// Render game on screen
|
||||
void render_to_screen();
|
||||
// Callbacks for the graphics driver
|
||||
void draw_game_screen_callback();
|
||||
void GfxDriverOnInitCallback(void *data);
|
||||
bool GfxDriverNullSpriteCallback(int x, int y);
|
||||
void putpixel_compensate (Common::Bitmap *g, int xx,int yy, int col);
|
||||
// create the actsps[aa] image with the object drawn correctly
|
||||
// returns 1 if nothing at all has changed and actsps is still
|
||||
// intact from last time; 0 otherwise
|
||||
int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
|
||||
void clear_letterbox_borders();
|
||||
|
||||
void draw_and_invalidate_text(Common::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).
|
||||
extern AGS_INLINE int get_fixed_pixel_size(int pixels);
|
||||
// coordinate conversion data,script ---> final game resolution
|
||||
extern AGS_INLINE int data_to_game_coord(int coord);
|
||||
extern AGS_INLINE void data_to_game_coords(int *x, int *y);
|
||||
extern AGS_INLINE void data_to_game_round_up(int *x, int *y);
|
||||
// coordinate conversion final game resolution ---> data,script
|
||||
extern AGS_INLINE int game_to_data_coord(int coord);
|
||||
extern AGS_INLINE void game_to_data_coords(int &x, int &y);
|
||||
extern AGS_INLINE int game_to_data_round_up(int coord);
|
||||
// convert contextual data coordinates to final game resolution
|
||||
extern AGS_INLINE void ctx_data_to_game_coord(int &x, int &y, bool hires_ctx);
|
||||
extern AGS_INLINE void ctx_data_to_game_size(int &x, int &y, bool hires_ctx);
|
||||
extern AGS_INLINE int ctx_data_to_game_size(int size, bool hires_ctx);
|
||||
extern AGS_INLINE 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 AGS_INLINE void defgame_to_finalgame_coords(int &x, int &y);
|
||||
|
||||
// Checks if the bitmap needs to be converted and **deletes original** if a new bitmap
|
||||
// had to be created (by default).
|
||||
// TODO: this helper function was meant to remove bitmap deletion from the GraphicsDriver's
|
||||
// implementations while keeping code changes to minimum. The proper solution would probably
|
||||
// be to use shared pointers when storing Bitmaps, or make Bitmap reference-counted object.
|
||||
Common::Bitmap *ReplaceBitmapWithSupportedFormat(Common::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.
|
||||
Common::Bitmap *PrepareSpriteForUse(Common::Bitmap *bitmap, bool has_alpha);
|
||||
// Same as above, but compatible for std::shared_ptr.
|
||||
Common::PBitmap PrepareSpriteForUse(Common::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.
|
||||
Common::Bitmap *CopyScreenIntoBitmap(int width, int height, bool at_native_res = false);
|
||||
|
||||
#endif // __AGS_EE_AC__DRAW_H
|
491
engines/ags/engine/ac/draw_software.cpp
Normal file
491
engines/ags/engine/ac/draw_software.cpp
Normal file
|
@ -0,0 +1,491 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// 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 perfomance 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 <string.h>
|
||||
#include <vector>
|
||||
#include "ac/draw_software.h"
|
||||
#include "gfx/bitmap.h"
|
||||
#include "util/scaling.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
using namespace AGS::Engine;
|
||||
|
||||
// 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();
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Dirty rects for the main viewport background (black screen);
|
||||
// these are used when the room viewport does not cover whole screen,
|
||||
// so that we know when to paint black after mouse cursor and gui.
|
||||
DirtyRects BlackRects;
|
||||
// Dirty rects object for the single room camera
|
||||
std::vector<DirtyRects> RoomCamRects;
|
||||
// Saved room camera offsets to know if we must invalidate whole surface.
|
||||
// TODO: if we support rotation then we also need to compare full transform!
|
||||
std::vector<std::pair<int, int>> RoomCamPositions;
|
||||
|
||||
|
||||
void dispose_invalid_regions(bool /* room_only */)
|
||||
{
|
||||
RoomCamRects.clear();
|
||||
RoomCamPositions.clear();
|
||||
}
|
||||
|
||||
void init_invalid_regions(int view_index, const Size &surf_size, const Rect &viewport)
|
||||
{
|
||||
if (view_index < 0)
|
||||
{
|
||||
BlackRects.Init(surf_size, viewport);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RoomCamRects.size() <= (size_t)view_index)
|
||||
{
|
||||
RoomCamRects.resize(view_index + 1);
|
||||
RoomCamPositions.resize(view_index + 1);
|
||||
}
|
||||
RoomCamRects[view_index].Init(surf_size, viewport);
|
||||
RoomCamPositions[view_index] = std::make_pair(-1000, -1000);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_invalid_regions(int view_index)
|
||||
{
|
||||
if (view_index >= 0)
|
||||
{
|
||||
RoomCamRects.erase(RoomCamRects.begin() + view_index);
|
||||
RoomCamPositions.erase(RoomCamPositions.begin() + view_index);
|
||||
}
|
||||
}
|
||||
|
||||
void set_invalidrects_cameraoffs(int view_index, int x, int y)
|
||||
{
|
||||
if (view_index < 0)
|
||||
{
|
||||
BlackRects.SetSurfaceOffsets(x, y);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
RoomCamRects[view_index].SetSurfaceOffsets(x, y);
|
||||
}
|
||||
|
||||
int &posxwas = RoomCamPositions[view_index].first;
|
||||
int &posywas = 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 : RoomCamRects)
|
||||
{
|
||||
if (!IsRectInsideRect(rects.Viewport, BlackRects.Viewport))
|
||||
BlackRects.NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
rects.NumDirtyRegions = WHOLESCREENDIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate_all_camera_rects(int view_index)
|
||||
{
|
||||
if (view_index < 0)
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
int a;
|
||||
|
||||
const Size &surfsz = rects.SurfaceSize;
|
||||
if (x1 >= surfsz.Width) x1 = surfsz.Width - 1;
|
||||
if (y1 >= surfsz.Height) y1 = surfsz.Height - 1;
|
||||
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;
|
||||
if (x2 < 0) x2 = 0;
|
||||
if (y2 < 0) y2 = 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;
|
||||
int tleft, tright;
|
||||
// find the nearest span, and enlarge that to include this rect
|
||||
for (s = 0; s < dirtyRow[a].numSpans; s++) {
|
||||
tleft = dirtyRow[a].span[s].x1 - x2;
|
||||
if ((tleft > 0) && (tleft < nearestDist)) {
|
||||
nearestDist = tleft;
|
||||
nearestWas = s;
|
||||
extendLeft = 1;
|
||||
}
|
||||
tright = x1 - dirtyRow[a].span[s].x2;
|
||||
if ((tright > 0) && (tright < nearestDist)) {
|
||||
nearestDist = tright;
|
||||
nearestWas = s;
|
||||
extendLeft = 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, 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
for (auto &rects : RoomCamRects)
|
||||
invalidate_rect_ds(rects, x1, y1, x2, y2, in_room);
|
||||
}
|
||||
|
||||
// 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()) && (ds->IsMemoryBitmap()))
|
||||
{
|
||||
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 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 (!BlackRects.IsInit())
|
||||
return;
|
||||
update_invalid_region(ds, (color_t)0, BlackRects);
|
||||
BlackRects.Reset();
|
||||
}
|
||||
|
||||
void update_room_invreg_and_reset(int view_index, Bitmap *ds, Bitmap *src, bool no_transform)
|
||||
{
|
||||
if (view_index < 0 || RoomCamRects.size() == 0)
|
||||
return;
|
||||
|
||||
update_invalid_region(ds, src, RoomCamRects[view_index], no_transform);
|
||||
RoomCamRects[view_index].Reset();
|
||||
}
|
46
engines/ags/engine/ac/draw_software.h
Normal file
46
engines/ags/engine/ac/draw_software.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// Software drawing component. Optimizes drawing for software renderer using
|
||||
// dirty rectangles technique.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DRAWSOFTWARE_H
|
||||
#define __AGS_EE_AC__DRAWSOFTWARE_H
|
||||
|
||||
#include "gfx/bitmap.h"
|
||||
#include "gfx/ddb.h"
|
||||
#include "util/geometry.h"
|
||||
|
||||
// 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);
|
||||
void invalidate_rect_ds(int x1, int y1, int x2, int y2, bool in_room);
|
||||
// Paints the black screen background in the regions marked as dirty
|
||||
void update_black_invreg_and_reset(AGS::Common::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::Common::Bitmap *ds, AGS::Common::Bitmap *src, bool no_transform);
|
||||
|
||||
#endif // __AGS_EE_AC__DRAWSOFTWARE_H
|
694
engines/ags/engine/ac/drawingsurface.cpp
Normal file
694
engines/ags/engine/ac/drawingsurface.cpp
Normal file
|
@ -0,0 +1,694 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/draw.h"
|
||||
#include "ac/drawingsurface.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/charactercache.h"
|
||||
#include "ac/display.h"
|
||||
#include "ac/game.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "ac/global_translation.h"
|
||||
#include "ac/objectcache.h"
|
||||
#include "ac/roomobject.h"
|
||||
#include "ac/roomstatus.h"
|
||||
#include "ac/string.h"
|
||||
#include "ac/walkbehind.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "font/fonts.h"
|
||||
#include "gui/guimain.h"
|
||||
#include "ac/spritecache.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "gfx/gfx_def.h"
|
||||
#include "gfx/gfx_util.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
using namespace AGS::Engine;
|
||||
|
||||
extern GameSetupStruct game;
|
||||
extern GameState play;
|
||||
extern RoomStatus*croom;
|
||||
extern RoomObject*objs;
|
||||
extern CharacterCache *charcache;
|
||||
extern ObjectCache objcache[MAX_ROOM_OBJECTS];
|
||||
extern SpriteCache spriteset;
|
||||
extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
|
||||
|
||||
// ** SCRIPT DRAWINGSURFACE OBJECT
|
||||
|
||||
void DrawingSurface_Release(ScriptDrawingSurface* sds)
|
||||
{
|
||||
if (sds->roomBackgroundNumber >= 0)
|
||||
{
|
||||
if (sds->modified)
|
||||
{
|
||||
if (sds->roomBackgroundNumber == play.bg_frame)
|
||||
{
|
||||
invalidate_screen();
|
||||
mark_current_background_dirty();
|
||||
}
|
||||
play.raw_modified[sds->roomBackgroundNumber] = 1;
|
||||
}
|
||||
|
||||
sds->roomBackgroundNumber = -1;
|
||||
}
|
||||
if (sds->roomMaskType > kRoomAreaNone)
|
||||
{
|
||||
if (sds->roomMaskType == kRoomAreaWalkBehind)
|
||||
{
|
||||
recache_walk_behinds();
|
||||
}
|
||||
sds->roomMaskType = kRoomAreaNone;
|
||||
}
|
||||
if (sds->dynamicSpriteNumber >= 0)
|
||||
{
|
||||
if (sds->modified)
|
||||
{
|
||||
int tt;
|
||||
// force a refresh of any cached object or character images
|
||||
if (croom != nullptr)
|
||||
{
|
||||
for (tt = 0; tt < croom->numobj; tt++)
|
||||
{
|
||||
if (objs[tt].num == sds->dynamicSpriteNumber)
|
||||
objcache[tt].sppic = -31999;
|
||||
}
|
||||
}
|
||||
for (tt = 0; tt < game.numcharacters; tt++)
|
||||
{
|
||||
if (charcache[tt].sppic == sds->dynamicSpriteNumber)
|
||||
charcache[tt].sppic = -31999;
|
||||
}
|
||||
for (tt = 0; tt < game.numgui; tt++)
|
||||
{
|
||||
if ((guis[tt].BgImage == sds->dynamicSpriteNumber) &&
|
||||
(guis[tt].IsDisplayed()))
|
||||
{
|
||||
guis_need_update = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sds->dynamicSpriteNumber = -1;
|
||||
}
|
||||
if (sds->dynamicSurfaceNumber >= 0)
|
||||
{
|
||||
delete dynamicallyCreatedSurfaces[sds->dynamicSurfaceNumber];
|
||||
dynamicallyCreatedSurfaces[sds->dynamicSurfaceNumber] = nullptr;
|
||||
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 (dynamicallyCreatedSurfaces[i] == nullptr)
|
||||
{
|
||||
dynamicallyCreatedSurfaces[i] = 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)
|
||||
quit("!DrawingSurface.DrawImage: cannot draw onto itself");
|
||||
if ((trans < 0) || (trans > 100))
|
||||
quit("!DrawingSurface.DrawImage: invalid transparency setting");
|
||||
|
||||
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); }
|
||||
|
||||
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 simplier blit/draw_sprite could be called (no translucency with alpha channel).
|
||||
bool needToFreeBitmap = false;
|
||||
if (dst_width != src->GetWidth() || dst_height != src->GetHeight() ||
|
||||
src_width != src->GetWidth() || src_height != src->GetHeight())
|
||||
{
|
||||
// Resize and/or partial copy specified
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmap(dst_width, dst_height, src->GetColorDepth());
|
||||
newPic->StretchBlt(src,
|
||||
RectWH(src_x, src_y, src_width, src_height),
|
||||
RectWH(0, 0, dst_width, dst_height));
|
||||
|
||||
src = newPic;
|
||||
needToFreeBitmap = true;
|
||||
update_polled_stuff_if_runtime();
|
||||
}
|
||||
|
||||
ds = sds->StartDrawing();
|
||||
sds->PointToGameResolution(&dst_x, &dst_y);
|
||||
|
||||
if (src->GetColorDepth() != ds->GetColorDepth()) {
|
||||
if (sprite_id >= 0)
|
||||
debug_script_warn("DrawImage: Sprite %d colour depth %d-bit not same as background depth %d-bit", sprite_id, src->GetColorDepth(), ds->GetColorDepth());
|
||||
else
|
||||
debug_script_warn("DrawImage: Source image colour depth %d-bit not same as background depth %d-bit", src->GetColorDepth(), ds->GetColorDepth());
|
||||
}
|
||||
|
||||
draw_sprite_support_alpha(ds, sds->hasAlphaChannel != 0, dst_x, dst_y, src, src_has_alpha,
|
||||
kBlendMode_Alpha, GfxDef::Trans100ToAlpha255(trans));
|
||||
|
||||
sds->FinishedDrawing();
|
||||
|
||||
if (needToFreeBitmap)
|
||||
delete src;
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawImageEx(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) || (spriteset[slot] == nullptr))
|
||||
quit("!DrawingSurface.DrawImage: invalid sprite slot number specified");
|
||||
DrawingSurface_DrawImageImpl(sds, spriteset[slot], dst_x, dst_y, trans, dst_width, dst_height,
|
||||
src_x, src_y, src_width, src_height, slot, (game.SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawImage(ScriptDrawingSurface* sds, int xx, int yy, int slot, int trans, int width, int height)
|
||||
{
|
||||
DrawingSurface_DrawImageEx(sds, xx, yy, slot, trans, width, height, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawSurfaceEx(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);
|
||||
}
|
||||
|
||||
void DrawingSurface_DrawSurface(ScriptDrawingSurface* target, ScriptDrawingSurface* source, int trans)
|
||||
{
|
||||
DrawingSurface_DrawSurfaceEx(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 (game.AllowRelativeRes())
|
||||
sds->highResCoordinates = (highRes) ? 1 : 0;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetUseHighResCoordinates(ScriptDrawingSurface *sds)
|
||||
{
|
||||
return sds->highResCoordinates;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetHeight(ScriptDrawingSurface *sds)
|
||||
{
|
||||
Bitmap *ds = sds->GetBitmapSurface();
|
||||
int height = ds->GetHeight();
|
||||
sds->SizeToGameResolution(&height);
|
||||
return height;
|
||||
}
|
||||
|
||||
int DrawingSurface_GetWidth(ScriptDrawingSurface *sds)
|
||||
{
|
||||
Bitmap *ds = sds->GetBitmapSurface();
|
||||
int width = ds->GetWidth();
|
||||
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) && (play.raw_color > 255)) {
|
||||
text_color = ds->GetCompatibleColor(1);
|
||||
debug_script_warn ("RawPrint: Attempted to use hi-color on 256-col background");
|
||||
}
|
||||
wouttext_outline(ds, xx, yy, font, text_color, text);
|
||||
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 = getfontspacing_outlined(font);
|
||||
sds->PointToGameResolution(&xx, &yy);
|
||||
sds->SizeToGameResolution(&wid);
|
||||
|
||||
if (break_up_text_into_lines(msg, Lines, wid, font) == 0)
|
||||
return;
|
||||
|
||||
Bitmap *ds = sds->StartDrawing();
|
||||
color_t text_color = sds->currentColour;
|
||||
|
||||
for (size_t i = 0; i < Lines.Count(); i++)
|
||||
{
|
||||
int drawAtX = xx;
|
||||
|
||||
if (alignment & kMAlignHCenter)
|
||||
{
|
||||
drawAtX = xx + ((wid / 2) - wgettextwidth(Lines[i], font) / 2);
|
||||
}
|
||||
else if (alignment & kMAlignRight)
|
||||
{
|
||||
drawAtX = (xx + wid) - wgettextwidth(Lines[i], font);
|
||||
}
|
||||
|
||||
wouttext_outline(ds, drawAtX, yy + linespacing*i, font, text_color, Lines[i]);
|
||||
}
|
||||
|
||||
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();
|
||||
unsigned int rawPixel = ds->GetPixel(x, y);
|
||||
unsigned int maskColor = ds->GetMaskColor();
|
||||
int colDepth = ds->GetColorDepth();
|
||||
|
||||
if (rawPixel == maskColor)
|
||||
{
|
||||
rawPixel = SCR_COLOR_TRANSPARENT;
|
||||
}
|
||||
else if (colDepth > 8)
|
||||
{
|
||||
int r = getr_depth(colDepth, rawPixel);
|
||||
int ds = getg_depth(colDepth, rawPixel);
|
||||
int b = getb_depth(colDepth, rawPixel);
|
||||
|
||||
rawPixel = Game_GetColorFromRGB(r, ds, b);
|
||||
}
|
||||
|
||||
sds->FinishedDrawingReadOnly();
|
||||
|
||||
return rawPixel;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
// 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_DrawImage_6(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_VOID_PINT6(ScriptDrawingSurface, DrawingSurface_DrawImage);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawImage(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
|
||||
DrawingSurface_DrawImageEx((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_VOID_PINT5_POBJ(ScriptDrawingSurface, DrawingSurface_DrawStringWrapped, const char);
|
||||
}
|
||||
|
||||
// void (ScriptDrawingSurface* target, ScriptDrawingSurface* source, int translev)
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawSurface_2(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
API_OBJCALL_VOID_POBJ_PINT(ScriptDrawingSurface, DrawingSurface_DrawSurface, ScriptDrawingSurface);
|
||||
}
|
||||
|
||||
RuntimeScriptValue Sc_DrawingSurface_DrawSurface(void *self, const RuntimeScriptValue *params, int32_t param_count)
|
||||
{
|
||||
ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
|
||||
DrawingSurface_DrawSurfaceEx((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 API for Plugins
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// void (ScriptDrawingSurface *sds, int xx, int yy, int font, const char* texx, ...)
|
||||
void ScPl_DrawingSurface_DrawString(ScriptDrawingSurface *sds, int xx, int yy, int font, const char* texx, ...)
|
||||
{
|
||||
API_PLUGIN_SCRIPT_SPRINTF(texx);
|
||||
DrawingSurface_DrawString(sds, xx, yy, font, scsf_buffer);
|
||||
}
|
||||
|
||||
void RegisterDrawingSurfaceAPI(ScriptAPIVersion base_api, ScriptAPIVersion compat_api)
|
||||
{
|
||||
ccAddExternalObjectFunction("DrawingSurface::Clear^1", Sc_DrawingSurface_Clear);
|
||||
ccAddExternalObjectFunction("DrawingSurface::CreateCopy^0", Sc_DrawingSurface_CreateCopy);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawCircle^3", Sc_DrawingSurface_DrawCircle);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawImage^6", Sc_DrawingSurface_DrawImage_6);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawImage^10", Sc_DrawingSurface_DrawImage);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawLine^5", Sc_DrawingSurface_DrawLine);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawMessageWrapped^5", Sc_DrawingSurface_DrawMessageWrapped);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawPixel^2", Sc_DrawingSurface_DrawPixel);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawRectangle^4", Sc_DrawingSurface_DrawRectangle);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawString^104", Sc_DrawingSurface_DrawString);
|
||||
if (base_api < kScriptAPI_v350)
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawStringWrapped^6", Sc_DrawingSurface_DrawStringWrapped_Old);
|
||||
else
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawStringWrapped^6", Sc_DrawingSurface_DrawStringWrapped);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawSurface^2", Sc_DrawingSurface_DrawSurface_2);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawSurface^10", Sc_DrawingSurface_DrawSurface);
|
||||
ccAddExternalObjectFunction("DrawingSurface::DrawTriangle^6", Sc_DrawingSurface_DrawTriangle);
|
||||
ccAddExternalObjectFunction("DrawingSurface::GetPixel^2", Sc_DrawingSurface_GetPixel);
|
||||
ccAddExternalObjectFunction("DrawingSurface::Release^0", Sc_DrawingSurface_Release);
|
||||
ccAddExternalObjectFunction("DrawingSurface::get_DrawingColor", Sc_DrawingSurface_GetDrawingColor);
|
||||
ccAddExternalObjectFunction("DrawingSurface::set_DrawingColor", Sc_DrawingSurface_SetDrawingColor);
|
||||
ccAddExternalObjectFunction("DrawingSurface::get_Height", Sc_DrawingSurface_GetHeight);
|
||||
ccAddExternalObjectFunction("DrawingSurface::get_UseHighResCoordinates", Sc_DrawingSurface_GetUseHighResCoordinates);
|
||||
ccAddExternalObjectFunction("DrawingSurface::set_UseHighResCoordinates", Sc_DrawingSurface_SetUseHighResCoordinates);
|
||||
ccAddExternalObjectFunction("DrawingSurface::get_Width", Sc_DrawingSurface_GetWidth);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::Clear^1", (void*)DrawingSurface_Clear);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::CreateCopy^0", (void*)DrawingSurface_CreateCopy);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawCircle^3", (void*)DrawingSurface_DrawCircle);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawImage^6", (void*)DrawingSurface_DrawImage);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawLine^5", (void*)DrawingSurface_DrawLine);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawMessageWrapped^5", (void*)DrawingSurface_DrawMessageWrapped);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawPixel^2", (void*)DrawingSurface_DrawPixel);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawRectangle^4", (void*)DrawingSurface_DrawRectangle);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawString^104", (void*)ScPl_DrawingSurface_DrawString);
|
||||
if (base_api < kScriptAPI_v350)
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawStringWrapped^6", (void*)DrawingSurface_DrawStringWrapped_Old);
|
||||
else
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawStringWrapped^6", (void*)DrawingSurface_DrawStringWrapped);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawSurface^2", (void*)DrawingSurface_DrawSurface);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::DrawTriangle^6", (void*)DrawingSurface_DrawTriangle);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::GetPixel^2", (void*)DrawingSurface_GetPixel);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::Release^0", (void*)DrawingSurface_Release);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::get_DrawingColor", (void*)DrawingSurface_GetDrawingColor);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::set_DrawingColor", (void*)DrawingSurface_SetDrawingColor);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::get_Height", (void*)DrawingSurface_GetHeight);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::get_UseHighResCoordinates", (void*)DrawingSurface_GetUseHighResCoordinates);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::set_UseHighResCoordinates", (void*)DrawingSurface_SetUseHighResCoordinates);
|
||||
ccAddExternalFunctionForPlugin("DrawingSurface::get_Width", (void*)DrawingSurface_GetWidth);
|
||||
}
|
45
engines/ags/engine/ac/drawingsurface.h
Normal file
45
engines/ags/engine/ac/drawingsurface.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DRAWINGSURFACE_H
|
||||
#define __AGS_EE_AC__DRAWINGSURFACE_H
|
||||
|
||||
#include "ac/dynobj/scriptdrawingsurface.h"
|
||||
|
||||
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 translev);
|
||||
void DrawingSurface_DrawImage_FullSrc(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_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);
|
||||
|
||||
#endif // __AGS_EE_AC__DRAWINGSURFACE_H
|
700
engines/ags/engine/ac/dynamicsprite.cpp
Normal file
700
engines/ags/engine/ac/dynamicsprite.cpp
Normal file
|
@ -0,0 +1,700 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <math.h>
|
||||
#include "ac/dynamicsprite.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/charactercache.h"
|
||||
#include "ac/draw.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/global_dynamicsprite.h"
|
||||
#include "ac/global_game.h"
|
||||
#include "ac/math.h" // M_PI
|
||||
#include "ac/objectcache.h"
|
||||
#include "ac/path_helper.h"
|
||||
#include "ac/roomobject.h"
|
||||
#include "ac/roomstatus.h"
|
||||
#include "ac/system.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "game/roomstruct.h"
|
||||
#include "gui/guibutton.h"
|
||||
#include "ac/spritecache.h"
|
||||
#include "gfx/graphicsdriver.h"
|
||||
#include "script/runtimescriptvalue.h"
|
||||
|
||||
using namespace Common;
|
||||
using namespace Engine;
|
||||
|
||||
extern GameSetupStruct game;
|
||||
extern SpriteCache spriteset;
|
||||
extern RoomStruct thisroom;
|
||||
extern RoomObject*objs;
|
||||
extern RoomStatus*croom;
|
||||
extern CharacterCache *charcache;
|
||||
extern ObjectCache objcache[MAX_ROOM_OBJECTS];
|
||||
|
||||
extern color palette[256];
|
||||
extern AGS::Engine::IGraphicsDriver *gfxDriver;
|
||||
|
||||
char check_dynamic_sprites_at_exit = 1;
|
||||
|
||||
// ** 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 ((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(game.SpriteInfos[sds->slot].Width);
|
||||
}
|
||||
|
||||
int DynamicSprite_GetHeight(ScriptDynamicSprite *sds) {
|
||||
return game_to_data_coord(game.SpriteInfos[sds->slot].Height);
|
||||
}
|
||||
|
||||
int DynamicSprite_GetColorDepth(ScriptDynamicSprite *sds) {
|
||||
int depth = 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 *newPic = BitmapHelper::CreateBitmap(width, height, spriteset[sds->slot]->GetColorDepth());
|
||||
newPic->StretchBlt(spriteset[sds->slot],
|
||||
RectWH(0, 0, game.SpriteInfos[sds->slot].Width, game.SpriteInfos[sds->slot].Height),
|
||||
RectWH(0, 0, width, height));
|
||||
|
||||
delete spriteset[sds->slot];
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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 *newPic = BitmapHelper::CreateTransparentBitmap(game.SpriteInfos[sds->slot].Width, game.SpriteInfos[sds->slot].Height, spriteset[sds->slot]->GetColorDepth());
|
||||
|
||||
if (direction == 1)
|
||||
newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_HFlip);
|
||||
else if (direction == 2)
|
||||
newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_VFlip);
|
||||
else if (direction == 3)
|
||||
newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_HVFlip);
|
||||
|
||||
delete spriteset[sds->slot];
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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 ((game.SpriteInfos[sds->slot].Width != game.SpriteInfos[sourceSprite].Width) ||
|
||||
(game.SpriteInfos[sds->slot].Height != game.SpriteInfos[sourceSprite].Height))
|
||||
{
|
||||
quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size");
|
||||
}
|
||||
|
||||
Bitmap *target = spriteset[sds->slot];
|
||||
Bitmap *source = 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 = (game.SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0;
|
||||
bool src_has_alpha = (game.SpriteInfos[sourceSprite].Flags & SPF_ALPHACHANNEL) != 0;
|
||||
game.SpriteInfos[sds->slot].Flags &= ~SPF_ALPHACHANNEL;
|
||||
if (src_has_alpha)
|
||||
{
|
||||
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 *newPic = BitmapHelper::CreateTransparentBitmap(width, height, spriteset[sds->slot]->GetColorDepth());
|
||||
// blit it into the enlarged image
|
||||
newPic->Blit(spriteset[sds->slot], 0, 0, x, y, game.SpriteInfos[sds->slot].Width, game.SpriteInfos[sds->slot].Height);
|
||||
|
||||
delete spriteset[sds->slot];
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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 > game.SpriteInfos[sds->slot].Width) || (height > game.SpriteInfos[sds->slot].Height))
|
||||
quit("!DynamicSprite.Crop: requested to crop an area larger than the source");
|
||||
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, spriteset[sds->slot]->GetColorDepth());
|
||||
// blit it cropped
|
||||
newPic->Blit(spriteset[sds->slot], x1, y1, 0, 0, newPic->GetWidth(), newPic->GetHeight());
|
||||
|
||||
delete spriteset[sds->slot];
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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)game.SpriteInfos[sds->slot].Width + sinVal * (double)game.SpriteInfos[sds->slot].Height);
|
||||
height = (sinVal * (double)game.SpriteInfos[sds->slot].Width + cosVal * (double)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 *newPic = BitmapHelper::CreateTransparentBitmap(width, height, spriteset[sds->slot]->GetColorDepth());
|
||||
|
||||
// rotate the sprite about its centre
|
||||
// (+ width%2 fixes one pixel offset problem)
|
||||
newPic->RotateBlt(spriteset[sds->slot], width / 2 + width % 2, height / 2,
|
||||
game.SpriteInfos[sds->slot].Width / 2, game.SpriteInfos[sds->slot].Height / 2, itofix(angle));
|
||||
|
||||
delete spriteset[sds->slot];
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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 = spriteset[sds->slot];
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmap(source->GetWidth(), source->GetHeight(), source->GetColorDepth());
|
||||
|
||||
tint_image(newPic, source, red, green, blue, saturation, (luminance * 25) / 10);
|
||||
|
||||
delete source;
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(sds->slot, newPic, (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('.') == -1)
|
||||
filename.Append(".bmp");
|
||||
|
||||
ResolvedPath rp;
|
||||
if (!ResolveWritePathAndCreateDirs(filename, rp))
|
||||
return 0;
|
||||
return spriteset[sds->slot]->SaveToFile(rp.FullPath, 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()
|
||||
|
||||
int gotSlot = spriteset.GetFreeIndex();
|
||||
if (gotSlot <= 0)
|
||||
return nullptr;
|
||||
|
||||
const Rect &viewport = 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);
|
||||
|
||||
Bitmap *newPic = CopyScreenIntoBitmap(width, height);
|
||||
|
||||
update_polled_stuff_if_runtime();
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic));
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
|
||||
return new_spr;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite* DynamicSprite_CreateFromExistingSprite(int slot, int preserveAlphaChannel) {
|
||||
|
||||
int gotSlot = spriteset.GetFreeIndex();
|
||||
if (gotSlot <= 0)
|
||||
return nullptr;
|
||||
|
||||
if (!spriteset.DoesSpriteExist(slot))
|
||||
quitprintf("DynamicSprite.CreateFromExistingSprite: sprite %d does not exist", slot);
|
||||
|
||||
// create a new sprite as a copy of the existing one
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmapCopy(spriteset[slot]);
|
||||
if (newPic == nullptr)
|
||||
return nullptr;
|
||||
|
||||
bool hasAlpha = (preserveAlphaChannel) && ((game.SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(gotSlot, newPic, hasAlpha);
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
|
||||
return new_spr;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite* DynamicSprite_CreateFromDrawingSurface(ScriptDrawingSurface *sds, int x, int y, int width, int height)
|
||||
{
|
||||
int gotSlot = spriteset.GetFreeIndex();
|
||||
if (gotSlot <= 0)
|
||||
return nullptr;
|
||||
|
||||
// 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");
|
||||
|
||||
int colDepth = ds->GetColorDepth();
|
||||
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, colDepth);
|
||||
if (newPic == nullptr)
|
||||
return nullptr;
|
||||
|
||||
newPic->Blit(ds, x, y, 0, 0, width, height);
|
||||
|
||||
sds->FinishedDrawingReadOnly();
|
||||
|
||||
add_dynamic_sprite(gotSlot, newPic, (sds->hasAlphaChannel != 0));
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
|
||||
return new_spr;
|
||||
}
|
||||
|
||||
ScriptDynamicSprite* DynamicSprite_Create(int width, int height, int alphaChannel)
|
||||
{
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
int gotSlot = spriteset.GetFreeIndex();
|
||||
if (gotSlot <= 0)
|
||||
return nullptr;
|
||||
|
||||
Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(width, height, game.GetColorDepth());
|
||||
if (newPic == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if ((alphaChannel) && (game.GetColorDepth() < 32))
|
||||
alphaChannel = false;
|
||||
|
||||
add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic), alphaChannel != 0);
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
|
||||
return new_spr;
|
||||
}
|
||||
|
||||
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 = play.bg_frame;
|
||||
}
|
||||
else if ((frame < 0) || ((size_t)frame >= thisroom.BgFrameCount))
|
||||
quit("!DynamicSprite.CreateFromBackground: invalid frame specified");
|
||||
|
||||
if (x1 == SCR_NO_VALUE) {
|
||||
x1 = 0;
|
||||
y1 = 0;
|
||||
width = play.room_width;
|
||||
height = play.room_height;
|
||||
}
|
||||
else if ((x1 < 0) || (y1 < 0) || (width < 1) || (height < 1) ||
|
||||
(x1 + width > play.room_width) || (y1 + height > play.room_height))
|
||||
quit("!DynamicSprite.CreateFromBackground: invalid co-ordinates specified");
|
||||
|
||||
data_to_game_coords(&x1, &y1);
|
||||
data_to_game_coords(&width, &height);
|
||||
|
||||
int gotSlot = spriteset.GetFreeIndex();
|
||||
if (gotSlot <= 0)
|
||||
return nullptr;
|
||||
|
||||
// create a new sprite as a copy of the existing one
|
||||
Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, thisroom.BgFrames[frame].Graphic->GetColorDepth());
|
||||
if (newPic == nullptr)
|
||||
return nullptr;
|
||||
|
||||
newPic->Blit(thisroom.BgFrames[frame].Graphic.get(), x1, y1, 0, 0, width, height);
|
||||
|
||||
// replace the bitmap in the sprite set
|
||||
add_dynamic_sprite(gotSlot, newPic);
|
||||
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
|
||||
return new_spr;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void add_dynamic_sprite(int gotSlot, Bitmap *redin, bool hasAlpha) {
|
||||
|
||||
spriteset.SetSprite(gotSlot, redin);
|
||||
|
||||
game.SpriteInfos[gotSlot].Flags = SPF_DYNAMICALLOC;
|
||||
|
||||
if (redin->GetColorDepth() > 8)
|
||||
game.SpriteInfos[gotSlot].Flags |= SPF_HICOLOR;
|
||||
if (redin->GetColorDepth() > 16)
|
||||
game.SpriteInfos[gotSlot].Flags |= SPF_TRUECOLOR;
|
||||
if (hasAlpha)
|
||||
game.SpriteInfos[gotSlot].Flags |= SPF_ALPHACHANNEL;
|
||||
|
||||
game.SpriteInfos[gotSlot].Width = redin->GetWidth();
|
||||
game.SpriteInfos[gotSlot].Height = redin->GetHeight();
|
||||
}
|
||||
|
||||
void free_dynamic_sprite (int gotSlot) {
|
||||
int tt;
|
||||
|
||||
if ((gotSlot < 0) || (gotSlot >= spriteset.GetSpriteSlotCount()))
|
||||
quit("!FreeDynamicSprite: invalid slot number");
|
||||
|
||||
if ((game.SpriteInfos[gotSlot].Flags & SPF_DYNAMICALLOC) == 0)
|
||||
quitprintf("!DeleteSprite: Attempted to free static sprite %d that was not loaded by the script", gotSlot);
|
||||
|
||||
spriteset.RemoveSprite(gotSlot, true);
|
||||
|
||||
game.SpriteInfos[gotSlot].Flags = 0;
|
||||
game.SpriteInfos[gotSlot].Width = 0;
|
||||
game.SpriteInfos[gotSlot].Height = 0;
|
||||
|
||||
// ensure it isn't still on any GUI buttons
|
||||
for (tt = 0; tt < numguibuts; tt++) {
|
||||
if (guibuts[tt].IsDeleted())
|
||||
continue;
|
||||
if (guibuts[tt].Image == gotSlot)
|
||||
guibuts[tt].Image = 0;
|
||||
if (guibuts[tt].CurrentImage == gotSlot)
|
||||
guibuts[tt].CurrentImage = 0;
|
||||
if (guibuts[tt].MouseOverImage == gotSlot)
|
||||
guibuts[tt].MouseOverImage = 0;
|
||||
if (guibuts[tt].PushedImage == gotSlot)
|
||||
guibuts[tt].PushedImage = 0;
|
||||
}
|
||||
|
||||
// force refresh of any object caches using the sprite
|
||||
if (croom != nullptr)
|
||||
{
|
||||
for (tt = 0; tt < croom->numobj; tt++)
|
||||
{
|
||||
if (objs[tt].num == gotSlot)
|
||||
{
|
||||
objs[tt].num = 0;
|
||||
objcache[tt].sppic = -1;
|
||||
}
|
||||
else if (objcache[tt].sppic == gotSlot)
|
||||
objcache[tt].sppic = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script API Functions
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "debug/out.h"
|
||||
#include "script/script_api.h"
|
||||
#include "script/script_runtime.h"
|
||||
|
||||
// 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()
|
||||
{
|
||||
ccAddExternalObjectFunction("DynamicSprite::ChangeCanvasSize^4", Sc_DynamicSprite_ChangeCanvasSize);
|
||||
ccAddExternalObjectFunction("DynamicSprite::CopyTransparencyMask^1", Sc_DynamicSprite_CopyTransparencyMask);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Crop^4", Sc_DynamicSprite_Crop);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Delete", Sc_DynamicSprite_Delete);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Flip^1", Sc_DynamicSprite_Flip);
|
||||
ccAddExternalObjectFunction("DynamicSprite::GetDrawingSurface^0", Sc_DynamicSprite_GetDrawingSurface);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Resize^2", Sc_DynamicSprite_Resize);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Rotate^3", Sc_DynamicSprite_Rotate);
|
||||
ccAddExternalObjectFunction("DynamicSprite::SaveToFile^1", Sc_DynamicSprite_SaveToFile);
|
||||
ccAddExternalObjectFunction("DynamicSprite::Tint^5", Sc_DynamicSprite_Tint);
|
||||
ccAddExternalObjectFunction("DynamicSprite::get_ColorDepth", Sc_DynamicSprite_GetColorDepth);
|
||||
ccAddExternalObjectFunction("DynamicSprite::get_Graphic", Sc_DynamicSprite_GetGraphic);
|
||||
ccAddExternalObjectFunction("DynamicSprite::get_Height", Sc_DynamicSprite_GetHeight);
|
||||
ccAddExternalObjectFunction("DynamicSprite::get_Width", Sc_DynamicSprite_GetWidth);
|
||||
ccAddExternalStaticFunction("DynamicSprite::Create^3", Sc_DynamicSprite_Create);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromBackground", Sc_DynamicSprite_CreateFromBackground);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromDrawingSurface^5", Sc_DynamicSprite_CreateFromDrawingSurface);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromExistingSprite^1", Sc_DynamicSprite_CreateFromExistingSprite_Old);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromExistingSprite^2", Sc_DynamicSprite_CreateFromExistingSprite);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromFile", Sc_DynamicSprite_CreateFromFile);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromSaveGame", Sc_DynamicSprite_CreateFromSaveGame);
|
||||
ccAddExternalStaticFunction("DynamicSprite::CreateFromScreenShot", Sc_DynamicSprite_CreateFromScreenShot);
|
||||
|
||||
/* ----------------------- Registering unsafe exports for plugins -----------------------*/
|
||||
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::ChangeCanvasSize^4", (void*)DynamicSprite_ChangeCanvasSize);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CopyTransparencyMask^1", (void*)DynamicSprite_CopyTransparencyMask);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Crop^4", (void*)DynamicSprite_Crop);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Delete", (void*)DynamicSprite_Delete);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Flip^1", (void*)DynamicSprite_Flip);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::GetDrawingSurface^0", (void*)DynamicSprite_GetDrawingSurface);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Resize^2", (void*)DynamicSprite_Resize);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Rotate^3", (void*)DynamicSprite_Rotate);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::SaveToFile^1", (void*)DynamicSprite_SaveToFile);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Tint^5", (void*)DynamicSprite_Tint);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::get_ColorDepth", (void*)DynamicSprite_GetColorDepth);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::get_Graphic", (void*)DynamicSprite_GetGraphic);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::get_Height", (void*)DynamicSprite_GetHeight);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::get_Width", (void*)DynamicSprite_GetWidth);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::Create^3", (void*)DynamicSprite_Create);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromBackground", (void*)DynamicSprite_CreateFromBackground);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromDrawingSurface^5", (void*)DynamicSprite_CreateFromDrawingSurface);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromExistingSprite^1", (void*)DynamicSprite_CreateFromExistingSprite_Old);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromExistingSprite^2", (void*)DynamicSprite_CreateFromExistingSprite);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromFile", (void*)DynamicSprite_CreateFromFile);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromSaveGame", (void*)DynamicSprite_CreateFromSaveGame);
|
||||
ccAddExternalFunctionForPlugin("DynamicSprite::CreateFromScreenShot", (void*)DynamicSprite_CreateFromScreenShot);
|
||||
}
|
51
engines/ags/engine/ac/dynamicsprite.h
Normal file
51
engines/ags/engine/ac/dynamicsprite.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_AC__DYNAMICSPRITE_H
|
||||
#define __AGS_EE_AC__DYNAMICSPRITE_H
|
||||
|
||||
#include "ac/dynobj/scriptdynamicsprite.h"
|
||||
#include "ac/dynobj/scriptdrawingsurface.h"
|
||||
|
||||
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);
|
||||
|
||||
|
||||
void add_dynamic_sprite(int gotSlot, Common::Bitmap *redin, bool hasAlpha = false);
|
||||
void free_dynamic_sprite (int gotSlot);
|
||||
|
||||
#endif // __AGS_EE_AC__DYNAMICSPRITE_H
|
35
engines/ags/engine/ac/dynobj/all_dynamicclasses.h
Normal file
35
engines/ags/engine/ac/dynobj/all_dynamicclasses.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__ALLDYNAMICCLASSES_H
|
||||
#define __AGS_EE_DYNOBJ__ALLDYNAMICCLASSES_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
#include "ac/dynobj/cc_audiochannel.h"
|
||||
#include "ac/dynobj/cc_audioclip.h"
|
||||
#include "ac/dynobj/cc_character.h"
|
||||
#include "ac/dynobj/cc_dialog.h"
|
||||
#include "ac/dynobj/cc_gui.h"
|
||||
#include "ac/dynobj/cc_guiobject.h"
|
||||
#include "ac/dynobj/cc_hotspot.h"
|
||||
#include "ac/dynobj/cc_inventory.h"
|
||||
#include "ac/dynobj/cc_object.h"
|
||||
#include "ac/dynobj/cc_region.h"
|
||||
|
||||
#include "ac/dynobj/cc_serializer.h"
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__ALLDYNAMICCLASSES_H
|
37
engines/ags/engine/ac/dynobj/all_scriptclasses.h
Normal file
37
engines/ags/engine/ac/dynobj/all_scriptclasses.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__ALLSCRIPTCLASSES_H
|
||||
#define __AGS_EE_DYNOBJ__ALLSCRIPTCLASSES_H
|
||||
|
||||
#include "ac/dynobj/scriptdatetime.h"
|
||||
#include "ac/dynobj/scriptdialog.h"
|
||||
#include "ac/dynobj/scriptdialogoptionsrendering.h"
|
||||
#include "ac/dynobj/scriptdrawingsurface.h"
|
||||
#include "ac/dynobj/scriptdynamicsprite.h"
|
||||
#include "ac/dynobj/scriptgui.h"
|
||||
#include "ac/dynobj/scripthotspot.h"
|
||||
#include "ac/dynobj/scriptinvitem.h"
|
||||
#include "ac/dynobj/scriptmouse.h"
|
||||
#include "ac/dynobj/scriptobject.h"
|
||||
#include "ac/dynobj/scriptoverlay.h"
|
||||
#include "ac/dynobj/scriptregion.h"
|
||||
#include "ac/dynobj/scriptstring.h"
|
||||
#include "ac/dynobj/scriptsystem.h"
|
||||
#include "ac/dynobj/scriptviewframe.h"
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__ALLSCRIPTOBJECTS_H
|
130
engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp
Normal file
130
engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <string.h>
|
||||
#include "core/types.h"
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
#include "ac/common.h" // quit()
|
||||
#include "util/bbop.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
// *** The script serialization routines for built-in types
|
||||
|
||||
int AGSCCDynamicObject::Dispose(const char *address, bool force) {
|
||||
// cannot be removed from memory
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::StartSerialize(char *sbuffer) {
|
||||
bytesSoFar = 0;
|
||||
serbuffer = sbuffer;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::SerializeInt(int val) {
|
||||
char *chptr = &serbuffer[bytesSoFar];
|
||||
int *iptr = (int*)chptr;
|
||||
*iptr = BBOp::Int32FromLE(val);
|
||||
bytesSoFar += 4;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::SerializeFloat(float val) {
|
||||
char *chptr = &serbuffer[bytesSoFar];
|
||||
float *fptr = (float*)chptr;
|
||||
*fptr = BBOp::FloatFromLE(val);
|
||||
bytesSoFar += 4;
|
||||
}
|
||||
|
||||
int AGSCCDynamicObject::EndSerialize() {
|
||||
return bytesSoFar;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::StartUnserialize(const char *sbuffer, int pTotalBytes) {
|
||||
bytesSoFar = 0;
|
||||
totalBytes = pTotalBytes;
|
||||
serbuffer = (char*)sbuffer;
|
||||
}
|
||||
|
||||
int AGSCCDynamicObject::UnserializeInt() {
|
||||
if (bytesSoFar >= totalBytes)
|
||||
quit("Unserialise: internal error: read past EOF");
|
||||
|
||||
char *chptr = &serbuffer[bytesSoFar];
|
||||
bytesSoFar += 4;
|
||||
return BBOp::Int32FromLE(*((int*)chptr));
|
||||
}
|
||||
|
||||
float AGSCCDynamicObject::UnserializeFloat() {
|
||||
if (bytesSoFar >= totalBytes)
|
||||
quit("Unserialise: internal error: read past EOF");
|
||||
|
||||
char *chptr = &serbuffer[bytesSoFar];
|
||||
bytesSoFar += 4;
|
||||
return BBOp::FloatFromLE(*((float*)chptr));
|
||||
}
|
||||
|
||||
const char* AGSCCDynamicObject::GetFieldPtr(const char *address, intptr_t offset)
|
||||
{
|
||||
return address + offset;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::Read(const char *address, intptr_t offset, void *dest, int size)
|
||||
{
|
||||
memcpy(dest, address + offset, size);
|
||||
}
|
||||
|
||||
uint8_t AGSCCDynamicObject::ReadInt8(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(uint8_t*)(address + offset);
|
||||
}
|
||||
|
||||
int16_t AGSCCDynamicObject::ReadInt16(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int16_t*)(address + offset);
|
||||
}
|
||||
|
||||
int32_t AGSCCDynamicObject::ReadInt32(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int32_t*)(address + offset);
|
||||
}
|
||||
|
||||
float AGSCCDynamicObject::ReadFloat(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(float*)(address + offset);
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::Write(const char *address, intptr_t offset, void *src, int size)
|
||||
{
|
||||
memcpy((void*)(address + offset), src, size);
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::WriteInt8(const char *address, intptr_t offset, uint8_t val)
|
||||
{
|
||||
*(uint8_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::WriteInt16(const char *address, intptr_t offset, int16_t val)
|
||||
{
|
||||
*(int16_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::WriteInt32(const char *address, intptr_t offset, int32_t val)
|
||||
{
|
||||
*(int32_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void AGSCCDynamicObject::WriteFloat(const char *address, intptr_t offset, float val)
|
||||
{
|
||||
*(float*)(address + offset) = val;
|
||||
}
|
60
engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h
Normal file
60
engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCDYNAMICOBJECT_H
|
||||
#define __AC_CCDYNAMICOBJECT_H
|
||||
|
||||
#include "ac/dynobj/cc_dynamicobject.h"
|
||||
|
||||
struct AGSCCDynamicObject : ICCDynamicObject {
|
||||
protected:
|
||||
virtual ~AGSCCDynamicObject() = default;
|
||||
public:
|
||||
// default implementation
|
||||
int Dispose(const char *address, bool force) override;
|
||||
|
||||
// TODO: pass savegame format version
|
||||
virtual void Unserialize(int index, const char *serializedData, int dataSize) = 0;
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset
|
||||
const char* GetFieldPtr(const char *address, intptr_t offset) override;
|
||||
void Read(const char *address, intptr_t offset, void *dest, int size) override;
|
||||
uint8_t ReadInt8(const char *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(const char *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(const char *address, intptr_t offset) override;
|
||||
float ReadFloat(const char *address, intptr_t offset) override;
|
||||
void Write(const char *address, intptr_t offset, void *src, int size) override;
|
||||
void WriteInt8(const char *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(const char *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(const char *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(const char *address, intptr_t offset, float val) override;
|
||||
|
||||
protected:
|
||||
// Savegame serialization
|
||||
// TODO: reimplement with the proper memory stream?!
|
||||
int bytesSoFar;
|
||||
int totalBytes;
|
||||
char *serbuffer;
|
||||
|
||||
void StartSerialize(char *sbuffer);
|
||||
void SerializeInt(int val);
|
||||
void SerializeFloat(float val);
|
||||
int EndSerialize();
|
||||
void StartUnserialize(const char *sbuffer, int pTotalBytes);
|
||||
int UnserializeInt();
|
||||
float UnserializeFloat();
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCDYNAMICOBJECT_H
|
36
engines/ags/engine/ac/dynobj/cc_audiochannel.cpp
Normal file
36
engines/ags/engine/ac/dynobj/cc_audiochannel.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_audiochannel.h"
|
||||
#include "ac/dynobj/scriptaudiochannel.h"
|
||||
#include "media/audio/audio_system.h"
|
||||
|
||||
extern ScriptAudioChannel scrAudioChannel[MAX_SOUND_CHANNELS + 1];
|
||||
|
||||
const char *CCAudioChannel::GetType() {
|
||||
return "AudioChannel";
|
||||
}
|
||||
|
||||
int CCAudioChannel::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptAudioChannel *ach = (ScriptAudioChannel*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(ach->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCAudioChannel::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int id = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrAudioChannel[id], this);
|
||||
}
|
29
engines/ags/engine/ac/dynobj/cc_audiochannel.h
Normal file
29
engines/ags/engine/ac/dynobj/cc_audiochannel.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__CCAUDIOCHANNEL_H
|
||||
#define __AGS_EE_DYNOBJ__CCAUDIOCHANNEL_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCAudioChannel final : AGSCCDynamicObject {
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__CCAUDIOCHANNEL_H
|
36
engines/ags/engine/ac/dynobj/cc_audioclip.cpp
Normal file
36
engines/ags/engine/ac/dynobj/cc_audioclip.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_audioclip.h"
|
||||
#include "ac/dynobj/scriptaudioclip.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
|
||||
extern GameSetupStruct game;
|
||||
|
||||
const char *CCAudioClip::GetType() {
|
||||
return "AudioClip";
|
||||
}
|
||||
|
||||
int CCAudioClip::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptAudioClip *ach = (ScriptAudioClip*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(ach->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCAudioClip::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int id = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &game.audioClips[id], this);
|
||||
}
|
29
engines/ags/engine/ac/dynobj/cc_audioclip.h
Normal file
29
engines/ags/engine/ac/dynobj/cc_audioclip.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__CCAUDIOCLIP_H
|
||||
#define __AGS_EE_DYNOBJ__CCAUDIOCLIP_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCAudioClip final : AGSCCDynamicObject {
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__CCAUDIOCLIP_H
|
58
engines/ags/engine/ac/dynobj/cc_character.cpp
Normal file
58
engines/ags/engine/ac/dynobj/cc_character.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_character.h"
|
||||
#include "ac/characterinfo.h"
|
||||
#include "ac/global_character.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "ac/game_version.h"
|
||||
|
||||
extern GameSetupStruct game;
|
||||
|
||||
// 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
|
||||
int CCCharacter::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
CharacterInfo *chaa = (CharacterInfo*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(chaa->index_id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCCharacter::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &game.chars[num], this);
|
||||
}
|
||||
|
||||
void CCCharacter::WriteInt16(const char *address, intptr_t offset, int16_t val)
|
||||
{
|
||||
*(int16_t*)(address + offset) = val;
|
||||
|
||||
// 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 reply on the previous behaviour.
|
||||
if (loaded_game_file_version < kGameVersion_270)
|
||||
{
|
||||
const int invoffset = 112;
|
||||
if (offset >= invoffset && offset < (invoffset + MAX_INV * sizeof(short)))
|
||||
{
|
||||
update_invorder();
|
||||
}
|
||||
}
|
||||
}
|
34
engines/ags/engine/ac/dynobj/cc_character.h
Normal file
34
engines/ags/engine/ac/dynobj/cc_character.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCCHARACTER_H
|
||||
#define __AC_CCCHARACTER_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCCharacter final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
void WriteInt16(const char *address, intptr_t offset, int16_t val) override;
|
||||
};
|
||||
|
||||
#endif // __AC_CCCHARACTER_H
|
38
engines/ags/engine/ac/dynobj/cc_dialog.cpp
Normal file
38
engines/ags/engine/ac/dynobj/cc_dialog.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_dialog.h"
|
||||
#include "ac/dialog.h"
|
||||
#include "ac/dialogtopic.h"
|
||||
#include "ac/gamestructdefines.h"
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCDialog::GetType() {
|
||||
return "Dialog";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCDialog::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptDialog *shh = (ScriptDialog*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCDialog::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrDialog[num], this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_dialog.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_dialog.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCDIALOG_H
|
||||
#define __AC_CCDIALOG_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCDialog final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCDIALOG_H
|
161
engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp
Normal file
161
engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <string.h>
|
||||
#include "cc_dynamicarray.h"
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCDynamicArray::GetType() {
|
||||
return CC_DYNAMIC_ARRAY_TYPE_NAME;
|
||||
}
|
||||
|
||||
int CCDynamicArray::Dispose(const char *address, bool force) {
|
||||
address -= 8;
|
||||
|
||||
// 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)
|
||||
{
|
||||
int *elementCount = (int*)address;
|
||||
if (elementCount[0] & ARRAY_MANAGED_TYPE_FLAG)
|
||||
{
|
||||
elementCount[0] &= ~ARRAY_MANAGED_TYPE_FLAG;
|
||||
for (int i = 0; i < elementCount[0]; i++)
|
||||
{
|
||||
if (elementCount[2 + i] != 0)
|
||||
{
|
||||
ccReleaseObjectReference(elementCount[2 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete address;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCDynamicArray::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
int *sizeInBytes = &((int*)address)[-1];
|
||||
int sizeToWrite = *sizeInBytes + 8;
|
||||
if (sizeToWrite > bufsize)
|
||||
{
|
||||
// buffer not big enough, ask for a bigger one
|
||||
return -sizeToWrite;
|
||||
}
|
||||
memcpy(buffer, address - 8, sizeToWrite);
|
||||
return sizeToWrite;
|
||||
}
|
||||
|
||||
void CCDynamicArray::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
char *newArray = new char[dataSize];
|
||||
memcpy(newArray, serializedData, dataSize);
|
||||
ccRegisterUnserializedObject(index, &newArray[8], this);
|
||||
}
|
||||
|
||||
DynObjectRef CCDynamicArray::Create(int numElements, int elementSize, bool isManagedType)
|
||||
{
|
||||
char *newArray = new char[numElements * elementSize + 8];
|
||||
memset(newArray, 0, numElements * elementSize + 8);
|
||||
int *sizePtr = (int*)newArray;
|
||||
sizePtr[0] = numElements;
|
||||
sizePtr[1] = numElements * elementSize;
|
||||
if (isManagedType)
|
||||
sizePtr[0] |= ARRAY_MANAGED_TYPE_FLAG;
|
||||
void *obj_ptr = &newArray[8];
|
||||
int32_t handle = ccRegisterManagedObject(obj_ptr, this);
|
||||
if (handle == 0)
|
||||
{
|
||||
delete[] newArray;
|
||||
return DynObjectRef(0, nullptr);
|
||||
}
|
||||
return DynObjectRef(handle, obj_ptr);
|
||||
}
|
||||
|
||||
|
||||
const char* CCDynamicArray::GetFieldPtr(const char *address, intptr_t offset)
|
||||
{
|
||||
return address + offset;
|
||||
}
|
||||
|
||||
void CCDynamicArray::Read(const char *address, intptr_t offset, void *dest, int size)
|
||||
{
|
||||
memcpy(dest, address + offset, size);
|
||||
}
|
||||
|
||||
uint8_t CCDynamicArray::ReadInt8(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(uint8_t*)(address + offset);
|
||||
}
|
||||
|
||||
int16_t CCDynamicArray::ReadInt16(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int16_t*)(address + offset);
|
||||
}
|
||||
|
||||
int32_t CCDynamicArray::ReadInt32(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int32_t*)(address + offset);
|
||||
}
|
||||
|
||||
float CCDynamicArray::ReadFloat(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(float*)(address + offset);
|
||||
}
|
||||
|
||||
void CCDynamicArray::Write(const char *address, intptr_t offset, void *src, int size)
|
||||
{
|
||||
memcpy((void*)(address + offset), src, size);
|
||||
}
|
||||
|
||||
void CCDynamicArray::WriteInt8(const char *address, intptr_t offset, uint8_t val)
|
||||
{
|
||||
*(uint8_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void CCDynamicArray::WriteInt16(const char *address, intptr_t offset, int16_t val)
|
||||
{
|
||||
*(int16_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void CCDynamicArray::WriteInt32(const char *address, intptr_t offset, int32_t val)
|
||||
{
|
||||
*(int32_t*)(address + offset) = val;
|
||||
}
|
||||
|
||||
void CCDynamicArray::WriteFloat(const char *address, intptr_t offset, float val)
|
||||
{
|
||||
*(float*)(address + offset) = val;
|
||||
}
|
||||
|
||||
CCDynamicArray globalDynamicArray;
|
||||
|
||||
|
||||
DynObjectRef DynamicArrayHelpers::CreateStringArray(const std::vector<const char*> items)
|
||||
{
|
||||
// NOTE: we need element size of "handle" for array of managed pointers
|
||||
DynObjectRef arr = globalDynamicArray.Create(items.size(), sizeof(int32_t), true);
|
||||
if (!arr.second)
|
||||
return arr;
|
||||
// Create script strings and put handles into array
|
||||
int32_t *slots = static_cast<int32_t*>(arr.second);
|
||||
for (auto s : items)
|
||||
{
|
||||
DynObjectRef str = stringClassImpl->CreateString(s);
|
||||
*(slots++) = str.first;
|
||||
}
|
||||
return arr;
|
||||
}
|
58
engines/ags/engine/ac/dynobj/cc_dynamicarray.h
Normal file
58
engines/ags/engine/ac/dynobj/cc_dynamicarray.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __CC_DYNAMICARRAY_H
|
||||
#define __CC_DYNAMICARRAY_H
|
||||
|
||||
#include <vector>
|
||||
#include "ac/dynobj/cc_dynamicobject.h" // ICCDynamicObject
|
||||
|
||||
#define CC_DYNAMIC_ARRAY_TYPE_NAME "CCDynamicArray"
|
||||
#define ARRAY_MANAGED_TYPE_FLAG 0x80000000
|
||||
|
||||
struct CCDynamicArray final : ICCDynamicObject
|
||||
{
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
int Dispose(const char *address, bool force) override;
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
virtual void Unserialize(int index, const char *serializedData, int dataSize);
|
||||
// Create managed array object and return a pointer to the beginning of a buffer
|
||||
DynObjectRef Create(int numElements, int elementSize, bool isManagedType);
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset
|
||||
const char* GetFieldPtr(const char *address, intptr_t offset) override;
|
||||
void Read(const char *address, intptr_t offset, void *dest, int size) override;
|
||||
uint8_t ReadInt8(const char *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(const char *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(const char *address, intptr_t offset) override;
|
||||
float ReadFloat(const char *address, intptr_t offset) override;
|
||||
void Write(const char *address, intptr_t offset, void *src, int size) override;
|
||||
void WriteInt8(const char *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(const char *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(const char *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(const char *address, intptr_t offset, float val) override;
|
||||
};
|
||||
|
||||
extern CCDynamicArray globalDynamicArray;
|
||||
|
||||
// Helper functions for setting up dynamic arrays.
|
||||
namespace DynamicArrayHelpers
|
||||
{
|
||||
// Create array of managed strings
|
||||
DynObjectRef CreateStringArray(const std::vector<const char*>);
|
||||
};
|
||||
|
||||
#endif
|
151
engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp
Normal file
151
engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// 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++.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
//#define DEBUG_MANAGED_OBJECTS
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ac/dynobj/cc_dynamicobject.h"
|
||||
#include "ac/dynobj/managedobjectpool.h"
|
||||
#include "debug/out.h"
|
||||
#include "script/cc_error.h"
|
||||
#include "script/script_common.h"
|
||||
#include "util/stream.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
ICCStringClass *stringClassImpl = nullptr;
|
||||
|
||||
// set the class that will be used for dynamic strings
|
||||
void ccSetStringClassImpl(ICCStringClass *theClass) {
|
||||
stringClassImpl = theClass;
|
||||
}
|
||||
|
||||
// register a memory handle for the object and allow script
|
||||
// pointers to point to it
|
||||
int32_t ccRegisterManagedObject(const void *object, ICCDynamicObject *callback, bool plugin_object) {
|
||||
int32_t handl = pool.AddObject((const char*)object, callback, plugin_object);
|
||||
|
||||
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, const void *object, ICCDynamicObject *callback, bool plugin_object) {
|
||||
return pool.AddUnserializedObject((const char*)object, callback, plugin_object, index);
|
||||
}
|
||||
|
||||
// unregister a particular object
|
||||
int ccUnRegisterManagedObject(const void *object) {
|
||||
return pool.RemoveObject((const char*)object);
|
||||
}
|
||||
|
||||
// remove all registered objects
|
||||
void ccUnregisterAllObjects() {
|
||||
pool.reset();
|
||||
}
|
||||
|
||||
// serialize all objects to disk
|
||||
void ccSerializeAllObjects(Stream *out) {
|
||||
pool.WriteToDisk(out);
|
||||
}
|
||||
|
||||
// un-serialise all objects (will remove all currently registered ones)
|
||||
int ccUnserializeAllObjects(Stream *in, ICCObjectReader *callback) {
|
||||
return pool.ReadFromDisk(in, callback);
|
||||
}
|
||||
|
||||
// dispose the object if RefCount==0
|
||||
void ccAttemptDisposeObject(int32_t handle) {
|
||||
pool.CheckDispose(handle);
|
||||
}
|
||||
|
||||
// translate between object handles and memory addresses
|
||||
int32_t ccGetObjectHandleFromAddress(const char *address) {
|
||||
// set to null
|
||||
if (address == nullptr)
|
||||
return 0;
|
||||
|
||||
int32_t handl = pool.AddressToHandle(address);
|
||||
|
||||
ManagedObjectLog("Line %d WritePtr: %08X to %d", 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;
|
||||
}
|
||||
|
||||
const char *ccGetObjectAddressFromHandle(int32_t handle) {
|
||||
if (handle == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
const char *addr = pool.HandleToAddress(handle);
|
||||
|
||||
ManagedObjectLog("Line %d ReadPtr: %d to %08X", 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, ICCDynamicObject *&manager)
|
||||
{
|
||||
if (handle == 0) {
|
||||
object = nullptr;
|
||||
manager = nullptr;
|
||||
return kScValUndefined;
|
||||
}
|
||||
ScriptValueType obj_type = 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 pool.AddRef(handle);
|
||||
}
|
||||
|
||||
int ccReleaseObjectReference(int32_t handle) {
|
||||
if (handle == 0)
|
||||
return 0;
|
||||
|
||||
if (pool.HandleToAddress(handle) == nullptr) {
|
||||
cc_error("Error releasing pointer: invalid handle %d", handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pool.SubRef(handle);
|
||||
}
|
116
engines/ags/engine/ac/dynobj/cc_dynamicobject.h
Normal file
116
engines/ags/engine/ac/dynobj/cc_dynamicobject.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// Managed script object interface.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __CC_DYNAMICOBJECT_H
|
||||
#define __CC_DYNAMICOBJECT_H
|
||||
|
||||
#include <utility>
|
||||
#include "core/types.h"
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS { namespace Common { class Stream; } }
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
// A pair of managed handle and abstract object pointer
|
||||
typedef std::pair<int32_t, void*> DynObjectRef;
|
||||
|
||||
|
||||
// OBJECT-BASED SCRIPTING RUNTIME FUNCTIONS
|
||||
// interface
|
||||
struct ICCDynamicObject {
|
||||
// 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(const char *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(const char *address, char *buffer, int bufsize) = 0;
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset.
|
||||
// WARNING: following were never a part of plugin API, therefore these methods
|
||||
// should **never** be called for kScValPluginObject script objects!
|
||||
//
|
||||
// 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 const char* GetFieldPtr(const char *address, intptr_t offset) = 0;
|
||||
virtual void Read(const char *address, intptr_t offset, void *dest, int size) = 0;
|
||||
virtual uint8_t ReadInt8(const char *address, intptr_t offset) = 0;
|
||||
virtual int16_t ReadInt16(const char *address, intptr_t offset) = 0;
|
||||
virtual int32_t ReadInt32(const char *address, intptr_t offset) = 0;
|
||||
virtual float ReadFloat(const char *address, intptr_t offset) = 0;
|
||||
virtual void Write(const char *address, intptr_t offset, void *src, int size) = 0;
|
||||
virtual void WriteInt8(const char *address, intptr_t offset, uint8_t val) = 0;
|
||||
virtual void WriteInt16(const char *address, intptr_t offset, int16_t val) = 0;
|
||||
virtual void WriteInt32(const char *address, intptr_t offset, int32_t val) = 0;
|
||||
virtual void WriteFloat(const char *address, intptr_t offset, float val) = 0;
|
||||
|
||||
protected:
|
||||
ICCDynamicObject() = default;
|
||||
~ICCDynamicObject() = default;
|
||||
};
|
||||
|
||||
struct ICCObjectReader {
|
||||
// TODO: pass savegame format version
|
||||
virtual void Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) = 0;
|
||||
};
|
||||
struct ICCStringClass {
|
||||
virtual DynObjectRef CreateString(const char *fromText) = 0;
|
||||
};
|
||||
|
||||
// set the class that will be used for dynamic strings
|
||||
extern void ccSetStringClassImpl(ICCStringClass *theClass);
|
||||
// register a memory handle for the object and allow script
|
||||
// pointers to point to it
|
||||
extern int32_t ccRegisterManagedObject(const void *object, ICCDynamicObject *, bool plugin_object = false);
|
||||
// register a de-serialized object
|
||||
extern int32_t ccRegisterUnserializedObject(int index, const void *object, ICCDynamicObject *, bool plugin_object = false);
|
||||
// unregister a particular object
|
||||
extern int ccUnRegisterManagedObject(const void *object);
|
||||
// remove all registered objects
|
||||
extern void ccUnregisterAllObjects();
|
||||
// serialize all objects to disk
|
||||
extern void ccSerializeAllObjects(Common::Stream *out);
|
||||
// un-serialise all objects (will remove all currently registered ones)
|
||||
extern int ccUnserializeAllObjects(Common::Stream *in, ICCObjectReader *callback);
|
||||
// dispose the object if RefCount==0
|
||||
extern void ccAttemptDisposeObject(int32_t handle);
|
||||
// translate between object handles and memory addresses
|
||||
extern int32_t ccGetObjectHandleFromAddress(const char *address);
|
||||
// TODO: not sure if it makes any sense whatsoever to use "const char*"
|
||||
// in these functions, might as well change to char* or just void*.
|
||||
extern const char *ccGetObjectAddressFromHandle(int32_t handle);
|
||||
|
||||
extern int ccAddObjectReference(int32_t handle);
|
||||
extern int ccReleaseObjectReference(int32_t handle);
|
||||
|
||||
extern ICCStringClass *stringClassImpl;
|
||||
|
||||
#endif // __CC_DYNAMICOBJECT_H
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef ADDR_AND_MANAGER_H
|
||||
#define ADDR_AND_MANAGER_H
|
||||
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "ac/dynobj/cc_dynamicobject.h"
|
||||
|
||||
extern ScriptValueType ccGetObjectAddressAndManagerFromHandle(
|
||||
int32_t handle, void *&object, ICCDynamicObject *&manager);
|
||||
|
||||
#endif
|
||||
|
38
engines/ags/engine/ac/dynobj/cc_gui.cpp
Normal file
38
engines/ags/engine/ac/dynobj/cc_gui.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_gui.h"
|
||||
#include "ac/dynobj/scriptgui.h"
|
||||
|
||||
extern ScriptGUI *scrGui;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCGUI::GetType() {
|
||||
return "GUI";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCGUI::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptGUI *shh = (ScriptGUI*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCGUI::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrGui[num], this);
|
||||
}
|
32
engines/ags/engine/ac/dynobj/cc_gui.h
Normal file
32
engines/ags/engine/ac/dynobj/cc_gui.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCGUI_H
|
||||
#define __AC_CCGUI_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCGUI final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
};
|
||||
|
||||
#endif // __AC_CCGUI_H
|
42
engines/ags/engine/ac/dynobj/cc_guiobject.cpp
Normal file
42
engines/ags/engine/ac/dynobj/cc_guiobject.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_guiobject.h"
|
||||
#include "ac/dynobj/scriptgui.h"
|
||||
#include "gui/guimain.h"
|
||||
#include "gui/guiobject.h"
|
||||
|
||||
using AGS::Common::GUIObject;
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCGUIObject::GetType() {
|
||||
return "GUIObject";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCGUIObject::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
GUIObject *guio = (GUIObject*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(guio->ParentId);
|
||||
SerializeInt(guio->Id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCGUIObject::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int guinum = UnserializeInt();
|
||||
int objnum = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, guis[guinum].GetControl(objnum), this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_guiobject.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_guiobject.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCGUIOBJECT_H
|
||||
#define __AC_CCGUIOBJECT_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCGUIObject final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCGUIOBJECT_H
|
40
engines/ags/engine/ac/dynobj/cc_hotspot.cpp
Normal file
40
engines/ags/engine/ac/dynobj/cc_hotspot.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_hotspot.h"
|
||||
#include "ac/dynobj/scripthotspot.h"
|
||||
#include "ac/common_defines.h"
|
||||
#include "game/roomstruct.h"
|
||||
|
||||
extern ScriptHotspot scrHotspot[MAX_ROOM_HOTSPOTS];
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCHotspot::GetType() {
|
||||
return "Hotspot";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCHotspot::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptHotspot *shh = (ScriptHotspot*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCHotspot::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrHotspot[num], this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_hotspot.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_hotspot.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCHOTSPOT_H
|
||||
#define __AC_CCHOTSPOT_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCHotspot final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCHOTSPOT_H
|
39
engines/ags/engine/ac/dynobj/cc_inventory.cpp
Normal file
39
engines/ags/engine/ac/dynobj/cc_inventory.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_inventory.h"
|
||||
#include "ac/dynobj/scriptinvitem.h"
|
||||
#include "ac/characterinfo.h"
|
||||
|
||||
extern ScriptInvItem scrInv[MAX_INV];
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCInventory::GetType() {
|
||||
return "Inventory";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCInventory::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptInvItem *shh = (ScriptInvItem*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCInventory::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrInv[num], this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_inventory.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_inventory.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCINVENTORY_H
|
||||
#define __AC_CCINVENTORY_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCInventory final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCINVENTORY_H
|
40
engines/ags/engine/ac/dynobj/cc_object.cpp
Normal file
40
engines/ags/engine/ac/dynobj/cc_object.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_object.h"
|
||||
#include "ac/dynobj/scriptobject.h"
|
||||
#include "ac/common_defines.h"
|
||||
#include "game/roomstruct.h"
|
||||
|
||||
extern ScriptObject scrObj[MAX_ROOM_OBJECTS];
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCObject::GetType() {
|
||||
return "Object";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCObject::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptObject *shh = (ScriptObject*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCObject::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrObj[num], this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_object.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_object.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCOBJECT_H
|
||||
#define __AC_CCOBJECT_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCObject final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCOBJECT_H
|
40
engines/ags/engine/ac/dynobj/cc_region.cpp
Normal file
40
engines/ags/engine/ac/dynobj/cc_region.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/cc_region.h"
|
||||
#include "ac/dynobj/scriptregion.h"
|
||||
#include "ac/common_defines.h"
|
||||
#include "game/roomstruct.h"
|
||||
|
||||
extern ScriptRegion scrRegion[MAX_ROOM_REGIONS];
|
||||
|
||||
// return the type name of the object
|
||||
const char *CCRegion::GetType() {
|
||||
return "Region";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int CCRegion::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
ScriptRegion *shh = (ScriptRegion*)address;
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(shh->id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void CCRegion::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int num = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, &scrRegion[num], this);
|
||||
}
|
33
engines/ags/engine/ac/dynobj/cc_region.h
Normal file
33
engines/ags/engine/ac/dynobj/cc_region.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_CCREGION_H
|
||||
#define __AC_CCREGION_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct CCRegion final : AGSCCDynamicObject {
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // __AC_CCREGION_H
|
144
engines/ags/engine/ac/dynobj/cc_serializer.cpp
Normal file
144
engines/ags/engine/ac/dynobj/cc_serializer.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <string.h>
|
||||
#include "ac/dynobj/cc_serializer.h"
|
||||
#include "ac/dynobj/all_dynamicclasses.h"
|
||||
#include "ac/dynobj/all_scriptclasses.h"
|
||||
#include "ac/dynobj/scriptcamera.h"
|
||||
#include "ac/dynobj/scriptcontainers.h"
|
||||
#include "ac/dynobj/scriptfile.h"
|
||||
#include "ac/dynobj/scriptuserobject.h"
|
||||
#include "ac/dynobj/scriptviewport.h"
|
||||
#include "ac/game.h"
|
||||
#include "debug/debug_log.h"
|
||||
#include "plugin/agsplugin.h"
|
||||
#include "plugin/pluginobjectreader.h"
|
||||
|
||||
extern CCGUIObject ccDynamicGUIObject;
|
||||
extern CCCharacter ccDynamicCharacter;
|
||||
extern CCHotspot ccDynamicHotspot;
|
||||
extern CCRegion ccDynamicRegion;
|
||||
extern CCInventory ccDynamicInv;
|
||||
extern CCGUI ccDynamicGUI;
|
||||
extern CCObject ccDynamicObject;
|
||||
extern CCDialog ccDynamicDialog;
|
||||
extern ScriptDrawingSurface* dialogOptionsRenderingSurface;
|
||||
extern ScriptDialogOptionsRendering ccDialogOptionsRendering;
|
||||
extern PluginObjectReader pluginReaders[MAX_PLUGIN_OBJECT_READERS];
|
||||
extern int numPluginReaders;
|
||||
|
||||
// *** De-serialization of script objects
|
||||
|
||||
|
||||
|
||||
void AGSDeSerializer::Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) {
|
||||
if (strcmp(objectType, "GUIObject") == 0) {
|
||||
ccDynamicGUIObject.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Character") == 0) {
|
||||
ccDynamicCharacter.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Hotspot") == 0) {
|
||||
ccDynamicHotspot.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Region") == 0) {
|
||||
ccDynamicRegion.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Inventory") == 0) {
|
||||
ccDynamicInv.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Dialog") == 0) {
|
||||
ccDynamicDialog.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "GUI") == 0) {
|
||||
ccDynamicGUI.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Object") == 0) {
|
||||
ccDynamicObject.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "String") == 0) {
|
||||
ScriptString *scf = new ScriptString();
|
||||
scf->Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
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, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "DateTime") == 0) {
|
||||
ScriptDateTime *scf = new ScriptDateTime();
|
||||
scf->Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "ViewFrame") == 0) {
|
||||
ScriptViewFrame *scf = new ScriptViewFrame();
|
||||
scf->Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "DynamicSprite") == 0) {
|
||||
ScriptDynamicSprite *scf = new ScriptDynamicSprite();
|
||||
scf->Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "DrawingSurface") == 0) {
|
||||
ScriptDrawingSurface *sds = new ScriptDrawingSurface();
|
||||
sds->Unserialize(index, serializedData, dataSize);
|
||||
|
||||
if (sds->isLinkedBitmapOnly)
|
||||
{
|
||||
dialogOptionsRenderingSurface = sds;
|
||||
}
|
||||
}
|
||||
else if (strcmp(objectType, "DialogOptionsRendering") == 0)
|
||||
{
|
||||
ccDialogOptionsRendering.Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "StringDictionary") == 0)
|
||||
{
|
||||
Dict_Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "StringSet") == 0)
|
||||
{
|
||||
Set_Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Viewport2") == 0)
|
||||
{
|
||||
Viewport_Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "Camera2") == 0)
|
||||
{
|
||||
Camera_Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (strcmp(objectType, "UserObject") == 0) {
|
||||
ScriptUserObject *suo = new ScriptUserObject();
|
||||
suo->Unserialize(index, serializedData, dataSize);
|
||||
}
|
||||
else if (!unserialize_audio_script_object(index, objectType, serializedData, dataSize))
|
||||
{
|
||||
// check if the type is read by a plugin
|
||||
for (int ii = 0; ii < numPluginReaders; ii++) {
|
||||
if (strcmp(objectType, pluginReaders[ii].type) == 0) {
|
||||
pluginReaders[ii].reader->Unserialize(index, serializedData, dataSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
quitprintf("Unserialise: unknown object type: '%s'", objectType);
|
||||
}
|
||||
}
|
||||
|
||||
AGSDeSerializer ccUnserializer;
|
||||
|
27
engines/ags/engine/ac/dynobj/cc_serializer.h
Normal file
27
engines/ags/engine/ac/dynobj/cc_serializer.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SERIALIZER_H
|
||||
#define __AC_SERIALIZER_H
|
||||
|
||||
#include "ac/dynobj/cc_dynamicobject.h"
|
||||
|
||||
struct AGSDeSerializer : ICCObjectReader {
|
||||
|
||||
void Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) override;
|
||||
};
|
||||
|
||||
extern AGSDeSerializer ccUnserializer;
|
||||
|
||||
#endif // __AC_SERIALIZER_H
|
322
engines/ags/engine/ac/dynobj/managedobjectpool.cpp
Normal file
322
engines/ags/engine/ac/dynobj/managedobjectpool.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include "ac/dynobj/managedobjectpool.h"
|
||||
#include "ac/dynobj/cc_dynamicarray.h" // globalDynamicArray, constants
|
||||
#include "debug/out.h"
|
||||
#include "util/string_utils.h" // fputstring, etc
|
||||
#include "script/cc_error.h"
|
||||
#include "script/script_common.h"
|
||||
#include "util/stream.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
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) {
|
||||
if (!o.isUsed()) { return 1; } // already removed
|
||||
|
||||
bool canBeRemovedFromPool = o.callback->Dispose(o.addr, force) != 0;
|
||||
if (!(canBeRemovedFromPool || force)) { return 0; }
|
||||
|
||||
auto handle = o.handle;
|
||||
available_ids.push(o.handle);
|
||||
|
||||
handleByAddress.erase(o.addr);
|
||||
o = ManagedObject();
|
||||
|
||||
ManagedObjectLog("Line %d Disposed managed object handle=%d", currentline, handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t ManagedObjectPool::AddRef(int32_t handle) {
|
||||
if (handle < 0 || (size_t)handle >= objects.size()) { return 0; }
|
||||
auto & o = objects[handle];
|
||||
if (!o.isUsed()) { return 0; }
|
||||
|
||||
o.refCount += 1;
|
||||
ManagedObjectLog("Line %d AddRef: handle=%d new refcount=%d", currentline, o.handle, o.refCount);
|
||||
return o.refCount;
|
||||
}
|
||||
|
||||
int ManagedObjectPool::CheckDispose(int32_t handle) {
|
||||
if (handle < 0 || (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 < 0 || (size_t)handle >= objects.size()) { return 0; }
|
||||
auto & o = objects[handle];
|
||||
if (!o.isUsed()) { return 0; }
|
||||
|
||||
o.refCount--;
|
||||
auto newRefCount = o.refCount;
|
||||
auto canBeDisposed = (o.addr != disableDisposeForObject);
|
||||
if (canBeDisposed) {
|
||||
CheckDispose(handle);
|
||||
}
|
||||
// object could be removed at this point, don't use any values.
|
||||
ManagedObjectLog("Line %d SubRef: handle=%d new refcount=%d canBeDisposed=%d", currentline, handle, newRefCount, canBeDisposed);
|
||||
return newRefCount;
|
||||
}
|
||||
|
||||
int32_t ManagedObjectPool::AddressToHandle(const char *addr) {
|
||||
if (addr == nullptr) { return 0; }
|
||||
auto it = handleByAddress.find(addr);
|
||||
if (it == handleByAddress.end()) { return 0; }
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// this function is called often (whenever a pointer is used)
|
||||
const char* ManagedObjectPool::HandleToAddress(int32_t handle) {
|
||||
if (handle < 0 || (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, ICCDynamicObject *&manager) {
|
||||
if (handle < 0 || (size_t)handle >= objects.size()) { return kScValUndefined; }
|
||||
auto & o = objects[handle];
|
||||
if (!o.isUsed()) { return kScValUndefined; }
|
||||
|
||||
object = (void *)o.addr; // WARNING: This strips the const from the char* pointer.
|
||||
manager = o.callback;
|
||||
return o.obj_type;
|
||||
}
|
||||
|
||||
int ManagedObjectPool::RemoveObject(const char *address) {
|
||||
if (address == nullptr) { return 0; }
|
||||
auto it = handleByAddress.find(address);
|
||||
if (it == handleByAddress.end()) { return 0; }
|
||||
|
||||
auto & o = objects[it->second];
|
||||
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::AddObject(const char *address, ICCDynamicObject *callback, bool plugin_object)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
auto & o = objects[handle];
|
||||
if (o.isUsed()) { cc_error("used: %d", handle); return 0; }
|
||||
|
||||
o = ManagedObject(plugin_object ? kScValPluginObject : kScValDynamicObject, handle, address, callback);
|
||||
|
||||
handleByAddress.insert({address, o.handle});
|
||||
objectCreationCounter++;
|
||||
ManagedObjectLog("Allocated managed object handle=%d, type=%s", handle, callback->GetType());
|
||||
return o.handle;
|
||||
}
|
||||
|
||||
|
||||
int ManagedObjectPool::AddUnserializedObject(const char *address, ICCDynamicObject *callback, bool plugin_object, int handle)
|
||||
{
|
||||
if (handle < 0) { cc_error("Attempt to assign invalid handle: %d", handle); return 0; }
|
||||
if ((size_t)handle >= objects.size()) {
|
||||
objects.resize(handle + 1024, ManagedObject());
|
||||
}
|
||||
|
||||
auto & o = objects[handle];
|
||||
if (o.isUsed()) { cc_error("bad save. used: %d", o.handle); return 0; }
|
||||
|
||||
o = ManagedObject(plugin_object ? kScValPluginObject : kScValDynamicObject, handle, address, callback);
|
||||
|
||||
handleByAddress.insert({address, o.handle});
|
||||
ManagedObjectLog("Allocated unserialized managed object handle=%d, type=%s", o.handle, callback->GetType());
|
||||
return o.handle;
|
||||
}
|
||||
|
||||
void ManagedObjectPool::WriteToDisk(Stream *out) {
|
||||
|
||||
// use this opportunity to clean up any non-referenced pointers
|
||||
RunGarbageCollection();
|
||||
|
||||
std::vector<char> 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((char*)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, ICCObjectReader *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);
|
||||
if (strcmp(typeNameBuffer, CC_DYNAMIC_ARRAY_TYPE_NAME) == 0) {
|
||||
globalDynamicArray.Unserialize(i, &serializeBuffer.front(), numBytes);
|
||||
} else {
|
||||
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);
|
||||
if (strcmp(typeNameBuffer, CC_DYNAMIC_ARRAY_TYPE_NAME) == 0) {
|
||||
globalDynamicArray.Unserialize(handle, &serializeBuffer.front(), numBytes);
|
||||
} else {
|
||||
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)
|
||||
while (!available_ids.empty()) { available_ids.pop(); }
|
||||
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);
|
||||
}
|
||||
while (!available_ids.empty()) { available_ids.pop(); }
|
||||
nextHandle = 1;
|
||||
}
|
||||
|
||||
ManagedObjectPool::ManagedObjectPool() : objectCreationCounter(0), nextHandle(1), available_ids(), objects(RESERVED_SIZE, ManagedObject()), handleByAddress() {
|
||||
handleByAddress.reserve(RESERVED_SIZE);
|
||||
}
|
||||
|
||||
ManagedObjectPool pool;
|
88
engines/ags/engine/ac/dynobj/managedobjectpool.h
Normal file
88
engines/ags/engine/ac/dynobj/managedobjectpool.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __CC_MANAGEDOBJECTPOOL_H
|
||||
#define __CC_MANAGEDOBJECTPOOL_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "script/runtimescriptvalue.h"
|
||||
#include "ac/dynobj/cc_dynamicobject.h" // ICCDynamicObject
|
||||
|
||||
namespace AGS { namespace Common { class Stream; }}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
struct ManagedObjectPool final {
|
||||
private:
|
||||
// TODO: find out if we can make handle size_t
|
||||
struct ManagedObject {
|
||||
ScriptValueType obj_type;
|
||||
int32_t handle;
|
||||
// TODO: this makes no sense having this as "const char*",
|
||||
// void* will be proper (and in all related functions)
|
||||
const char *addr;
|
||||
ICCDynamicObject *callback;
|
||||
int refCount;
|
||||
|
||||
bool isUsed() const { return obj_type != kScValUndefined; }
|
||||
|
||||
ManagedObject()
|
||||
: obj_type(kScValUndefined), handle(0), addr(nullptr), callback(nullptr), refCount(0) {}
|
||||
ManagedObject(ScriptValueType obj_type, int32_t handle, const char *addr, ICCDynamicObject * callback)
|
||||
: obj_type(obj_type), handle(handle), addr(addr), callback(callback), 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<const char *, int32_t> handleByAddress;
|
||||
|
||||
void Init(int32_t theHandle, const char *theAddress, ICCDynamicObject *theCallback, ScriptValueType objType);
|
||||
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(const char *addr);
|
||||
const char* HandleToAddress(int32_t handle);
|
||||
ScriptValueType HandleToAddressAndManager(int32_t handle, void *&object, ICCDynamicObject *&manager);
|
||||
int RemoveObject(const char *address);
|
||||
void RunGarbageCollectionIfAppropriate();
|
||||
int AddObject(const char *address, ICCDynamicObject *callback, bool plugin_object);
|
||||
int AddUnserializedObject(const char *address, ICCDynamicObject *callback, bool plugin_object, int handle);
|
||||
void WriteToDisk(Common::Stream *out);
|
||||
int ReadFromDisk(Common::Stream *in, ICCObjectReader *reader);
|
||||
void reset();
|
||||
ManagedObjectPool();
|
||||
|
||||
const char* disableDisposeForObject {nullptr};
|
||||
};
|
||||
|
||||
extern ManagedObjectPool pool;
|
||||
|
||||
#ifdef DEBUG_MANAGED_OBJECTS
|
||||
#define ManagedObjectLog(...) Debug::Printf(kDbgGroup_ManObj, kDbgMsg_Debug, __VA_ARGS__)
|
||||
#else
|
||||
#define ManagedObjectLog(...)
|
||||
#endif
|
||||
|
||||
#endif // __CC_MANAGEDOBJECTPOOL_H
|
27
engines/ags/engine/ac/dynobj/scriptaudiochannel.h
Normal file
27
engines/ags/engine/ac/dynobj/scriptaudiochannel.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
|
||||
|
||||
struct ScriptAudioChannel
|
||||
{
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
|
64
engines/ags/engine/ac/dynobj/scriptcamera.cpp
Normal file
64
engines/ags/engine/ac/dynobj/scriptcamera.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptcamera.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "util/bbop.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
ScriptCamera::ScriptCamera(int id) : _id(id) {}
|
||||
|
||||
const char *ScriptCamera::GetType()
|
||||
{
|
||||
return "Camera2";
|
||||
}
|
||||
|
||||
int ScriptCamera::Dispose(const char *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;
|
||||
}
|
||||
|
||||
int ScriptCamera::Serialize(const char *address, char *buffer, int bufsize)
|
||||
{
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(_id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptCamera::Unserialize(int index, const char *serializedData, int dataSize)
|
||||
{
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
_id = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptCamera *Camera_Unserialize(int handle, const char *serializedData, int dataSize)
|
||||
{
|
||||
// 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 = BBOp::Int32FromLE(*((int*)serializedData));
|
||||
if (id >= 0)
|
||||
{
|
||||
auto scam = play.RegisterRoomCamera(id, handle);
|
||||
if (scam)
|
||||
return scam;
|
||||
}
|
||||
return new ScriptCamera(-1); // make invalid reference
|
||||
}
|
44
engines/ags/engine/ac/dynobj/scriptcamera.h
Normal file
44
engines/ags/engine/ac/dynobj/scriptcamera.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTCAMERA_H
|
||||
#define __AC_SCRIPTCAMERA_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
// 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(const char *address, bool force) override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
private:
|
||||
int _id = -1; // index of camera in the game state array
|
||||
};
|
||||
|
||||
// Unserialize camera from the memory stream
|
||||
ScriptCamera *Camera_Unserialize(int handle, const char *serializedData, int dataSize);
|
||||
|
||||
#endif // __AC_SCRIPTCAMERA_H
|
29
engines/ags/engine/ac/dynobj/scriptcontainers.h
Normal file
29
engines/ags/engine/ac/dynobj/scriptcontainers.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AC_SCRIPTCONTAINERS_H
|
||||
#define __AC_SCRIPTCONTAINERS_H
|
||||
|
||||
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, const char *serializedData, int dataSize);
|
||||
// Create and register new set
|
||||
ScriptSetBase *Set_Create(bool sorted, bool case_sensitive);
|
||||
// Unserialize set from the memory stream
|
||||
ScriptSetBase *Set_Unserialize(int index, const char *serializedData, int dataSize);
|
||||
|
||||
#endif // __AC_SCRIPTCONTAINERS_H
|
55
engines/ags/engine/ac/dynobj/scriptdatetime.cpp
Normal file
55
engines/ags/engine/ac/dynobj/scriptdatetime.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptdatetime.h"
|
||||
|
||||
int ScriptDateTime::Dispose(const char *address, bool force) {
|
||||
// always dispose a DateTime
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDateTime::GetType() {
|
||||
return "DateTime";
|
||||
}
|
||||
|
||||
int ScriptDateTime::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(year);
|
||||
SerializeInt(month);
|
||||
SerializeInt(day);
|
||||
SerializeInt(hour);
|
||||
SerializeInt(minute);
|
||||
SerializeInt(second);
|
||||
SerializeInt(rawUnixTime);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptDateTime::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
year = UnserializeInt();
|
||||
month = UnserializeInt();
|
||||
day = UnserializeInt();
|
||||
hour = UnserializeInt();
|
||||
minute = UnserializeInt();
|
||||
second = UnserializeInt();
|
||||
rawUnixTime = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDateTime::ScriptDateTime() {
|
||||
year = month = day = 0;
|
||||
hour = minute = second = 0;
|
||||
rawUnixTime = 0;
|
||||
}
|
36
engines/ags/engine/ac/dynobj/scriptdatetime.h
Normal file
36
engines/ags/engine/ac/dynobj/scriptdatetime.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTDATETIME_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTDATETIME_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptDateTime final : AGSCCDynamicObject {
|
||||
int year, month, day;
|
||||
int hour, minute, second;
|
||||
int rawUnixTime;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
ScriptDateTime();
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTDATETIME_H
|
26
engines/ags/engine/ac/dynobj/scriptdialog.h
Normal file
26
engines/ags/engine/ac/dynobj/scriptdialog.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTDIALOG_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTDIALOG_H
|
||||
|
||||
struct ScriptDialog {
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTDIALOG_H
|
|
@ -0,0 +1,53 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptdialogoptionsrendering.h"
|
||||
|
||||
// return the type name of the object
|
||||
const char *ScriptDialogOptionsRendering::GetType() {
|
||||
return "DialogOptionsRendering";
|
||||
}
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int ScriptDialogOptionsRendering::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScriptDialogOptionsRendering::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
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();
|
||||
}
|
47
engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h
Normal file
47
engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTDIALOGOPTIONSRENDERING_H
|
||||
#define __AC_SCRIPTDIALOGOPTIONSRENDERING_H
|
||||
|
||||
#include "ac/dynobj/scriptdrawingsurface.h"
|
||||
|
||||
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;
|
||||
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
void Reset();
|
||||
|
||||
ScriptDialogOptionsRendering();
|
||||
};
|
||||
|
||||
|
||||
#endif // __AC_SCRIPTDIALOGOPTIONSRENDERING_H
|
50
engines/ags/engine/ac/dynobj/scriptdict.cpp
Normal file
50
engines/ags/engine/ac/dynobj/scriptdict.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
#include "ac/dynobj/scriptdict.h"
|
||||
|
||||
int ScriptDictBase::Dispose(const char *address, bool force)
|
||||
{
|
||||
Clear();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDictBase::GetType()
|
||||
{
|
||||
return "StringDictionary";
|
||||
}
|
||||
|
||||
int ScriptDictBase::Serialize(const char *address, char *buffer, int bufsize)
|
||||
{
|
||||
size_t total_sz = CalcSerializeSize() + sizeof(int32_t) * 2;
|
||||
if (bufsize < 0 || total_sz >(size_t)bufsize)
|
||||
{
|
||||
// buffer not big enough, ask for a bigger one
|
||||
return -((int)total_sz);
|
||||
}
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(IsSorted());
|
||||
SerializeInt(IsCaseSensitive());
|
||||
SerializeContainer();
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptDictBase::Unserialize(int index, const char *serializedData, int dataSize)
|
||||
{
|
||||
// NOTE: we expect sorted/case flags are read by external reader;
|
||||
// this is awkward, but I did not find better design solution atm
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
UnserializeContainer(serializedData);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
186
engines/ags/engine/ac/dynobj/scriptdict.h
Normal file
186
engines/ags/engine/ac/dynobj/scriptdict.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// 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 perfomance impact that would make.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AC_SCRIPTDICT_H
|
||||
#define __AC_SCRIPTDICT_H
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <string.h>
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
#include "util/string.h"
|
||||
#include "util/string_types.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
class ScriptDictBase : public AGSCCDynamicObject
|
||||
{
|
||||
public:
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) 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;
|
||||
|
||||
private:
|
||||
virtual size_t CalcSerializeSize() = 0;
|
||||
virtual void SerializeContainer() = 0;
|
||||
virtual void UnserializeContainer(const char *serializedData) = 0;
|
||||
};
|
||||
|
||||
template <typename TDict, bool is_sorted, bool is_casesensitive>
|
||||
class ScriptDictImpl final : public ScriptDictBase
|
||||
{
|
||||
public:
|
||||
typedef typename TDict::const_iterator ConstIterator;
|
||||
|
||||
ScriptDictImpl() = default;
|
||||
|
||||
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 { return _dic.count(String::Wrapper(key)) != 0; }
|
||||
const char *Get(const char *key) override
|
||||
{
|
||||
auto it = _dic.find(String::Wrapper(key));
|
||||
if (it == _dic.end()) return nullptr;
|
||||
return it->second.GetNullableCStr();
|
||||
}
|
||||
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;
|
||||
size_t key_len = strlen(key);
|
||||
size_t value_len = value ? strlen(value) : 0;
|
||||
return TryAddItem(key, key_len, value, value_len);
|
||||
}
|
||||
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->first.GetCStr()); // keys cannot be null
|
||||
}
|
||||
void GetValues(std::vector<const char*> &buf) const override
|
||||
{
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
buf.push_back(it->second.GetNullableCStr()); // values may be null
|
||||
}
|
||||
|
||||
private:
|
||||
bool TryAddItem(const char *key, size_t key_len, const char *value, size_t value_len)
|
||||
{
|
||||
String elem_key(key, key_len);
|
||||
String elem_value;
|
||||
if (value)
|
||||
elem_value.SetString(value, value_len);
|
||||
_dic[elem_key] = elem_value;
|
||||
return true;
|
||||
}
|
||||
void DeleteItem(ConstIterator it) { /* do nothing */ }
|
||||
|
||||
size_t CalcSerializeSize() override
|
||||
{
|
||||
size_t total_sz = sizeof(int32_t);
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
{
|
||||
total_sz += sizeof(int32_t) + it->first.GetLength();
|
||||
total_sz += sizeof(int32_t) + it->second.GetLength();
|
||||
}
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
void SerializeContainer() override
|
||||
{
|
||||
SerializeInt((int)_dic.size());
|
||||
for (auto it = _dic.begin(); it != _dic.end(); ++it)
|
||||
{
|
||||
SerializeInt((int)it->first.GetLength());
|
||||
memcpy(&serbuffer[bytesSoFar], it->first.GetCStr(), it->first.GetLength());
|
||||
bytesSoFar += it->first.GetLength();
|
||||
if (it->second.GetNullableCStr()) // values may be null
|
||||
{
|
||||
SerializeInt((int)it->second.GetLength());
|
||||
memcpy(&serbuffer[bytesSoFar], it->second.GetCStr(), it->second.GetLength());
|
||||
bytesSoFar += it->second.GetLength();
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializeInt(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnserializeContainer(const char *serializedData) override
|
||||
{
|
||||
size_t item_count = (size_t)UnserializeInt();
|
||||
for (size_t i = 0; i < item_count; ++i)
|
||||
{
|
||||
size_t key_len = UnserializeInt();
|
||||
int key_pos = bytesSoFar; bytesSoFar += key_len;
|
||||
size_t value_len = UnserializeInt();
|
||||
if (value_len == (size_t)-1)
|
||||
{
|
||||
TryAddItem(&serializedData[key_pos], key_len, nullptr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int value_pos = bytesSoFar; bytesSoFar += value_len;
|
||||
TryAddItem(&serializedData[key_pos], key_len, &serializedData[value_pos], value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TDict _dic;
|
||||
};
|
||||
|
||||
typedef ScriptDictImpl< std::map<String, String>, true, true > ScriptDict;
|
||||
typedef ScriptDictImpl< std::map<String, String, StrLessNoCase>, true, false > ScriptDictCI;
|
||||
typedef ScriptDictImpl< std::unordered_map<String, String>, false, true > ScriptHashDict;
|
||||
typedef ScriptDictImpl< std::unordered_map<String, String, HashStrNoCase, StrEqNoCase>, false, false > ScriptHashDictCI;
|
||||
|
||||
#endif // __AC_SCRIPTDICT_H
|
129
engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
Normal file
129
engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptdrawingsurface.h"
|
||||
#include "ac/spritecache.h"
|
||||
#include "ac/runtime_defines.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/drawingsurface.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "ac/gamesetupstruct.h"
|
||||
#include "game/roomstruct.h"
|
||||
#include "gfx/bitmap.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
extern RoomStruct thisroom;
|
||||
extern SpriteCache spriteset;
|
||||
extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
|
||||
extern GameState play;
|
||||
extern GameSetupStruct game;
|
||||
|
||||
Bitmap* ScriptDrawingSurface::GetBitmapSurface()
|
||||
{
|
||||
// TODO: consider creating weak_ptr here, and store one in the DrawingSurface!
|
||||
if (roomBackgroundNumber >= 0)
|
||||
return thisroom.BgFrames[roomBackgroundNumber].Graphic.get();
|
||||
else if (dynamicSpriteNumber >= 0)
|
||||
return spriteset[dynamicSpriteNumber];
|
||||
else if (dynamicSurfaceNumber >= 0)
|
||||
return dynamicallyCreatedSurfaces[dynamicSurfaceNumber];
|
||||
else if (linkedBitmapOnly != nullptr)
|
||||
return linkedBitmapOnly;
|
||||
else if (roomMaskType > kRoomAreaNone)
|
||||
return thisroom.GetMask(roomMaskType);
|
||||
quit("!DrawingSurface: attempted to use surface after Release was called");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bitmap *ScriptDrawingSurface::StartDrawing()
|
||||
{
|
||||
//abufBackup = abuf;
|
||||
return this->GetBitmapSurface();
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::FinishedDrawingReadOnly()
|
||||
{
|
||||
//abuf = abufBackup;
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::FinishedDrawing()
|
||||
{
|
||||
FinishedDrawingReadOnly();
|
||||
modified = 1;
|
||||
}
|
||||
|
||||
int ScriptDrawingSurface::Dispose(const char *address, bool force) {
|
||||
|
||||
// dispose the drawing surface
|
||||
DrawingSurface_Release(this);
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDrawingSurface::GetType() {
|
||||
return "DrawingSurface";
|
||||
}
|
||||
|
||||
int ScriptDrawingSurface::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(roomBackgroundNumber & 0xFFFF | (roomMaskType << 16));
|
||||
SerializeInt(dynamicSpriteNumber);
|
||||
SerializeInt(dynamicSurfaceNumber);
|
||||
SerializeInt(currentColour);
|
||||
SerializeInt(currentColourScript);
|
||||
SerializeInt(highResCoordinates);
|
||||
SerializeInt(modified);
|
||||
SerializeInt(hasAlphaChannel);
|
||||
SerializeInt(isLinkedBitmapOnly ? 1 : 0);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptDrawingSurface::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int room_ds = UnserializeInt();
|
||||
roomBackgroundNumber = static_cast<short>(room_ds & 0xFFFF);
|
||||
roomMaskType = (RoomAreaMask)(room_ds >> 16);
|
||||
dynamicSpriteNumber = UnserializeInt();
|
||||
dynamicSurfaceNumber = UnserializeInt();
|
||||
currentColour = UnserializeInt();
|
||||
currentColourScript = UnserializeInt();
|
||||
highResCoordinates = UnserializeInt();
|
||||
modified = UnserializeInt();
|
||||
hasAlphaChannel = UnserializeInt();
|
||||
isLinkedBitmapOnly = (UnserializeInt() != 0);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDrawingSurface::ScriptDrawingSurface()
|
||||
{
|
||||
roomBackgroundNumber = -1;
|
||||
roomMaskType = kRoomAreaNone;
|
||||
dynamicSpriteNumber = -1;
|
||||
dynamicSurfaceNumber = -1;
|
||||
isLinkedBitmapOnly = false;
|
||||
linkedBitmapOnly = nullptr;
|
||||
currentColour = 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 (game.IsLegacyHiRes() && game.IsDataInNativeCoordinates())
|
||||
{
|
||||
highResCoordinates = 1;
|
||||
}
|
||||
}
|
55
engines/ags/engine/ac/dynobj/scriptdrawingsurface.h
Normal file
55
engines/ags/engine/ac/dynobj/scriptdrawingsurface.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTDRAWINGSURFACE_H
|
||||
#define __AC_SCRIPTDRAWINGSURFACE_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
#include "game/roomstruct.h"
|
||||
|
||||
namespace AGS { namespace Common { class Bitmap; }}
|
||||
|
||||
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;
|
||||
Common::Bitmap *linkedBitmapOnly;
|
||||
int currentColour;
|
||||
int currentColourScript;
|
||||
int highResCoordinates;
|
||||
int modified;
|
||||
int hasAlphaChannel;
|
||||
//Common::Bitmap* abufBackup;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
Common::Bitmap* GetBitmapSurface();
|
||||
Common::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();
|
||||
};
|
||||
|
||||
#endif // __AC_SCRIPTDRAWINGSURFACE_H
|
50
engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp
Normal file
50
engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptdynamicsprite.h"
|
||||
#include "ac/dynamicsprite.h"
|
||||
|
||||
int ScriptDynamicSprite::Dispose(const char *address, bool force) {
|
||||
// always dispose
|
||||
if ((slot) && (!force))
|
||||
free_dynamic_sprite(slot);
|
||||
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptDynamicSprite::GetType() {
|
||||
return "DynamicSprite";
|
||||
}
|
||||
|
||||
int ScriptDynamicSprite::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(slot);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptDynamicSprite::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
slot = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite::ScriptDynamicSprite(int theSlot) {
|
||||
slot = theSlot;
|
||||
ccRegisterManagedObject(this, this);
|
||||
}
|
||||
|
||||
ScriptDynamicSprite::ScriptDynamicSprite() {
|
||||
slot = 0;
|
||||
}
|
32
engines/ags/engine/ac/dynobj/scriptdynamicsprite.h
Normal file
32
engines/ags/engine/ac/dynobj/scriptdynamicsprite.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTDYNAMICSPRITE_H
|
||||
#define __AC_SCRIPTDYNAMICSPRITE_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptDynamicSprite final : AGSCCDynamicObject {
|
||||
int slot;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
ScriptDynamicSprite(int slot);
|
||||
ScriptDynamicSprite();
|
||||
};
|
||||
|
||||
#endif // __AC_SCRIPTDYNAMICSPRITE_H
|
105
engines/ags/engine/ac/dynobj/scriptfile.cpp
Normal file
105
engines/ags/engine/ac/dynobj/scriptfile.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptfile.h"
|
||||
#include "ac/global_file.h"
|
||||
|
||||
// CHECKME: actually NULLs here will be equal to kFile_Open & kFile_Read
|
||||
const Common::FileOpenMode sc_File::fopenModes[] =
|
||||
{Common::kFile_Open/*CHECKME, was undefined*/, Common::kFile_Open, Common::kFile_CreateAlways, Common::kFile_Create};
|
||||
const Common::FileWorkMode sc_File::fworkModes[] =
|
||||
{Common::kFile_Read/*CHECKME, was undefined*/, Common::kFile_Read, Common::kFile_Write, Common::kFile_Write};
|
||||
|
||||
int sc_File::Dispose(const char *address, bool force) {
|
||||
Close();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *sc_File::GetType() {
|
||||
return "File";
|
||||
}
|
||||
|
||||
int sc_File::Serialize(const char *address, char *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;
|
||||
}
|
||||
|
||||
|
||||
const char* sc_File::GetFieldPtr(const char *address, intptr_t offset)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
void sc_File::Read(const char *address, intptr_t offset, void *dest, int size)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t sc_File::ReadInt8(const char *address, intptr_t offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t sc_File::ReadInt16(const char *address, intptr_t offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sc_File::ReadInt32(const char *address, intptr_t offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float sc_File::ReadFloat(const char *address, intptr_t offset)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void sc_File::Write(const char *address, intptr_t offset, void *src, int size)
|
||||
{
|
||||
}
|
||||
|
||||
void sc_File::WriteInt8(const char *address, intptr_t offset, uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
void sc_File::WriteInt16(const char *address, intptr_t offset, int16_t val)
|
||||
{
|
||||
}
|
||||
|
||||
void sc_File::WriteInt32(const char *address, intptr_t offset, int32_t val)
|
||||
{
|
||||
}
|
||||
|
||||
void sc_File::WriteFloat(const char *address, intptr_t offset, float val)
|
||||
{
|
||||
}
|
61
engines/ags/engine/ac/dynobj/scriptfile.h
Normal file
61
engines/ags/engine/ac/dynobj/scriptfile.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTFILE_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTFILE_H
|
||||
|
||||
#include "ac/dynobj/cc_dynamicobject.h"
|
||||
#include "util/file.h"
|
||||
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
#define scFileRead 1
|
||||
#define scFileWrite 2
|
||||
#define scFileAppend 3
|
||||
|
||||
struct sc_File final : ICCDynamicObject {
|
||||
int32_t handle;
|
||||
|
||||
static const Common::FileOpenMode fopenModes[];
|
||||
static const Common::FileWorkMode fworkModes[];
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
|
||||
const char *GetType() override;
|
||||
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
|
||||
int OpenFile(const char *filename, int mode);
|
||||
void Close();
|
||||
|
||||
sc_File();
|
||||
|
||||
// Legacy support for reading and writing object values by their relative offset
|
||||
const char* GetFieldPtr(const char *address, intptr_t offset) override;
|
||||
void Read(const char *address, intptr_t offset, void *dest, int size) override;
|
||||
uint8_t ReadInt8(const char *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(const char *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(const char *address, intptr_t offset) override;
|
||||
float ReadFloat(const char *address, intptr_t offset) override;
|
||||
void Write(const char *address, intptr_t offset, void *src, int size) override;
|
||||
void WriteInt8(const char *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(const char *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(const char *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(const char *address, intptr_t offset, float val) override;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTFILE_H
|
27
engines/ags/engine/ac/dynobj/scriptgui.h
Normal file
27
engines/ags/engine/ac/dynobj/scriptgui.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTGUI_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTGUI_H
|
||||
|
||||
// 64 bit: This struct must be 8 byte long
|
||||
struct ScriptGUI {
|
||||
int id;
|
||||
int __padding;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTGUI_H
|
26
engines/ags/engine/ac/dynobj/scripthotspot.h
Normal file
26
engines/ags/engine/ac/dynobj/scripthotspot.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTHOTSPOT_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTHOTSPOT_H
|
||||
|
||||
struct ScriptHotspot {
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTHOTSPOT_H
|
26
engines/ags/engine/ac/dynobj/scriptinvitem.h
Normal file
26
engines/ags/engine/ac/dynobj/scriptinvitem.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTINVITEM_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTINVITEM_H
|
||||
|
||||
struct ScriptInvItem {
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTINVITEM_H
|
26
engines/ags/engine/ac/dynobj/scriptmouse.h
Normal file
26
engines/ags/engine/ac/dynobj/scriptmouse.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTMOUSE_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTMOUSE_H
|
||||
|
||||
// The text script's "mouse" struct
|
||||
struct ScriptMouse {
|
||||
int x,y;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTMOUSE_H
|
30
engines/ags/engine/ac/dynobj/scriptobject.h
Normal file
30
engines/ags/engine/ac/dynobj/scriptobject.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTOBJECT_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTOBJECT_H
|
||||
|
||||
#include "ac/roomobject.h"
|
||||
|
||||
// 64 bit: Struct size must be 8 byte for scripts to work
|
||||
struct ScriptObject {
|
||||
int id;
|
||||
//RoomObject *obj;
|
||||
int __padding;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTOBJECT_H
|
83
engines/ags/engine/ac/dynobj/scriptoverlay.cpp
Normal file
83
engines/ags/engine/ac/dynobj/scriptoverlay.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptoverlay.h"
|
||||
#include "ac/common.h"
|
||||
#include "ac/overlay.h"
|
||||
#include "ac/runtime_defines.h"
|
||||
#include "ac/screenoverlay.h"
|
||||
|
||||
int ScriptOverlay::Dispose(const char *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
|
||||
int overlayIndex = find_overlay_of_type(overlayId);
|
||||
if (overlayIndex >= 0)
|
||||
{
|
||||
screenover[overlayIndex].associatedOverlayHandle = 0;
|
||||
}
|
||||
|
||||
// if this is being removed voluntarily (ie. pointer out of
|
||||
// scope) then remove the associateed overlay
|
||||
// Otherwise, it's a Restre Game or something so don't
|
||||
if ((!force) && (!isBackgroundSpeech) && (Overlay_GetValid(this)))
|
||||
{
|
||||
Remove();
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptOverlay::GetType() {
|
||||
return "Overlay";
|
||||
}
|
||||
|
||||
int ScriptOverlay::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(overlayId);
|
||||
SerializeInt(borderWidth);
|
||||
SerializeInt(borderHeight);
|
||||
SerializeInt(isBackgroundSpeech);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptOverlay::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
overlayId = UnserializeInt();
|
||||
borderWidth = UnserializeInt();
|
||||
borderHeight = UnserializeInt();
|
||||
isBackgroundSpeech = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
void ScriptOverlay::Remove()
|
||||
{
|
||||
int overlayIndex = find_overlay_of_type(overlayId);
|
||||
if (overlayIndex < 0)
|
||||
{
|
||||
quit("ScriptOverlay::Remove: overlay is not there!");
|
||||
}
|
||||
remove_screen_overlay_index(overlayIndex);
|
||||
overlayId = -1;
|
||||
}
|
||||
|
||||
|
||||
ScriptOverlay::ScriptOverlay() {
|
||||
overlayId = -1;
|
||||
borderWidth = 0;
|
||||
borderHeight = 0;
|
||||
isBackgroundSpeech = 0;
|
||||
}
|
34
engines/ags/engine/ac/dynobj/scriptoverlay.h
Normal file
34
engines/ags/engine/ac/dynobj/scriptoverlay.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTOVERLAY_H
|
||||
#define __AC_SCRIPTOVERLAY_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptOverlay final : AGSCCDynamicObject {
|
||||
int overlayId;
|
||||
int borderWidth;
|
||||
int borderHeight;
|
||||
int isBackgroundSpeech;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
void Remove();
|
||||
ScriptOverlay();
|
||||
};
|
||||
|
||||
#endif // __AC_SCRIPTOVERLAY_H
|
26
engines/ags/engine/ac/dynobj/scriptregion.h
Normal file
26
engines/ags/engine/ac/dynobj/scriptregion.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTREGION_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTREGION_H
|
||||
|
||||
struct ScriptRegion {
|
||||
int id;
|
||||
int reserved;
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTREGION_H
|
50
engines/ags/engine/ac/dynobj/scriptset.cpp
Normal file
50
engines/ags/engine/ac/dynobj/scriptset.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
#include "ac/dynobj/scriptset.h"
|
||||
|
||||
int ScriptSetBase::Dispose(const char *address, bool force)
|
||||
{
|
||||
Clear();
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptSetBase::GetType()
|
||||
{
|
||||
return "StringSet";
|
||||
}
|
||||
|
||||
int ScriptSetBase::Serialize(const char *address, char *buffer, int bufsize)
|
||||
{
|
||||
size_t total_sz = CalcSerializeSize() + sizeof(int32_t) * 2;
|
||||
if (bufsize < 0 || total_sz > (size_t)bufsize)
|
||||
{
|
||||
// buffer not big enough, ask for a bigger one
|
||||
return -((int)total_sz);
|
||||
}
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(IsSorted());
|
||||
SerializeInt(IsCaseSensitive());
|
||||
SerializeContainer();
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptSetBase::Unserialize(int index, const char *serializedData, int dataSize)
|
||||
{
|
||||
// NOTE: we expect sorted/case flags are read by external reader;
|
||||
// this is awkward, but I did not find better design solution atm
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
UnserializeContainer(serializedData);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
144
engines/ags/engine/ac/dynobj/scriptset.h
Normal file
144
engines/ags/engine/ac/dynobj/scriptset.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// 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 perfomance impact that would make.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AC_SCRIPTSET_H
|
||||
#define __AC_SCRIPTSET_H
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <string.h>
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
#include "util/string.h"
|
||||
#include "util/string_types.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
class ScriptSetBase : public AGSCCDynamicObject
|
||||
{
|
||||
public:
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) 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;
|
||||
|
||||
private:
|
||||
virtual size_t CalcSerializeSize() = 0;
|
||||
virtual void SerializeContainer() = 0;
|
||||
virtual void UnserializeContainer(const char *serializedData) = 0;
|
||||
};
|
||||
|
||||
template <typename TSet, bool is_sorted, bool is_casesensitive>
|
||||
class ScriptSetImpl final : public ScriptSetBase
|
||||
{
|
||||
public:
|
||||
typedef typename TSet::const_iterator ConstIterator;
|
||||
|
||||
ScriptSetImpl() = default;
|
||||
|
||||
bool IsCaseSensitive() const override { return is_casesensitive; }
|
||||
bool IsSorted() const override { return is_sorted; }
|
||||
|
||||
bool Add(const char *item) override
|
||||
{
|
||||
if (!item) return false;
|
||||
size_t len = strlen(item);
|
||||
return TryAddItem(item, len);
|
||||
}
|
||||
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 char *item, size_t len)
|
||||
{
|
||||
return _set.insert(String(item, len)).second;
|
||||
}
|
||||
void DeleteItem(ConstIterator it) { /* do nothing */ }
|
||||
|
||||
size_t CalcSerializeSize() override
|
||||
{
|
||||
size_t total_sz = sizeof(int32_t);
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it)
|
||||
total_sz += sizeof(int32_t) + it->GetLength();
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
void SerializeContainer() override
|
||||
{
|
||||
SerializeInt((int)_set.size());
|
||||
for (auto it = _set.begin(); it != _set.end(); ++it)
|
||||
{
|
||||
SerializeInt((int)it->GetLength());
|
||||
memcpy(&serbuffer[bytesSoFar], it->GetCStr(), it->GetLength());
|
||||
bytesSoFar += it->GetLength();
|
||||
}
|
||||
}
|
||||
|
||||
void UnserializeContainer(const char *serializedData) override
|
||||
{
|
||||
size_t item_count = (size_t)UnserializeInt();
|
||||
for (size_t i = 0; i < item_count; ++i)
|
||||
{
|
||||
size_t len = UnserializeInt();
|
||||
TryAddItem(&serializedData[bytesSoFar], len);
|
||||
bytesSoFar += len;
|
||||
}
|
||||
}
|
||||
|
||||
TSet _set;
|
||||
};
|
||||
|
||||
typedef ScriptSetImpl< std::set<String>, true, true > ScriptSet;
|
||||
typedef ScriptSetImpl< std::set<String, StrLessNoCase>, true, false > ScriptSetCI;
|
||||
typedef ScriptSetImpl< std::unordered_set<String>, false, true > ScriptHashSet;
|
||||
typedef ScriptSetImpl< std::unordered_set<String, HashStrNoCase, StrEqNoCase>, false, false > ScriptHashSetCI;
|
||||
|
||||
#endif // __AC_SCRIPTSET_H
|
66
engines/ags/engine/ac/dynobj/scriptstring.cpp
Normal file
66
engines/ags/engine/ac/dynobj/scriptstring.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptstring.h"
|
||||
#include "ac/string.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
DynObjectRef ScriptString::CreateString(const char *fromText) {
|
||||
return CreateNewScriptStringObj(fromText);
|
||||
}
|
||||
|
||||
int ScriptString::Dispose(const char *address, bool force) {
|
||||
// always dispose
|
||||
if (text) {
|
||||
free(text);
|
||||
text = nullptr;
|
||||
}
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptString::GetType() {
|
||||
return "String";
|
||||
}
|
||||
|
||||
int ScriptString::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
|
||||
auto toSerialize = text ? text : "";
|
||||
|
||||
auto len = strlen(toSerialize);
|
||||
SerializeInt(len);
|
||||
strcpy(&serbuffer[bytesSoFar], toSerialize);
|
||||
bytesSoFar += len + 1;
|
||||
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptString::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
int textsize = UnserializeInt();
|
||||
text = (char*)malloc(textsize + 1);
|
||||
strcpy(text, &serializedData[bytesSoFar]);
|
||||
ccRegisterUnserializedObject(index, text, this);
|
||||
}
|
||||
|
||||
ScriptString::ScriptString() {
|
||||
text = nullptr;
|
||||
}
|
||||
|
||||
ScriptString::ScriptString(const char *fromText) {
|
||||
text = (char*)malloc(strlen(fromText) + 1);
|
||||
strcpy(text, fromText);
|
||||
}
|
34
engines/ags/engine/ac/dynobj/scriptstring.h
Normal file
34
engines/ags/engine/ac/dynobj/scriptstring.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTSTRING_H
|
||||
#define __AC_SCRIPTSTRING_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptString final : AGSCCDynamicObject, ICCStringClass {
|
||||
char *text;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
DynObjectRef CreateString(const char *fromText) override;
|
||||
|
||||
ScriptString();
|
||||
ScriptString(const char *fromText);
|
||||
};
|
||||
|
||||
#endif // __AC_SCRIPTSTRING_H
|
33
engines/ags/engine/ac/dynobj/scriptsystem.h
Normal file
33
engines/ags/engine/ac/dynobj/scriptsystem.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTSYSTEM_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTSYSTEM_H
|
||||
|
||||
// The text script's "system" struct
|
||||
struct ScriptSystem {
|
||||
int width,height;
|
||||
int coldepth;
|
||||
int os;
|
||||
int windowed;
|
||||
int vsync;
|
||||
int viewport_width, viewport_height;
|
||||
char aci_version[10]; // FIXME this when possible, version format is different now
|
||||
int reserved[5]; // so that future scripts don't overwrite data
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTSYSTEM_H
|
144
engines/ags/engine/ac/dynobj/scriptuserobject.cpp
Normal file
144
engines/ags/engine/ac/dynobj/scriptuserobject.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <memory.h>
|
||||
#include "scriptuserobject.h"
|
||||
|
||||
// return the type name of the object
|
||||
const char *ScriptUserObject::GetType()
|
||||
{
|
||||
return "UserObject";
|
||||
}
|
||||
|
||||
ScriptUserObject::ScriptUserObject()
|
||||
: _size(0)
|
||||
, _data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ScriptUserObject::~ScriptUserObject()
|
||||
{
|
||||
delete [] _data;
|
||||
}
|
||||
|
||||
/* static */ ScriptUserObject *ScriptUserObject::CreateManaged(size_t size)
|
||||
{
|
||||
ScriptUserObject *suo = new ScriptUserObject();
|
||||
suo->Create(nullptr, size);
|
||||
ccRegisterManagedObject(suo, suo);
|
||||
return suo;
|
||||
}
|
||||
|
||||
void ScriptUserObject::Create(const char *data, size_t size)
|
||||
{
|
||||
delete [] _data;
|
||||
_data = nullptr;
|
||||
|
||||
_size = size;
|
||||
if (_size > 0)
|
||||
{
|
||||
_data = new char[size];
|
||||
if (data)
|
||||
memcpy(_data, data, _size);
|
||||
else
|
||||
memset(_data, 0, _size);
|
||||
}
|
||||
}
|
||||
|
||||
int ScriptUserObject::Dispose(const char *address, bool force)
|
||||
{
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScriptUserObject::Serialize(const char *address, char *buffer, int bufsize)
|
||||
{
|
||||
if (_size > bufsize)
|
||||
// buffer not big enough, ask for a bigger one
|
||||
return -_size;
|
||||
|
||||
memcpy(buffer, _data, _size);
|
||||
return _size;
|
||||
}
|
||||
|
||||
void ScriptUserObject::Unserialize(int index, const char *serializedData, int dataSize)
|
||||
{
|
||||
Create(serializedData, dataSize);
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
const char* ScriptUserObject::GetFieldPtr(const char *address, intptr_t offset)
|
||||
{
|
||||
return _data + offset;
|
||||
}
|
||||
|
||||
void ScriptUserObject::Read(const char *address, intptr_t offset, void *dest, int size)
|
||||
{
|
||||
memcpy(dest, _data + offset, size);
|
||||
}
|
||||
|
||||
uint8_t ScriptUserObject::ReadInt8(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(uint8_t*)(_data + offset);
|
||||
}
|
||||
|
||||
int16_t ScriptUserObject::ReadInt16(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int16_t*)(_data + offset);
|
||||
}
|
||||
|
||||
int32_t ScriptUserObject::ReadInt32(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(int32_t*)(_data + offset);
|
||||
}
|
||||
|
||||
float ScriptUserObject::ReadFloat(const char *address, intptr_t offset)
|
||||
{
|
||||
return *(float*)(_data + offset);
|
||||
}
|
||||
|
||||
void ScriptUserObject::Write(const char *address, intptr_t offset, void *src, int size)
|
||||
{
|
||||
memcpy((void*)(_data + offset), src, size);
|
||||
}
|
||||
|
||||
void ScriptUserObject::WriteInt8(const char *address, intptr_t offset, uint8_t val)
|
||||
{
|
||||
*(uint8_t*)(_data + offset) = val;
|
||||
}
|
||||
|
||||
void ScriptUserObject::WriteInt16(const char *address, intptr_t offset, int16_t val)
|
||||
{
|
||||
*(int16_t*)(_data + offset) = val;
|
||||
}
|
||||
|
||||
void ScriptUserObject::WriteInt32(const char *address, intptr_t offset, int32_t val)
|
||||
{
|
||||
*(int32_t*)(_data + offset) = val;
|
||||
}
|
||||
|
||||
void ScriptUserObject::WriteFloat(const char *address, intptr_t offset, float val)
|
||||
{
|
||||
*(float*)(_data + offset) = val;
|
||||
}
|
||||
|
||||
|
||||
// Allocates managed struct containing two ints: X and Y
|
||||
ScriptUserObject *ScriptStructHelpers::CreatePoint(int x, int y)
|
||||
{
|
||||
ScriptUserObject *suo = ScriptUserObject::CreateManaged(sizeof(int32_t) * 2);
|
||||
suo->WriteInt32((const char*)suo, 0, x);
|
||||
suo->WriteInt32((const char*)suo, sizeof(int32_t), y);
|
||||
return suo;
|
||||
}
|
75
engines/ags/engine/ac/dynobj/scriptuserobject.h
Normal file
75
engines/ags/engine/ac/dynobj/scriptuserobject.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// Managed object, which size and contents are defined by user script
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef __AGS_EE_DYNOBJ__SCRIPTUSERSTRUCT_H
|
||||
#define __AGS_EE_DYNOBJ__SCRIPTUSERSTRUCT_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptUserObject final : ICCDynamicObject
|
||||
{
|
||||
public:
|
||||
ScriptUserObject();
|
||||
|
||||
protected:
|
||||
virtual ~ScriptUserObject();
|
||||
|
||||
public:
|
||||
static ScriptUserObject *CreateManaged(size_t size);
|
||||
void Create(const char *data, size_t size);
|
||||
|
||||
// return the type name of the object
|
||||
const char *GetType() override;
|
||||
int Dispose(const char *address, bool force) override;
|
||||
// serialize the object into BUFFER (which is BUFSIZE bytes)
|
||||
// return number of bytes used
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
virtual void Unserialize(int index, const char *serializedData, int dataSize);
|
||||
|
||||
// Support for reading and writing object values by their relative offset
|
||||
const char* GetFieldPtr(const char *address, intptr_t offset) override;
|
||||
void Read(const char *address, intptr_t offset, void *dest, int size) override;
|
||||
uint8_t ReadInt8(const char *address, intptr_t offset) override;
|
||||
int16_t ReadInt16(const char *address, intptr_t offset) override;
|
||||
int32_t ReadInt32(const char *address, intptr_t offset) override;
|
||||
float ReadFloat(const char *address, intptr_t offset) override;
|
||||
void Write(const char *address, intptr_t offset, void *src, int size) override;
|
||||
void WriteInt8(const char *address, intptr_t offset, uint8_t val) override;
|
||||
void WriteInt16(const char *address, intptr_t offset, int16_t val) override;
|
||||
void WriteInt32(const char *address, intptr_t offset, int32_t val) override;
|
||||
void WriteFloat(const char *address, intptr_t offset, float val) override;
|
||||
|
||||
private:
|
||||
// NOTE: we use signed int for Size at the moment, because the managed
|
||||
// object interface's Serialize() function requires the object to return
|
||||
// negative value of size in case the provided buffer was not large
|
||||
// enough. Since this interface is also a part of Plugin API, we would
|
||||
// need more significant change to program before we could use different
|
||||
// approach.
|
||||
int32_t _size;
|
||||
char *_data;
|
||||
};
|
||||
|
||||
|
||||
// Helper functions for setting up custom managed structs based on ScriptUserObject.
|
||||
namespace ScriptStructHelpers
|
||||
{
|
||||
// Creates a managed Point object, represented as a pair of X and Y coordinates.
|
||||
ScriptUserObject *CreatePoint(int x, int y);
|
||||
};
|
||||
|
||||
#endif // __AGS_EE_DYNOBJ__SCRIPTUSERSTRUCT_H
|
53
engines/ags/engine/ac/dynobj/scriptviewframe.cpp
Normal file
53
engines/ags/engine/ac/dynobj/scriptviewframe.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptviewframe.h"
|
||||
|
||||
int ScriptViewFrame::Dispose(const char *address, bool force) {
|
||||
// always dispose a ViewFrame
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ScriptViewFrame::GetType() {
|
||||
return "ViewFrame";
|
||||
}
|
||||
|
||||
int ScriptViewFrame::Serialize(const char *address, char *buffer, int bufsize) {
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(view);
|
||||
SerializeInt(loop);
|
||||
SerializeInt(frame);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptViewFrame::Unserialize(int index, const char *serializedData, int dataSize) {
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
view = UnserializeInt();
|
||||
loop = UnserializeInt();
|
||||
frame = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptViewFrame::ScriptViewFrame(int p_view, int p_loop, int p_frame) {
|
||||
view = p_view;
|
||||
loop = p_loop;
|
||||
frame = p_frame;
|
||||
}
|
||||
|
||||
ScriptViewFrame::ScriptViewFrame() {
|
||||
view = -1;
|
||||
loop = -1;
|
||||
frame = -1;
|
||||
}
|
32
engines/ags/engine/ac/dynobj/scriptviewframe.h
Normal file
32
engines/ags/engine/ac/dynobj/scriptviewframe.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTVIEWFRAME_H
|
||||
#define __AC_SCRIPTVIEWFRAME_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
struct ScriptViewFrame final : AGSCCDynamicObject {
|
||||
int view, loop, frame;
|
||||
|
||||
int Dispose(const char *address, bool force) override;
|
||||
const char *GetType() override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
ScriptViewFrame(int p_view, int p_loop, int p_frame);
|
||||
ScriptViewFrame();
|
||||
};
|
||||
|
||||
#endif // __AC_SCRIPTVIEWFRAME_H
|
64
engines/ags/engine/ac/dynobj/scriptviewport.cpp
Normal file
64
engines/ags/engine/ac/dynobj/scriptviewport.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ac/dynobj/scriptviewport.h"
|
||||
#include "ac/gamestate.h"
|
||||
#include "util/bbop.h"
|
||||
|
||||
using namespace AGS::Common;
|
||||
|
||||
ScriptViewport::ScriptViewport(int id) : _id(id) {}
|
||||
|
||||
const char *ScriptViewport::GetType()
|
||||
{
|
||||
return "Viewport2";
|
||||
}
|
||||
|
||||
int ScriptViewport::Dispose(const char *address, bool force)
|
||||
{
|
||||
// Note that ScriptViewport is a reference to actual Viewport object,
|
||||
// and this deletes the reference, while viewport may remain in GameState.
|
||||
delete this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScriptViewport::Serialize(const char *address, char *buffer, int bufsize)
|
||||
{
|
||||
StartSerialize(buffer);
|
||||
SerializeInt(_id);
|
||||
return EndSerialize();
|
||||
}
|
||||
|
||||
void ScriptViewport::Unserialize(int index, const char *serializedData, int dataSize)
|
||||
{
|
||||
StartUnserialize(serializedData, dataSize);
|
||||
_id = UnserializeInt();
|
||||
ccRegisterUnserializedObject(index, this, this);
|
||||
}
|
||||
|
||||
ScriptViewport *Viewport_Unserialize(int handle, const char *serializedData, int dataSize)
|
||||
{
|
||||
// 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 Viewport gets removed.
|
||||
const int id = BBOp::Int32FromLE(*((int*)serializedData));
|
||||
if (id >= 0)
|
||||
{
|
||||
auto scview = play.RegisterRoomViewport(id, handle);
|
||||
if (scview)
|
||||
return scview;
|
||||
}
|
||||
return new ScriptViewport(-1); // make invalid reference
|
||||
}
|
43
engines/ags/engine/ac/dynobj/scriptviewport.h
Normal file
43
engines/ags/engine/ac/dynobj/scriptviewport.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//=============================================================================
|
||||
//
|
||||
// Adventure Game Studio (AGS)
|
||||
//
|
||||
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
|
||||
// The full list of copyright holders can be found in the Copyright.txt
|
||||
// file, which is part of this source code distribution.
|
||||
//
|
||||
// The AGS source code is provided under the Artistic License 2.0.
|
||||
// A copy of this license can be found in the file License.txt and at
|
||||
// http://www.opensource.org/licenses/artistic-license-2.0.php
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef __AC_SCRIPTVIEWPORT_H
|
||||
#define __AC_SCRIPTVIEWPORT_H
|
||||
|
||||
#include "ac/dynobj/cc_agsdynamicobject.h"
|
||||
|
||||
// ScriptViewport keeps a reference to actual room Viewport in script.
|
||||
struct ScriptViewport final : AGSCCDynamicObject
|
||||
{
|
||||
public:
|
||||
ScriptViewport(int id);
|
||||
// Get viewport index; negative means the viewport was deleted
|
||||
int GetID() const { return _id; }
|
||||
void SetID(int id) { _id = id; }
|
||||
// Reset viewport index to indicate that this reference is no longer valid
|
||||
void Invalidate() { _id = -1; }
|
||||
|
||||
const char *GetType() override;
|
||||
int Dispose(const char *address, bool force) override;
|
||||
int Serialize(const char *address, char *buffer, int bufsize) override;
|
||||
void Unserialize(int index, const char *serializedData, int dataSize) override;
|
||||
|
||||
private:
|
||||
int _id = -1; // index of viewport in the game state array
|
||||
};
|
||||
|
||||
// Unserialize viewport from the memory stream
|
||||
ScriptViewport *Viewport_Unserialize(int handle, const char *serializedData, int dataSize);
|
||||
|
||||
#endif // __AC_SCRIPTVIEWPORT_H
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue