From 85b9ae02b7e8f4ab36d55aebe97ff46f25a4dcac Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 30 Sep 2024 23:09:40 -0300 Subject: [PATCH 01/13] Delete makeheaders --- .gitignore | 2 - CMakeLists.txt | 13 - Makefile | 8 - include/Engine/Application.h | 98 ++ include/Engine/Audio/AudioManager.h | 89 ++ include/Engine/Audio/AudioPlayback.h | 41 + include/Engine/Bytecode/Bytecode.h | 31 + include/Engine/Bytecode/Compiler.h | 221 ++++ include/Engine/Bytecode/GarbageCollector.h | 38 + include/Engine/Bytecode/ScriptEntity.h | 81 ++ include/Engine/Bytecode/ScriptManager.h | 97 ++ include/Engine/Bytecode/SourceFileMap.h | 29 + include/Engine/Bytecode/StandardLibrary.h | 34 + include/Engine/Bytecode/TypeImpl/ArrayImpl.h | 24 + .../Engine/Bytecode/TypeImpl/FunctionImpl.h | 23 + include/Engine/Bytecode/TypeImpl/MapImpl.h | 25 + include/Engine/Bytecode/TypeImpl/StringImpl.h | 24 + include/Engine/Bytecode/VMThread.h | 114 ++ include/Engine/Bytecode/Values.h | 25 + include/Engine/Diagnostics/Clock.h | 23 + include/Engine/Diagnostics/Log.h | 31 + include/Engine/Diagnostics/Memory.h | 42 + .../Engine/Diagnostics/PerformanceMeasure.h | 23 + include/Engine/Diagnostics/RemoteDebug.h | 22 + include/Engine/Extensions/Discord.h | 28 + include/Engine/Filesystem/Directory.h | 25 + include/Engine/Filesystem/File.h | 21 + include/Engine/FontFace.h | 23 + include/Engine/Graphics.h | 198 +++ include/Engine/Hashing/CRC32.h | 22 + include/Engine/Hashing/CombinedHash.h | 21 + include/Engine/Hashing/FNV1A.h | 22 + include/Engine/Hashing/MD5.h | 24 + include/Engine/Hashing/Murmur.h | 22 + include/Engine/IO/Compression/Huffman.h | 19 + include/Engine/IO/Compression/LZ11.h | 19 + include/Engine/IO/Compression/LZSS.h | 19 + include/Engine/IO/Compression/RunLength.h | 19 + include/Engine/IO/Compression/ZLibStream.h | 37 + include/Engine/IO/FileStream.h | 38 + include/Engine/IO/MemoryStream.h | 37 + include/Engine/IO/NetworkStream.h | 35 + include/Engine/IO/ResourceStream.h | 32 + include/Engine/IO/SDLStream.h | 36 + include/Engine/IO/Serializer.h | 80 ++ include/Engine/IO/Stream.h | 62 + include/Engine/Input/Controller.h | 52 + include/Engine/Input/InputAction.h | 24 + include/Engine/Input/InputPlayer.h | 86 ++ include/Engine/InputManager.h | 128 ++ include/Engine/Math/Clipper.h | 25 + include/Engine/Math/Ease.h | 49 + include/Engine/Math/Geometry.h | 25 + include/Engine/Math/Math.h | 57 + include/Engine/Math/Matrix4x4.h | 39 + include/Engine/Math/Random.h | 24 + include/Engine/Math/Vector.h | 32 + include/Engine/Media/Decoder.h | 64 + include/Engine/Media/Decoders/AudioDecoder.h | 42 + include/Engine/Media/Decoders/VideoDecoder.h | 37 + include/Engine/Media/MediaPlayer.h | 68 + include/Engine/Media/MediaSource.h | 38 + include/Engine/Media/Utils/MediaPlayerState.h | 29 + include/Engine/Media/Utils/PtrBuffer.h | 36 + include/Engine/Media/Utils/RingBuffer.h | 34 + include/Engine/Network/HTTP.h | 21 + include/Engine/Network/WebSocketClient.h | 47 + include/Engine/Rendering/D3D/D3DRenderer.h | 76 ++ include/Engine/Rendering/FaceInfo.h | 33 + include/Engine/Rendering/GL/GLRenderer.h | 100 ++ include/Engine/Rendering/GL/GLShader.h | 58 + include/Engine/Rendering/GL/GLShaderBuilder.h | 29 + .../Engine/Rendering/GL/GLShaderContainer.h | 35 + include/Engine/Rendering/GameTexture.h | 28 + include/Engine/Rendering/Material.h | 39 + include/Engine/Rendering/ModelRenderer.h | 56 + include/Engine/Rendering/PolygonRenderer.h | 51 + include/Engine/Rendering/SDL2/SDL2Renderer.h | 73 ++ include/Engine/Rendering/Shader.h | 19 + .../Rendering/Software/PolygonRasterizer.h | 52 + include/Engine/Rendering/Software/Scanline.h | 30 + .../Rendering/Software/SoftwareRenderer.h | 155 +++ include/Engine/Rendering/Texture.h | 39 + include/Engine/Rendering/TextureReference.h | 25 + include/Engine/Rendering/VertexBuffer.h | 34 + include/Engine/Rendering/ViewTexture.h | 24 + include/Engine/ResourceTypes/IModel.h | 62 + include/Engine/ResourceTypes/ISound.h | 34 + include/Engine/ResourceTypes/ISprite.h | 45 + include/Engine/ResourceTypes/Image.h | 26 + .../Engine/ResourceTypes/ImageFormats/GIF.h | 34 + .../ResourceTypes/ImageFormats/ImageFormat.h | 28 + .../Engine/ResourceTypes/ImageFormats/JPEG.h | 24 + .../Engine/ResourceTypes/ImageFormats/PNG.h | 26 + .../ResourceTypes/ModelFormats/HatchModel.h | 50 + .../ResourceTypes/ModelFormats/Importer.h | 32 + .../ResourceTypes/ModelFormats/MD3Model.h | 34 + .../ResourceTypes/ModelFormats/RSDKModel.h | 21 + .../Engine/ResourceTypes/ResourceManager.h | 29 + .../SceneFormats/HatchSceneReader.h | 39 + .../SceneFormats/RSDKSceneReader.h | 33 + .../SceneFormats/TiledMapReader.h | 29 + .../Engine/ResourceTypes/SoundFormats/OGG.h | 36 + .../ResourceTypes/SoundFormats/SoundFormat.h | 43 + .../Engine/ResourceTypes/SoundFormats/WAV.h | 28 + include/Engine/Scene.h | 212 +++ include/Engine/Scene/SceneInfo.h | 46 + include/Engine/Scene/SceneLayer.h | 76 ++ include/Engine/Scene/ScrollingIndex.h | 21 + include/Engine/Scene/ScrollingInfo.h | 23 + include/Engine/Scene/TileConfig.h | 28 + include/Engine/Scene/TileSpriteInfo.h | 22 + include/Engine/Scene/View.h | 54 + include/Engine/TextFormats/INI/INI.h | 50 + include/Engine/TextFormats/XML/XMLParser.h | 33 + include/Engine/Types/DrawGroupList.h | 34 + include/Engine/Types/Entity.h | 137 ++ include/Engine/Types/ObjectList.h | 43 + include/Engine/Types/ObjectRegistry.h | 33 + include/Engine/Types/Tileset.h | 38 + include/Engine/Utilities/ColorUtils.h | 37 + include/Engine/Utilities/StringUtils.h | 38 + tools/makeheaders | Bin 85736 -> 0 bytes tools/makeheaders-src/crc32.h | 91 -- tools/makeheaders-src/main.cpp | 852 ------------ tools/makeheaders.exe | Bin 2215483 -> 0 bytes tools/makeheaders2-src/crc32.h | 74 -- tools/makeheaders2-src/dirent.c | 316 ----- tools/makeheaders2-src/dirent.h | 92 -- tools/makeheaders2-src/makeheaders.cpp | 1161 ----------------- 130 files changed, 5465 insertions(+), 2609 deletions(-) create mode 100644 include/Engine/Application.h create mode 100644 include/Engine/Audio/AudioManager.h create mode 100644 include/Engine/Audio/AudioPlayback.h create mode 100644 include/Engine/Bytecode/Bytecode.h create mode 100644 include/Engine/Bytecode/Compiler.h create mode 100644 include/Engine/Bytecode/GarbageCollector.h create mode 100644 include/Engine/Bytecode/ScriptEntity.h create mode 100644 include/Engine/Bytecode/ScriptManager.h create mode 100644 include/Engine/Bytecode/SourceFileMap.h create mode 100644 include/Engine/Bytecode/StandardLibrary.h create mode 100644 include/Engine/Bytecode/TypeImpl/ArrayImpl.h create mode 100644 include/Engine/Bytecode/TypeImpl/FunctionImpl.h create mode 100644 include/Engine/Bytecode/TypeImpl/MapImpl.h create mode 100644 include/Engine/Bytecode/TypeImpl/StringImpl.h create mode 100644 include/Engine/Bytecode/VMThread.h create mode 100644 include/Engine/Bytecode/Values.h create mode 100644 include/Engine/Diagnostics/Clock.h create mode 100644 include/Engine/Diagnostics/Log.h create mode 100644 include/Engine/Diagnostics/Memory.h create mode 100644 include/Engine/Diagnostics/PerformanceMeasure.h create mode 100644 include/Engine/Diagnostics/RemoteDebug.h create mode 100644 include/Engine/Extensions/Discord.h create mode 100644 include/Engine/Filesystem/Directory.h create mode 100644 include/Engine/Filesystem/File.h create mode 100644 include/Engine/FontFace.h create mode 100644 include/Engine/Graphics.h create mode 100644 include/Engine/Hashing/CRC32.h create mode 100644 include/Engine/Hashing/CombinedHash.h create mode 100644 include/Engine/Hashing/FNV1A.h create mode 100644 include/Engine/Hashing/MD5.h create mode 100644 include/Engine/Hashing/Murmur.h create mode 100644 include/Engine/IO/Compression/Huffman.h create mode 100644 include/Engine/IO/Compression/LZ11.h create mode 100644 include/Engine/IO/Compression/LZSS.h create mode 100644 include/Engine/IO/Compression/RunLength.h create mode 100644 include/Engine/IO/Compression/ZLibStream.h create mode 100644 include/Engine/IO/FileStream.h create mode 100644 include/Engine/IO/MemoryStream.h create mode 100644 include/Engine/IO/NetworkStream.h create mode 100644 include/Engine/IO/ResourceStream.h create mode 100644 include/Engine/IO/SDLStream.h create mode 100644 include/Engine/IO/Serializer.h create mode 100644 include/Engine/IO/Stream.h create mode 100644 include/Engine/Input/Controller.h create mode 100644 include/Engine/Input/InputAction.h create mode 100644 include/Engine/Input/InputPlayer.h create mode 100644 include/Engine/InputManager.h create mode 100644 include/Engine/Math/Clipper.h create mode 100644 include/Engine/Math/Ease.h create mode 100644 include/Engine/Math/Geometry.h create mode 100644 include/Engine/Math/Math.h create mode 100644 include/Engine/Math/Matrix4x4.h create mode 100644 include/Engine/Math/Random.h create mode 100644 include/Engine/Math/Vector.h create mode 100644 include/Engine/Media/Decoder.h create mode 100644 include/Engine/Media/Decoders/AudioDecoder.h create mode 100644 include/Engine/Media/Decoders/VideoDecoder.h create mode 100644 include/Engine/Media/MediaPlayer.h create mode 100644 include/Engine/Media/MediaSource.h create mode 100644 include/Engine/Media/Utils/MediaPlayerState.h create mode 100644 include/Engine/Media/Utils/PtrBuffer.h create mode 100644 include/Engine/Media/Utils/RingBuffer.h create mode 100644 include/Engine/Network/HTTP.h create mode 100644 include/Engine/Network/WebSocketClient.h create mode 100644 include/Engine/Rendering/D3D/D3DRenderer.h create mode 100644 include/Engine/Rendering/FaceInfo.h create mode 100644 include/Engine/Rendering/GL/GLRenderer.h create mode 100644 include/Engine/Rendering/GL/GLShader.h create mode 100644 include/Engine/Rendering/GL/GLShaderBuilder.h create mode 100644 include/Engine/Rendering/GL/GLShaderContainer.h create mode 100644 include/Engine/Rendering/GameTexture.h create mode 100644 include/Engine/Rendering/Material.h create mode 100644 include/Engine/Rendering/ModelRenderer.h create mode 100644 include/Engine/Rendering/PolygonRenderer.h create mode 100644 include/Engine/Rendering/SDL2/SDL2Renderer.h create mode 100644 include/Engine/Rendering/Shader.h create mode 100644 include/Engine/Rendering/Software/PolygonRasterizer.h create mode 100644 include/Engine/Rendering/Software/Scanline.h create mode 100644 include/Engine/Rendering/Software/SoftwareRenderer.h create mode 100644 include/Engine/Rendering/Texture.h create mode 100644 include/Engine/Rendering/TextureReference.h create mode 100644 include/Engine/Rendering/VertexBuffer.h create mode 100644 include/Engine/Rendering/ViewTexture.h create mode 100644 include/Engine/ResourceTypes/IModel.h create mode 100644 include/Engine/ResourceTypes/ISound.h create mode 100644 include/Engine/ResourceTypes/ISprite.h create mode 100644 include/Engine/ResourceTypes/Image.h create mode 100644 include/Engine/ResourceTypes/ImageFormats/GIF.h create mode 100644 include/Engine/ResourceTypes/ImageFormats/ImageFormat.h create mode 100644 include/Engine/ResourceTypes/ImageFormats/JPEG.h create mode 100644 include/Engine/ResourceTypes/ImageFormats/PNG.h create mode 100644 include/Engine/ResourceTypes/ModelFormats/HatchModel.h create mode 100644 include/Engine/ResourceTypes/ModelFormats/Importer.h create mode 100644 include/Engine/ResourceTypes/ModelFormats/MD3Model.h create mode 100644 include/Engine/ResourceTypes/ModelFormats/RSDKModel.h create mode 100644 include/Engine/ResourceTypes/ResourceManager.h create mode 100644 include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h create mode 100644 include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h create mode 100644 include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h create mode 100644 include/Engine/ResourceTypes/SoundFormats/OGG.h create mode 100644 include/Engine/ResourceTypes/SoundFormats/SoundFormat.h create mode 100644 include/Engine/ResourceTypes/SoundFormats/WAV.h create mode 100644 include/Engine/Scene.h create mode 100644 include/Engine/Scene/SceneInfo.h create mode 100644 include/Engine/Scene/SceneLayer.h create mode 100644 include/Engine/Scene/ScrollingIndex.h create mode 100644 include/Engine/Scene/ScrollingInfo.h create mode 100644 include/Engine/Scene/TileConfig.h create mode 100644 include/Engine/Scene/TileSpriteInfo.h create mode 100644 include/Engine/Scene/View.h create mode 100644 include/Engine/TextFormats/INI/INI.h create mode 100644 include/Engine/TextFormats/XML/XMLParser.h create mode 100644 include/Engine/Types/DrawGroupList.h create mode 100644 include/Engine/Types/Entity.h create mode 100644 include/Engine/Types/ObjectList.h create mode 100644 include/Engine/Types/ObjectRegistry.h create mode 100644 include/Engine/Types/Tileset.h create mode 100644 include/Engine/Utilities/ColorUtils.h create mode 100644 include/Engine/Utilities/StringUtils.h delete mode 100755 tools/makeheaders delete mode 100644 tools/makeheaders-src/crc32.h delete mode 100644 tools/makeheaders-src/main.cpp delete mode 100644 tools/makeheaders.exe delete mode 100644 tools/makeheaders2-src/crc32.h delete mode 100644 tools/makeheaders2-src/dirent.c delete mode 100644 tools/makeheaders2-src/dirent.h delete mode 100644 tools/makeheaders2-src/makeheaders.cpp diff --git a/.gitignore b/.gitignore index 9634f5d4..d70d313e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,6 @@ HatchGameEngine.exe *-Debug.exe *-Release.exe -makeheaders.bin -include/* # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/CMakeLists.txt b/CMakeLists.txt index b26b0eb2..0051b96a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,18 +87,6 @@ endif() add_definitions(-DMINIZ_NO_ARCHIVE_APIS -DMINIZ_NO_ARCHIVE_WRITING_APIS -DMINIZ_NO_TIME ) -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(MAKEHEADERS_BINARY makeheaders.exe) -else() - set(MAKEHEADERS_BINARY makeheaders) -endif() - -add_custom_target(makeheaders ALL - COMMAND ${CMAKE_SOURCE_DIR}/tools/${MAKEHEADERS_BINARY} source/ - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - BYPRODUCTS "${CMAKE_SOURCE_DIR}/include/makeheaders.bin" "${CMAKE_SOURCE_DIR}/include/Engine" - COMMENT "Generating header files") - find_file(REPO_DIR NAMES .git PATHS ${CMAKE_SOURCE_DIR} NO_DEFAULT_PATH) if (REPO_DIR) @@ -112,7 +100,6 @@ if (REPO_DIR) endif() add_executable(${PROJECT_NAME} ${HATCH_SOURCES}) -add_dependencies(${PROJECT_NAME} makeheaders) set(OUT_EXEC_NAME ${PROJECT_NAME}) diff --git a/Makefile b/Makefile index 3daef30d..cd41dc1b 100644 --- a/Makefile +++ b/Makefile @@ -37,12 +37,6 @@ ifeq ($(PLATFORM),$(PLATFORM_WINDOWS)) PROGRAM_SUFFIX := .exe endif -ifeq ($(PLATFORM),$(PLATFORM_LINUX)) -MAKEHEADERS := ./tools/makeheaders -else -MAKEHEADERS := ./tools/makeheaders$(PROGRAM_SUFFIX) -endif - USING_LIBAV = 0 USING_CURL = 0 USING_LIBPNG = 1 @@ -143,7 +137,6 @@ endif all: mkdir -p $(OBJ_DIRS) - $(MAKEHEADERS) source $(MAKE) build clean: @@ -164,7 +157,6 @@ package: @mkdir -p "$(TARGETDIR).app/Contents/Resources" @# @rm -rf $(OBJS) @mkdir -p $(OBJ_DIRS) - @./tools/makeheaders source @make build @chmod +x "$(TARGETDIR)" @cp "$(TARGETDIR)" "$(TARGETDIR).app/Contents/MacOS/$(TARGET)" diff --git a/include/Engine/Application.h b/include/Engine/Application.h new file mode 100644 index 00000000..63f070e1 --- /dev/null +++ b/include/Engine/Application.h @@ -0,0 +1,98 @@ +#ifndef ENGINE_APPLICATION_H +#define ENGINE_APPLICATION_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Application { +private: + static void MakeEngineVersion(); + static void Restart(); + static void LoadAudioSettings(); + static void LoadKeyBinds(); + static void LoadDevSettings(); + static void PollEvents(); + static void RunFrame(void* p); + static void DelayFrame(); + static void LoadGameConfig(); + static void DisposeGameConfig(); + static string ParseGameVersion(XMLNode* versionNode); + static void LoadGameInfo(); + static int HandleAppEvents(void* data, SDL_Event* event); + +public: + static vector CmdLineArgs; + static INI* Settings; + static char SettingsFile[4096]; + static XMLNode* GameConfig; + static int TargetFPS; + static float CurrentFPS; + static bool Running; + static bool GameStart; + static SDL_Window* Window; + static char WindowTitle[256]; + static int WindowWidth; + static int WindowHeight; + static int DefaultMonitor; + static Platforms Platform; + static char EngineVersion[256]; + static char GameTitle[256]; + static char GameTitleShort[256]; + static char GameVersion[256]; + static char GameDescription[256]; + static int UpdatesPerFrame; + static bool Stepper; + static bool Step; + static int MasterVolume; + static int MusicVolume; + static int SoundVolume; + static int StartSceneNum; + static bool DevMenuActivated; + + static void Init(int argc, char* args[]); + static void SetTargetFrameRate(int targetFPS); + static bool IsPC(); + static bool IsMobile(); + static void GetPerformanceSnapshot(); + static void SetWindowTitle(const char* title); + static void UpdateWindowTitle(); + static void SetMasterVolume(int volume); + static void SetMusicVolume(int volume); + static void SetSoundVolume(int volume); + static bool IsWindowResizeable(); + static void SetWindowSize(int window_w, int window_h); + static bool GetWindowFullscreen(); + static void SetWindowFullscreen(bool isFullscreen); + static void SetWindowBorderless(bool isBorderless); + static int GetKeyBind(int bind); + static void SetKeyBind(int bind, int key); + static void Run(int argc, char* args[]); + static void Cleanup(); + static void LoadSceneInfo(); + static void InitPlayerControls(); + static bool LoadSettings(const char* filename); + static void ReadSettings(); + static void ReloadSettings(); + static void ReloadSettings(const char* filename); + static void InitSettings(const char* filename); + static void SaveSettings(); + static void SaveSettings(const char* filename); + static void SetSettingsFilename(const char* filename); +}; + +#endif /* ENGINE_APPLICATION_H */ diff --git a/include/Engine/Audio/AudioManager.h b/include/Engine/Audio/AudioManager.h new file mode 100644 index 00000000..6b83e69c --- /dev/null +++ b/include/Engine/Audio/AudioManager.h @@ -0,0 +1,89 @@ +#ifndef ENGINE_AUDIO_AUDIOMANAGER_H +#define ENGINE_AUDIO_AUDIOMANAGER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include + +class AudioManager { +private: + static void UpdateChannelPlayer(AudioPlayback* playback, ISound* sound); + static bool HandleFading(AudioChannel* audio); + +public: + static SDL_AudioDeviceID Device; + static SDL_AudioSpec DeviceFormat; + static bool AudioEnabled; + static Uint8 BytesPerSample; + static Uint8* MixBuffer; + static size_t MixBufferSize; + static deque MusicStack; + static AudioChannel* SoundArray; + static int SoundArrayLength; + static float MasterVolume; + static float MusicVolume; + static float SoundVolume; + static float LowPassFilter; + static Uint8* AudioQueue; + static size_t AudioQueueSize; + static size_t AudioQueueMaxSize; + enum { + REQUEST_EOF = 0, + REQUEST_ERROR = -1, + REQUEST_CONVERTING = -2, + }; + + static void CalculateCoeffs(); + static Sint16 ProcessSample(Sint16 inSample, int channel); + static float ProcessSampleFloat(float inSample, int channel); + static void Init(); + static void ClampParams(float& pan, float& speed, float& volume); + static void SetSound(int channel, ISound* music); + static void SetSound(int channel, ISound* sound, bool loop, int loopPoint, float pan, float speed, float volume, void* origin); + static int PlaySound(ISound* music); + static int PlaySound(ISound* music, bool loop, int loopPoint, float pan, float speed, float volume, void* origin); + static void PushMusic(ISound* music, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished); + static void PushMusicAt(ISound* music, double at, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished); + static void RemoveMusic(ISound* music); + static bool IsPlayingMusic(); + static bool IsPlayingMusic(ISound* music); + static void ClearMusic(); + static void ClearSounds(); + static void FadeOutMusic(double seconds); + static void AlterMusic(float pan, float speed, float volume); + static double GetMusicPosition(ISound* music); + static void Lock(); + static void Unlock(); + static int GetFreeChannel(); + static void AlterChannel(int channel, float pan, float speed, float volume); + static bool AudioIsPlaying(int channel); + static bool AudioIsPlaying(ISound* audio); + static void AudioUnpause(int channel); + static void AudioUnpause(ISound* audio); + static void AudioPause(int channel); + static void AudioPause(ISound* audio); + static void AudioStop(int channel); + static void AudioStop(ISound* audio); + static void AudioUnpauseAll(); + static void AudioPauseAll(); + static void AudioStopAll(); + static bool IsOriginPlaying(void* origin, ISound* audio); + static void StopOriginSound(void* origin, ISound* audio); + static void StopAllOriginSounds(void* origin); + static void MixAudioLR(Uint8* dest, Uint8* src, size_t len, float volumeL, float volumeR); + static bool AudioPlayMix(AudioChannel* audio, Uint8* stream, int len, float volume); + static void AudioCallback(void* data, Uint8* stream, int len); + static void Dispose(); +}; + +#endif /* ENGINE_AUDIO_AUDIOMANAGER_H */ diff --git a/include/Engine/Audio/AudioPlayback.h b/include/Engine/Audio/AudioPlayback.h new file mode 100644 index 00000000..5228e85f --- /dev/null +++ b/include/Engine/Audio/AudioPlayback.h @@ -0,0 +1,41 @@ +#ifndef ENGINE_AUDIO_AUDIOPLAYBACK_H +#define ENGINE_AUDIO_AUDIOPLAYBACK_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class AudioPlayback { +private: + void CreateConversionStream(SDL_AudioSpec format); + +public: + Uint8* Buffer = NULL; + Uint8* UnconvertedSampleBuffer = NULL; + Uint32 BufferedSamples = 0; + SDL_AudioSpec Format; + size_t BytesPerSample = 0; + size_t RequiredSamples = 0; + size_t DeviceBytesPerSample = 0; + SDL_AudioStream* ConversionStream = NULL; + SoundFormat* SoundData = NULL; + bool OwnsSoundData = false; + Sint32 LoopIndex = -1; + + AudioPlayback(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample); + void Change(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample); + void Dispose(); + int RequestSamples(int samples, bool loop, int sample_to_loop_to); + void Seek(int samples); + ~AudioPlayback(); +}; + +#endif /* ENGINE_AUDIO_AUDIOPLAYBACK_H */ diff --git a/include/Engine/Bytecode/Bytecode.h b/include/Engine/Bytecode/Bytecode.h new file mode 100644 index 00000000..5f029555 --- /dev/null +++ b/include/Engine/Bytecode/Bytecode.h @@ -0,0 +1,31 @@ +#ifndef ENGINE_BYTECODE_BYTECODE_H +#define ENGINE_BYTECODE_BYTECODE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Bytecode { +public: + static const char* Magic; + static Uint32 LatestVersion; + static vector FunctionNames; + vector Functions; + Uint8 Version; + bool HasDebugInfo = false; + const char* SourceFilename = nullptr; + + Bytecode(); + ~Bytecode(); + bool Read(BytecodeContainer bytecode, HashMap* tokens); + void Write(Stream* stream, const char* sourceFilename, HashMap* tokenMap); +}; + +#endif /* ENGINE_BYTECODE_BYTECODE_H */ diff --git a/include/Engine/Bytecode/Compiler.h b/include/Engine/Bytecode/Compiler.h new file mode 100644 index 00000000..f1fbf748 --- /dev/null +++ b/include/Engine/Bytecode/Compiler.h @@ -0,0 +1,221 @@ +#ifndef ENGINE_BYTECODE_COMPILER_H +#define ENGINE_BYTECODE_COMPILER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Compiler { +private: + void WarnVariablesUnused(); + void WriteBytecode(Stream* stream, const char* filename); + +public: + static Parser parser; + static Scanner scanner; + static ParseRule* Rules; + static vector Functions; + static vector ModuleLocals; + static HashMap* TokenMap; + static bool ShowWarnings; + static bool WriteDebugInfo; + static bool WriteSourceFilename; + Compiler* Enclosing = nullptr; + ObjFunction* Function = nullptr; + int Type = 0; + string ClassName; + Local Locals[0x100]; + int LocalCount = 0; + int ScopeDepth = 0; + vector ClassHashList; + vector ClassExtendedList; + vector* UnusedVariables = nullptr; + + Token MakeToken(int type); + Token MakeTokenRaw(int type, const char* message); + Token ErrorToken(const char* message); + bool IsEOF(); + bool IsDigit(char c); + bool IsHexDigit(char c); + bool IsAlpha(char c); + bool IsIdentifierStart(char c); + bool IsIdentifierBody(char c); + bool MatchChar(char expected); + char AdvanceChar(); + char PrevChar(); + char PeekChar(); + char PeekNextChar(); + virtual void SkipWhitespace(); + int CheckKeyword(int start, int length, const char* rest, int type); + virtual int GetKeywordType(); + Token StringToken(); + Token NumberToken(); + Token IdentifierToken(); + virtual Token ScanToken(); + void AdvanceToken(); + Token NextToken(); + Token PeekToken(); + Token PeekNextToken(); + Token PrevToken(); + bool MatchToken(int expectedType); + bool MatchAssignmentToken(); + bool CheckToken(int expectedType); + void ConsumeToken(int type, const char* message); + void SynchronizeToken(); + bool ReportError(int line, bool fatal, const char* string, ...); + bool ReportErrorPos(int line, int pos, bool fatal, const char* string, ...); + void ErrorAt(Token* token, const char* message, bool fatal); + void Error(const char* message); + void ErrorAtCurrent(const char* message); + void Warning(const char* message); + void WarningInFunction(const char* format, ...); + void ParseVariable(const char* errorMessage); + bool IdentifiersEqual(Token* a, Token* b); + void MarkInitialized(); + void DefineVariableToken(Token global); + void DeclareVariable(Token* name); + int ParseModuleVariable(const char* errorMessage); + void DefineModuleVariable(int local); + int DeclareModuleVariable(Token* name); + void EmitSetOperation(Uint8 setOp, int arg, Token name); + void EmitGetOperation(Uint8 getOp, int arg, Token name); + void EmitAssignmentToken(Token assignmentToken); + void EmitCopy(Uint8 count); + void EmitCall(const char *name, int argCount, bool isSuper); + void EmitCall(Token name, int argCount, bool isSuper); + void NamedVariable(Token name, bool canAssign); + void ScopeBegin(); + void ScopeEnd(); + void ClearToScope(int depth); + void PopToScope(int depth); + void PopMultiple(int count); + int AddLocal(Token name); + int AddLocal(const char* name, size_t len); + int AddHiddenLocal(const char* name, size_t len); + void RenameLocal(Local* local, const char* name, size_t len); + void RenameLocal(Local* local, const char* name); + void RenameLocal(Local* local, Token name); + int ResolveLocal(Token* name); + int AddModuleLocal(Token name); + int ResolveModuleLocal(Token* name); + Uint8 GetArgumentList(); + void GetThis(bool canAssign); + void GetSuper(bool canAssign); + void GetDot(bool canAssign); + void GetElement(bool canAssign); + void GetGrouping(bool canAssign); + void GetLiteral(bool canAssign); + void GetInteger(bool canAssign); + void GetDecimal(bool canAssign); + ObjString* MakeString(Token token); + void GetString(bool canAssign); + void GetArray(bool canAssign); + void GetMap(bool canAssign); + bool IsConstant(); + void GetConstant(bool canAssign); + int GetConstantValue(); + void GetVariable(bool canAssign); + void GetLogicalAND(bool canAssign); + void GetLogicalOR(bool canAssign); + void GetConditional(bool canAssign); + void GetUnary(bool canAssign); + void GetNew(bool canAssign); + void GetBinary(bool canAssign); + void GetHas(bool canAssign); + void GetSuffix(bool canAssign); + void GetCall(bool canAssign); + void GetExpression(); + void GetPrintStatement(); + void GetExpressionStatement(); + void GetContinueStatement(); + void GetDoWhileStatement(); + void GetReturnStatement(); + void GetRepeatStatement(); + void GetSwitchStatement(); + void GetCaseStatement(); + void GetDefaultStatement(); + void GetWhileStatement(); + void GetBreakStatement(); + void GetBlockStatement(); + void GetWithStatement(); + void GetForStatement(); + void GetForEachStatement(); + void GetIfStatement(); + void GetStatement(); + int GetFunction(int type, string className); + int GetFunction(int type); + void GetMethod(Token className); + void GetVariableDeclaration(); + void GetModuleVariableDeclaration(); + void GetPropertyDeclaration(Token propertyName); + void GetClassDeclaration(); + void GetEnumDeclaration(); + void GetImportDeclaration(); + void GetUsingDeclaration(); + void GetEventDeclaration(); + void GetDeclaration(); + static void MakeRules(); + ParseRule* GetRule(int type); + void ParsePrecedence(Precedence precedence); + Uint32 GetHash(char* string); + Uint32 GetHash(Token token); + Chunk* CurrentChunk(); + int CodePointer(); + void EmitByte(Uint8 byte); + void EmitBytes(Uint8 byte1, Uint8 byte2); + void EmitUint16(Uint16 value); + void EmitUint32(Uint32 value); + int GetConstantIndex(VMValue value); + int EmitConstant(VMValue value); + void EmitLoop(int loopStart); + int GetJump(int offset); + int GetPosition(); + int EmitJump(Uint8 instruction); + int EmitJump(Uint8 instruction, int jump); + void PatchJump(int offset, int jump); + void PatchJump(int offset); + void EmitStringHash(const char* string); + void EmitStringHash(Token token); + void EmitReturn(); + void StartBreakJumpList(); + void EndBreakJumpList(); + void StartContinueJumpList(); + void EndContinueJumpList(); + void StartSwitchJumpList(); + void EndSwitchJumpList(); + int FindConstant(VMValue value); + int MakeConstant(VMValue value); + bool HasThis(); + void SetReceiverName(const char *name); + void SetReceiverName(Token name); + static int HashInstruction(const char* name, Chunk* chunk, int offset); + static int ConstantInstruction(const char* name, Chunk* chunk, int offset); + static int SimpleInstruction(const char* name, int offset); + static int ByteInstruction(const char* name, Chunk* chunk, int offset); + static int LocalInstruction(const char* name, Chunk* chunk, int offset); + static int MethodInstruction(const char* name, Chunk* chunk, int offset); + static int InvokeInstruction(const char* name, Chunk* chunk, int offset); + static int JumpInstruction(const char* name, int sign, Chunk* chunk, int offset); + static int ClassInstruction(const char* name, Chunk* chunk, int offset); + static int EnumInstruction(const char* name, Chunk* chunk, int offset); + static int WithInstruction(const char* name, Chunk* chunk, int offset); + static int DebugInstruction(Chunk* chunk, int offset); + static void DebugChunk(Chunk* chunk, const char* name, int minArity, int maxArity); + static void Init(); + static void PrepareCompiling(); + void Initialize(Compiler* enclosing, int scope, int type); + bool Compile(const char* filename, const char* source, const char* output); + void Finish(); + virtual ~Compiler(); + static void FinishCompiling(); + static void Dispose(); +}; + +#endif /* ENGINE_BYTECODE_COMPILER_H */ diff --git a/include/Engine/Bytecode/GarbageCollector.h b/include/Engine/Bytecode/GarbageCollector.h new file mode 100644 index 00000000..3729e8c2 --- /dev/null +++ b/include/Engine/Bytecode/GarbageCollector.h @@ -0,0 +1,38 @@ +#ifndef ENGINE_BYTECODE_GARBAGECOLLECTOR_H +#define ENGINE_BYTECODE_GARBAGECOLLECTOR_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class GarbageCollector { +private: + static void FreeValue(VMValue value); + static void GrayValue(VMValue value); + static void GrayObject(void* obj); + static void GrayHashMapItem(Uint32, VMValue value); + static void GrayHashMap(void* pointer); + static void BlackenObject(Obj* object); + +public: + static vector GrayList; + static Obj* RootObject; + static size_t NextGC; + static size_t GarbageSize; + static double MaxTimeAlotted; + static bool Print; + static bool FilterSweepEnabled; + static int FilterSweepType; + + static void Init(); + static void Collect(); +}; + +#endif /* ENGINE_BYTECODE_GARBAGECOLLECTOR_H */ diff --git a/include/Engine/Bytecode/ScriptEntity.h b/include/Engine/Bytecode/ScriptEntity.h new file mode 100644 index 00000000..9c24a69c --- /dev/null +++ b/include/Engine/Bytecode/ScriptEntity.h @@ -0,0 +1,81 @@ +#ifndef ENGINE_BYTECODE_SCRIPTENTITY_H +#define ENGINE_BYTECODE_SCRIPTENTITY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ScriptEntity : public Entity { +private: + bool GetCallableValue(Uint32 hash, VMValue& value); + ObjFunction* GetCallableFunction(Uint32 hash); + +public: + static bool DisableAutoAnimate; + ObjInstance* Instance = NULL; + HashMap* Properties; + + void Link(ObjInstance* instance); + void LinkFields(); + bool RunFunction(Uint32 hash); + bool RunCreateFunction(VMValue flag); + bool RunInitializer(); + bool ChangeClass(const char* className); + void Copy(ScriptEntity* other, bool copyClass); + void CopyFields(ScriptEntity* other); + void CopyVMFields(ScriptEntity* other); + void Initialize(); + void Create(VMValue flag); + void Create(); + void PostCreate(); + void UpdateEarly(); + void Update(); + void UpdateLate(); + void RenderEarly(); + void Render(int CamX, int CamY); + void RenderLate(); + void OnAnimationFinish(); + void OnSceneLoad(); + void OnSceneRestart(); + void GameStart(); + void Remove(); + void Dispose(); + static bool VM_Getter(Obj* object, Uint32 hash, VMValue* result, Uint32 threadID); + static bool VM_Setter(Obj* object, Uint32 hash, VMValue value, Uint32 threadID); + static VMValue VM_SetAnimation(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_ResetAnimation(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_Animate(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_GetIDWithinClass(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_AddToRegistry(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_IsInRegistry(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_RemoveFromRegistry(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_ApplyMotion(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_InView(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_CollidedWithObject(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_GetHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_ReturnHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_CollideWithObject(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_SolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_TopSolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_ApplyPhysics(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_PropertyExists(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_PropertyGet(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_SetViewVisibility(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_SetViewOverride(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_AddToDrawGroup(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_IsInDrawGroup(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_RemoveFromDrawGroup(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_PlaySound(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_LoopSound(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_StopSound(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_StopAllSounds(int argCount, VMValue* args, Uint32 threadID); +}; + +#endif /* ENGINE_BYTECODE_SCRIPTENTITY_H */ diff --git a/include/Engine/Bytecode/ScriptManager.h b/include/Engine/Bytecode/ScriptManager.h new file mode 100644 index 00000000..1edd8217 --- /dev/null +++ b/include/Engine/Bytecode/ScriptManager.h @@ -0,0 +1,97 @@ +#ifndef ENGINE_BYTECODE_SCRIPTMANAGER_H +#define ENGINE_BYTECODE_SCRIPTMANAGER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class ScriptEntity; + +#include +#include +#include +#include +#include +#include +#include +#include + +class ScriptManager { +private: + static Uint32 GetBranchLimit(); + static void RemoveNonGlobalableValue(Uint32 hash, VMValue value); + static void FreeNativeValue(Uint32 hash, VMValue value); + static void FreeFunction(ObjFunction* function); + static void FreeModule(ObjModule* module); + static void FreeClass(ObjClass* klass); + static void FreeEnumeration(ObjEnum* enumeration); + static void FreeNamespace(ObjNamespace* ns); + static void FreeModules(); + +public: + static bool LoadAllClasses; + static HashMap* Globals; + static HashMap* Constants; + static std::set FreedGlobals; + static VMThread Threads[8]; + static Uint32 ThreadCount; + static vector ModuleList; + static HashMap* Sources; + static HashMap* Classes; + static HashMap* Tokens; + static vector AllNamespaces; + static vector ClassImplList; + static SDL_mutex* GlobalLock; + + static void RequestGarbageCollection(); + static void ForceGarbageCollection(); + static void ResetStack(); + static void Init(); + static void DisposeGlobalValueTable(HashMap* globals); + static void Dispose(); + static void FreeString(ObjString* string); + static void FreeGlobalValue(Uint32 hash, VMValue value); + static VMValue CastValueAsString(VMValue v, bool prettyPrint); + static VMValue CastValueAsString(VMValue v); + static VMValue CastValueAsInteger(VMValue v); + static VMValue CastValueAsDecimal(VMValue v); + static VMValue Concatenate(VMValue va, VMValue vb); + static bool ValuesSortaEqual(VMValue a, VMValue b); + static bool ValuesEqual(VMValue a, VMValue b); + static bool ValueFalsey(VMValue a); + static VMValue DelinkValue(VMValue val); + static bool DoIntegerConversion(VMValue& value, Uint32 threadID); + static bool DoDecimalConversion(VMValue& value, Uint32 threadID); + static void FreeValue(VMValue value); + static bool Lock(); + static void Unlock(); + static void DefineMethod(VMThread* thread, ObjFunction* function, Uint32 hash); + static void DefineNative(ObjClass* klass, const char* name, NativeFn function); + static void GlobalLinkInteger(ObjClass* klass, const char* name, int* value); + static void GlobalLinkDecimal(ObjClass* klass, const char* name, float* value); + static void GlobalConstInteger(ObjClass* klass, const char* name, int value); + static void GlobalConstDecimal(ObjClass* klass, const char* name, float value); + static ObjClass* GetClassParent(ObjClass* klass); + static VMValue GetClassMethod(ObjClass* klass, Uint32 hash); + static void LinkStandardLibrary(); + static void LinkExtensions(); + static bool RunBytecode(BytecodeContainer bytecodeContainer, Uint32 filenameHash); + static bool CallFunction(char* functionName); + static Entity* SpawnObject(const char* objectName); + static Uint32 MakeFilenameHash(char *filename); + static BytecodeContainer GetBytecodeFromFilenameHash(Uint32 filenameHash); + static bool ClassExists(const char* objectName); + static bool LoadScript(char* filename); + static bool LoadScript(const char* filename); + static bool LoadScript(Uint32 hash); + static bool LoadObjectClass(const char* objectName, bool addNativeFunctions); + static void AddNativeObjectFunctions(ObjClass* klass); + static ObjClass* GetObjectClass(const char* className); + static Entity* ObjectSpawnFunction(ObjectList* list); + static void LoadClasses(); +}; + +#endif /* ENGINE_BYTECODE_SCRIPTMANAGER_H */ diff --git a/include/Engine/Bytecode/SourceFileMap.h b/include/Engine/Bytecode/SourceFileMap.h new file mode 100644 index 00000000..8f74d83d --- /dev/null +++ b/include/Engine/Bytecode/SourceFileMap.h @@ -0,0 +1,29 @@ +#ifndef ENGINE_BYTECODE_SOURCEFILEMAP_H +#define ENGINE_BYTECODE_SOURCEFILEMAP_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class SourceFileMap { +public: + static bool Initialized; + static HashMap* Checksums; + static HashMap*>* ClassMap; + static Uint32 DirectoryChecksum; + static Uint32 Magic; + static bool DoLogging; + + static void CheckInit(); + static void CheckForUpdate(); + static void Dispose(); +}; + +#endif /* ENGINE_BYTECODE_SOURCEFILEMAP_H */ diff --git a/include/Engine/Bytecode/StandardLibrary.h b/include/Engine/Bytecode/StandardLibrary.h new file mode 100644 index 00000000..d5867f09 --- /dev/null +++ b/include/Engine/Bytecode/StandardLibrary.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_BYTECODE_STANDARDLIBRARY_H +#define ENGINE_BYTECODE_STANDARDLIBRARY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class StandardLibrary { +public: + static int GetInteger(VMValue* args, int index, Uint32 threadID); + static float GetDecimal(VMValue* args, int index, Uint32 threadID); + static char* GetString(VMValue* args, int index, Uint32 threadID); + static ObjString* GetVMString(VMValue* args, int index, Uint32 threadID); + static ObjArray* GetArray(VMValue* args, int index, Uint32 threadID); + static ObjMap* GetMap(VMValue* args, int index, Uint32 threadID); + static ISprite* GetSprite(VMValue* args, int index, Uint32 threadID); + static ISound* GetSound(VMValue* args, int index, Uint32 threadID); + static ObjInstance* GetInstance(VMValue* args, int index, Uint32 threadID); + static ObjFunction* GetFunction(VMValue* args, int index, Uint32 threadID); + static void CheckArgCount(int argCount, int expects); + static void CheckAtLeastArgCount(int argCount, int expects); + static void Link(); + static void Dispose(); +}; + +#endif /* ENGINE_BYTECODE_STANDARDLIBRARY_H */ diff --git a/include/Engine/Bytecode/TypeImpl/ArrayImpl.h b/include/Engine/Bytecode/TypeImpl/ArrayImpl.h new file mode 100644 index 00000000..f01680f3 --- /dev/null +++ b/include/Engine/Bytecode/TypeImpl/ArrayImpl.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_BYTECODE_TYPEIMPL_ARRAYIMPL_H +#define ENGINE_BYTECODE_TYPEIMPL_ARRAYIMPL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ArrayImpl { +public: + static ObjClass *Class; + + static void Init(); + static VMValue VM_Iterate(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID); +}; + +#endif /* ENGINE_BYTECODE_TYPEIMPL_ARRAYIMPL_H */ diff --git a/include/Engine/Bytecode/TypeImpl/FunctionImpl.h b/include/Engine/Bytecode/TypeImpl/FunctionImpl.h new file mode 100644 index 00000000..9eaf49d4 --- /dev/null +++ b/include/Engine/Bytecode/TypeImpl/FunctionImpl.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_BYTECODE_TYPEIMPL_FUNCTIONIMPL_H +#define ENGINE_BYTECODE_TYPEIMPL_FUNCTIONIMPL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class FunctionImpl { +public: + static ObjClass *Class; + + static void Init(); + static VMValue VM_Bind(int argCount, VMValue* args, Uint32 threadID); +}; + +#endif /* ENGINE_BYTECODE_TYPEIMPL_FUNCTIONIMPL_H */ diff --git a/include/Engine/Bytecode/TypeImpl/MapImpl.h b/include/Engine/Bytecode/TypeImpl/MapImpl.h new file mode 100644 index 00000000..1f5e2388 --- /dev/null +++ b/include/Engine/Bytecode/TypeImpl/MapImpl.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_BYTECODE_TYPEIMPL_MAPIMPL_H +#define ENGINE_BYTECODE_TYPEIMPL_MAPIMPL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class MapImpl { +public: + static ObjClass *Class; + + static void Init(); + static VMValue VM_GetKeys(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_Iterate(int argCount, VMValue* args, Uint32 threadID); + static VMValue VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID); +}; + +#endif /* ENGINE_BYTECODE_TYPEIMPL_MAPIMPL_H */ diff --git a/include/Engine/Bytecode/TypeImpl/StringImpl.h b/include/Engine/Bytecode/TypeImpl/StringImpl.h new file mode 100644 index 00000000..4e3ec0fd --- /dev/null +++ b/include/Engine/Bytecode/TypeImpl/StringImpl.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_BYTECODE_TYPEIMPL_STRINGIMPL_H +#define ENGINE_BYTECODE_TYPEIMPL_STRINGIMPL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class StringImpl { +public: + static ObjClass *Class; + + static void Init(); + static bool VM_ElementGet(Obj* object, VMValue at, VMValue* result, Uint32 threadID); + static bool VM_ElementSet(Obj* object, VMValue at, VMValue value, Uint32 threadID); +}; + +#endif /* ENGINE_BYTECODE_TYPEIMPL_STRINGIMPL_H */ diff --git a/include/Engine/Bytecode/VMThread.h b/include/Engine/Bytecode/VMThread.h new file mode 100644 index 00000000..123a792a --- /dev/null +++ b/include/Engine/Bytecode/VMThread.h @@ -0,0 +1,114 @@ +#ifndef ENGINE_BYTECODE_VMTHREAD_H +#define ENGINE_BYTECODE_VMTHREAD_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class VMThread { +private: + string GetFunctionName(ObjFunction* function); + void PrintStackTrace(PrintBuffer* buffer, const char* errorString); + bool CheckBranchLimit(CallFrame* frame); + bool DoJump(CallFrame* frame, int offset); + bool DoJumpBack(CallFrame* frame, int offset); + bool GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter); + bool GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields); + bool GetProperty(Obj* object, ObjClass* klass, Uint32 hash); + bool HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter); + bool HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields); + bool HasProperty(Obj* object, ObjClass* klass, Uint32 hash); + bool SetProperty(Table* fields, Uint32 hash, VMValue field, VMValue value); + bool BindMethod(VMValue receiver, VMValue method); + bool CallBoundMethod(ObjBoundMethod* bound, int argCount); + bool CallValue(VMValue callee, int argCount); + bool CallForObject(VMValue callee, int argCount); + bool InstantiateClass(VMValue callee, int argCount); + bool DoClassExtension(VMValue value, VMValue originalValue, bool clearSrc); + +public: + VMValue Stack[STACK_SIZE_MAX]; + VMValue* StackTop = Stack; + VMValue RegisterValue; + CallFrame Frames[FRAMES_MAX]; + Uint32 FrameCount; + Uint32 ReturnFrame; + VMValue FunctionToInvoke; + VMValue InterpretResult; + enum ThreadState { + CREATED = 0, + RUNNING = 1, + WAITING = 2, + CLOSED = 3, + }; + char Name[THREAD_NAME_MAX]; + Uint32 ID; + bool DebugInfo; + Uint32 BranchLimit; + static bool InstructionIgnoreMap[0x100]; + static std::jmp_buf JumpBuffer; + + static char* GetToken(Uint32 hash); + static char* GetVariableOrMethodName(Uint32 hash); + void MakeErrorMessage(PrintBuffer* buffer, const char* errorString); + int ThrowRuntimeError(bool fatal, const char* errorMessage, ...); + void PrintStack(); + void ReturnFromNative() throw(); + void Push(VMValue value); + VMValue Pop(); + void Pop(unsigned amount); + VMValue Peek(int offset); + Uint32 StackSize(); + void ResetStack(); + Uint8 ReadByte(CallFrame* frame); + Uint16 ReadUInt16(CallFrame* frame); + Uint32 ReadUInt32(CallFrame* frame); + Sint16 ReadSInt16(CallFrame* frame); + Sint32 ReadSInt32(CallFrame* frame); + VMValue ReadConstant(CallFrame* frame); + bool ShowBranchLimitMessage(const char* errorMessage, ...); + int RunInstruction(); + void RunInstructionSet(); + void RunValue(VMValue value, int argCount); + void RunFunction(ObjFunction* func, int argCount); + void InvokeForEntity(VMValue value, int argCount); + VMValue RunEntityFunction(ObjFunction* function, int argCount); + void CallInitializer(VMValue value); + bool Call(ObjFunction* function, int argCount); + bool InvokeFromClass(ObjClass* klass, Uint32 hash, int argCount); + bool InvokeForInstance(Uint32 hash, int argCount, bool isSuper); + bool Import(VMValue value); + bool ImportModule(VMValue value); + VMValue Values_Multiply(); + VMValue Values_Division(); + VMValue Values_Modulo(); + VMValue Values_Plus(); + VMValue Values_Minus(); + VMValue Values_BitwiseLeft(); + VMValue Values_BitwiseRight(); + VMValue Values_BitwiseAnd(); + VMValue Values_BitwiseXor(); + VMValue Values_BitwiseOr(); + VMValue Values_LogicalAND(); + VMValue Values_LogicalOR(); + VMValue Values_LessThan(); + VMValue Values_GreaterThan(); + VMValue Values_LessThanOrEqual(); + VMValue Values_GreaterThanOrEqual(); + VMValue Values_Increment(); + VMValue Values_Decrement(); + VMValue Values_Negate(); + VMValue Values_LogicalNOT(); + VMValue Values_BitwiseNOT(); + VMValue Value_TypeOf(); +}; + +#endif /* ENGINE_BYTECODE_VMTHREAD_H */ diff --git a/include/Engine/Bytecode/Values.h b/include/Engine/Bytecode/Values.h new file mode 100644 index 00000000..fb310d3a --- /dev/null +++ b/include/Engine/Bytecode/Values.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_BYTECODE_VALUES_H +#define ENGINE_BYTECODE_VALUES_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class Values { +public: + static void PrintValue(VMValue value); + static void PrintValue(PrintBuffer* buffer, VMValue value); + static void PrintValue(PrintBuffer* buffer, VMValue value, bool prettyPrint); + static void PrintValue(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint); + static void PrintObject(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint); +}; + +#endif /* ENGINE_BYTECODE_VALUES_H */ diff --git a/include/Engine/Diagnostics/Clock.h b/include/Engine/Diagnostics/Clock.h new file mode 100644 index 00000000..1f56bdd7 --- /dev/null +++ b/include/Engine/Diagnostics/Clock.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_DIAGNOSTICS_CLOCK_H +#define ENGINE_DIAGNOSTICS_CLOCK_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Clock { +public: + static void Init(); + static void Start(); + static double GetTicks(); + static double End(); + static void Delay(double milliseconds); +}; + +#endif /* ENGINE_DIAGNOSTICS_CLOCK_H */ diff --git a/include/Engine/Diagnostics/Log.h b/include/Engine/Diagnostics/Log.h new file mode 100644 index 00000000..6c61596e --- /dev/null +++ b/include/Engine/Diagnostics/Log.h @@ -0,0 +1,31 @@ +#ifndef ENGINE_DIAGNOSTICS_LOG_H +#define ENGINE_DIAGNOSTICS_LOG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class Log { +public: + enum LogLevels { + LOG_VERBOSE = -1, + LOG_INFO = 0, + LOG_WARN = 1, + LOG_ERROR = 2, + LOG_IMPORTANT = 3, + }; + static int LogLevel; + static const char* LogFilename; + static bool WriteToFile; + + static void Init(); + static void SetLogLevel(int sev); + static void Print(int sev, const char* format, ...); +}; + +#endif /* ENGINE_DIAGNOSTICS_LOG_H */ diff --git a/include/Engine/Diagnostics/Memory.h b/include/Engine/Diagnostics/Memory.h new file mode 100644 index 00000000..17b7596d --- /dev/null +++ b/include/Engine/Diagnostics/Memory.h @@ -0,0 +1,42 @@ +#ifndef ENGINE_DIAGNOSTICS_MEMORY_H +#define ENGINE_DIAGNOSTICS_MEMORY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Memory { +private: + static vector TrackedMemory; + static vector TrackedSizes; + static vector TrackedMemoryNames; + + +public: + static size_t MemoryUsage; + static bool IsTracking; + + static void Memset4(void* dst, Uint32 val, size_t dwords); + static void* Malloc(size_t size); + static void* Calloc(size_t count, size_t size); + static void* Realloc(void* pointer, size_t size); + static void* TrackedMalloc(const char* identifier, size_t size); + static void* TrackedCalloc(const char* identifier, size_t count, size_t size); + static void Track(void* pointer, const char* identifier); + static void Track(void* pointer, size_t size, const char* identifier); + static void TrackLast(const char* identifier); + static void Free(void* pointer); + static void Remove(void* pointer); + static const char* GetName(void* pointer); + static void ClearTrackedMemory(); + static size_t CheckLeak(); + static void PrintLeak(); +}; + +#endif /* ENGINE_DIAGNOSTICS_MEMORY_H */ diff --git a/include/Engine/Diagnostics/PerformanceMeasure.h b/include/Engine/Diagnostics/PerformanceMeasure.h new file mode 100644 index 00000000..f1066a63 --- /dev/null +++ b/include/Engine/Diagnostics/PerformanceMeasure.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_DIAGNOSTICS_PERFORMANCEMEASURE_H +#define ENGINE_DIAGNOSTICS_PERFORMANCEMEASURE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class PerformanceMeasure { +public: + static bool Initialized; + static Perf_ViewRender PERF_ViewRender[MAX_SCENE_VIEWS]; + + static void Init(); +}; + +#endif /* ENGINE_DIAGNOSTICS_PERFORMANCEMEASURE_H */ diff --git a/include/Engine/Diagnostics/RemoteDebug.h b/include/Engine/Diagnostics/RemoteDebug.h new file mode 100644 index 00000000..b0431b91 --- /dev/null +++ b/include/Engine/Diagnostics/RemoteDebug.h @@ -0,0 +1,22 @@ +#ifndef ENGINE_DIAGNOSTICS_REMOTEDEBUG_H +#define ENGINE_DIAGNOSTICS_REMOTEDEBUG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class RemoteDebug { +public: + static bool Initialized; + static bool UsingRemoteDebug; + + static void Init(); + static bool AwaitResponse(); +}; + +#endif /* ENGINE_DIAGNOSTICS_REMOTEDEBUG_H */ diff --git a/include/Engine/Extensions/Discord.h b/include/Engine/Extensions/Discord.h new file mode 100644 index 00000000..9acd9bfa --- /dev/null +++ b/include/Engine/Extensions/Discord.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_EXTENSIONS_DISCORD_H +#define ENGINE_EXTENSIONS_DISCORD_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Discord { +public: + static bool Initialized; + + static void Init(const char* application_id, const char* steam_id); + static void UpdatePresence(char* details); + static void UpdatePresence(char* details, char* state); + static void UpdatePresence(char* details, char* state, char* image_key); + static void UpdatePresence(char* details, char* state, char* image_key, time_t start_time); + static void UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max); + static void UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max, time_t start_time); + static void Dispose(); +}; + +#endif /* ENGINE_EXTENSIONS_DISCORD_H */ diff --git a/include/Engine/Filesystem/Directory.h b/include/Engine/Filesystem/Directory.h new file mode 100644 index 00000000..7a3de0d3 --- /dev/null +++ b/include/Engine/Filesystem/Directory.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_FILESYSTEM_DIRECTORY_H +#define ENGINE_FILESYSTEM_DIRECTORY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Directory { +public: + static bool Exists(const char* path); + static bool Create(const char* path); + static bool GetCurrentWorkingDirectory(char* out, size_t sz); + static void GetFiles(vector* files, const char* path, const char* searchPattern, bool allDirs); + static vector GetFiles(const char* path, const char* searchPattern, bool allDirs); + static void GetDirectories(vector* files, const char* path, const char* searchPattern, bool allDirs); + static vector GetDirectories(const char* path, const char* searchPattern, bool allDirs); +}; + +#endif /* ENGINE_FILESYSTEM_DIRECTORY_H */ diff --git a/include/Engine/Filesystem/File.h b/include/Engine/Filesystem/File.h new file mode 100644 index 00000000..e8f893c9 --- /dev/null +++ b/include/Engine/Filesystem/File.h @@ -0,0 +1,21 @@ +#ifndef ENGINE_FILESYSTEM_FILE_H +#define ENGINE_FILESYSTEM_FILE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class File { +public: + static bool Exists(const char* path); + static size_t ReadAllBytes(const char* path, char** out); + static bool WriteAllBytes(const char* path, const char* bytes, size_t len); +}; + +#endif /* ENGINE_FILESYSTEM_FILE_H */ diff --git a/include/Engine/FontFace.h b/include/Engine/FontFace.h new file mode 100644 index 00000000..729877a0 --- /dev/null +++ b/include/Engine/FontFace.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_FONTFACE_H +#define ENGINE_FONTFACE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include + +class FontFace { +public: + static ISprite* SpriteFromFont(Stream* stream, int pixelSize, char* filename); +}; + +#endif /* ENGINE_FONTFACE_H */ diff --git a/include/Engine/Graphics.h b/include/Engine/Graphics.h new file mode 100644 index 00000000..7ebe130f --- /dev/null +++ b/include/Engine/Graphics.h @@ -0,0 +1,198 @@ +#ifndef ENGINE_GRAPHICS_H +#define ENGINE_GRAPHICS_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class ISprite; +class IModel; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Graphics { +public: + static HashMap* TextureMap; + static map SpriteSheetTextureMap; + static bool VsyncEnabled; + static int MultisamplingEnabled; + static int FontDPI; + static bool SupportsBatching; + static bool TextureBlend; + static bool TextureInterpolate; + static Uint32 PreferredPixelFormat; + static Uint32 MaxTextureWidth; + static Uint32 MaxTextureHeight; + static Texture* TextureHead; + static vector VertexBuffers; + static Scene3D Scene3Ds[MAX_3D_SCENES]; + static stack StateStack; + static stack MatrixStack; + static Matrix4x4* ModelViewMatrix; + static Viewport CurrentViewport; + static Viewport BackupViewport; + static ClipArea CurrentClip; + static ClipArea BackupClip; + static View* CurrentView; + static float BlendColors[4]; + static float TintColors[4]; + static int BlendMode; + static int TintMode; + static int StencilTest; + static int StencilOpPass; + static int StencilOpFail; + static void* FramebufferPixels; + static size_t FramebufferSize; + static Uint32 PaletteColors[MAX_PALETTE_COUNT][0x100]; + static Uint8 PaletteIndexLines[MAX_FRAMEBUFFER_HEIGHT]; + static bool PaletteUpdated; + static Texture* PaletteTexture; + static Texture* CurrentRenderTarget; + static Sint32 CurrentScene3D; + static Sint32 CurrentVertexBuffer; + static void* CurrentShader; + static bool SmoothFill; + static bool SmoothStroke; + static float PixelOffset; + static bool NoInternalTextures; + static bool UsePalettes; + static bool UsePaletteIndexLines; + static bool UseTinting; + static bool UseDepthTesting; + static bool UseSoftwareRenderer; + static unsigned CurrentFrame; + // Rendering functions + static GraphicsFunctions Internal; + static GraphicsFunctions* GfxFunctions; + static const char* Renderer; + + static void Init(); + static void ChooseBackend(); + static Uint32 GetWindowFlags(); + static void SetVSync(bool enabled); + static void Reset(); + static void Dispose(); + static Point ProjectToScreen(float x, float y, float z); + static Texture* CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + static Texture* CreateTextureFromPixels(Uint32 width, Uint32 height, void* pixels, int pitch); + static Texture* CreateTextureFromSurface(SDL_Surface* surface); + static int LockTexture(Texture* texture, void** pixels, int* pitch); + static int UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch); + static int UpdateYUVTexture(Texture* texture, SDL_Rect* src, Uint8* pixelsY, int pitchY, Uint8* pixelsU, int pitchU, Uint8* pixelsV, int pitchV); + static int SetTexturePalette(Texture* texture, void* palette, unsigned numPaletteColors); + static int ConvertTextureToRGBA(Texture* texture); + static int ConvertTextureToPalette(Texture* texture, unsigned paletteNumber); + static void UnlockTexture(Texture* texture); + static void DisposeTexture(Texture* texture); + static TextureReference* GetSpriteSheet(string sheetPath); + static TextureReference* AddSpriteSheet(string sheetPath, Texture* texture); + static void DisposeSpriteSheet(string sheetPath); + static void DeleteSpriteSheetMap(); + static Uint32 CreateVertexBuffer(Uint32 maxVertices, int unloadPolicy); + static void DeleteVertexBuffer(Uint32 vertexBufferIndex); + static void UseShader(void* shader); + static void SetTextureInterpolation(bool interpolate); + static void Clear(); + static void Present(); + static void SoftwareStart(); + static void SoftwareEnd(); + static void UpdateGlobalPalette(); + static void UnloadSceneData(); + static void SetRenderTarget(Texture* texture); + static void CopyScreen(int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h, Texture* texture); + static void UpdateOrtho(float width, float height); + static void UpdateOrthoFlipped(float width, float height); + static void UpdatePerspective(float fovy, float aspect, float nearv, float farv); + static void UpdateProjectionMatrix(); + static void MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect); + static void CalculateMVPMatrix(Matrix4x4* output, Matrix4x4* modelMatrix, Matrix4x4* viewMatrix, Matrix4x4* projMatrix); + static void SetViewport(float x, float y, float w, float h); + static void ResetViewport(); + static void Resize(int width, int height); + static void SetClip(int x, int y, int width, int height); + static void ClearClip(); + static void Save(); + static void Translate(float x, float y, float z); + static void Rotate(float x, float y, float z); + static void Scale(float x, float y, float z); + static void Restore(); + static BlendState GetBlendState(); + static void PushState(); + static void PopState(); + static void SetBlendColor(float r, float g, float b, float a); + static void SetBlendMode(int blendMode); + static void SetBlendMode(int srcC, int dstC, int srcA, int dstA); + static void SetTintColor(float r, float g, float b, float a); + static void SetTintMode(int mode); + static void SetTintEnabled(bool enabled); + static void SetLineWidth(float n); + static void StrokeLine(float x1, float y1, float x2, float y2); + static void StrokeCircle(float x, float y, float rad, float thickness); + static void StrokeEllipse(float x, float y, float w, float h); + static void StrokeTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void StrokeRectangle(float x, float y, float w, float h); + static void FillCircle(float x, float y, float rad); + static void FillEllipse(float x, float y, float w, float h); + static void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void FillRectangle(float x, float y, float w, float h); + static void DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation); + static void DrawTile(int tile, int x, int y, bool flipX, bool flipY); + static void DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView); + static void DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView); + static void DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction); + static void RunCustomSceneLayerFunction(ObjFunction* func, int layerIndex); + static void DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void BindVertexBuffer(Uint32 vertexBufferIndex); + static void UnbindVertexBuffer(); + static void BindScene3D(Uint32 sceneIndex); + static void ClearScene3D(Uint32 sceneIndex); + static void DrawScene3D(Uint32 sceneIndex, Uint32 drawMode); + static Uint32 CreateScene3D(int unloadPolicy); + static void DeleteScene3D(Uint32 sceneIndex); + static void InitScene3D(Uint32 sceneIndex, Uint32 numVertices); + static void MakeSpritePolygon(VertexAttribute data[4], float x, float y, float z, int flipX, int flipY, float scaleX, float scaleY, Texture* texture, int frameX, int frameY, int frameW, int frameH); + static void MakeSpritePolygonUVs(VertexAttribute data[4], int flipX, int flipY, Texture* texture, int frameX, int frameY, int frameW, int frameH); + static void MakeFrameBufferID(ISprite* sprite, AnimFrame* frame); + static void DeleteFrameBufferID(AnimFrame* frame); + static void SetDepthTesting(bool enabled); + static bool SpriteRangeCheck(ISprite* sprite, int animation, int frame); + static void ConvertFromARGBtoNative(Uint32* argb, int count); + static void ConvertFromNativeToARGB(Uint32* argb, int count); + static void SetStencilEnabled(bool enabled); + static bool GetStencilEnabled(); + static void SetStencilTestFunc(int stencilTest); + static void SetStencilPassFunc(int stencilOp); + static void SetStencilFailFunc(int stencilOp); + static void SetStencilValue(int value); + static void SetStencilMask(int mask); + static void ClearStencil(); +}; + +#endif /* ENGINE_GRAPHICS_H */ diff --git a/include/Engine/Hashing/CRC32.h b/include/Engine/Hashing/CRC32.h new file mode 100644 index 00000000..0e6a8998 --- /dev/null +++ b/include/Engine/Hashing/CRC32.h @@ -0,0 +1,22 @@ +#ifndef ENGINE_HASHING_CRC32_H +#define ENGINE_HASHING_CRC32_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class CRC32 { +public: + static Uint32 EncryptString(char* data); + static Uint32 EncryptString(const char* message); + static Uint32 EncryptData(const void* data, size_t size); + static Uint32 EncryptData(const void* data, size_t size, Uint32 crc); +}; + +#endif /* ENGINE_HASHING_CRC32_H */ diff --git a/include/Engine/Hashing/CombinedHash.h b/include/Engine/Hashing/CombinedHash.h new file mode 100644 index 00000000..582f4ba7 --- /dev/null +++ b/include/Engine/Hashing/CombinedHash.h @@ -0,0 +1,21 @@ +#ifndef ENGINE_HASHING_COMBINEDHASH_H +#define ENGINE_HASHING_COMBINEDHASH_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class CombinedHash { +public: + static Uint32 EncryptString(char* data); + static Uint32 EncryptString(const char* message); + static Uint32 EncryptData(const void* message, size_t len); +}; + +#endif /* ENGINE_HASHING_COMBINEDHASH_H */ diff --git a/include/Engine/Hashing/FNV1A.h b/include/Engine/Hashing/FNV1A.h new file mode 100644 index 00000000..aca23a94 --- /dev/null +++ b/include/Engine/Hashing/FNV1A.h @@ -0,0 +1,22 @@ +#ifndef ENGINE_HASHING_FNV1A_H +#define ENGINE_HASHING_FNV1A_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class FNV1A { +public: + static Uint32 EncryptString(char* message); + static Uint32 EncryptString(const char* message); + static Uint32 EncryptData(const void* data, size_t size); + static Uint32 EncryptData(const void* data, size_t size, Uint32 hash); +}; + +#endif /* ENGINE_HASHING_FNV1A_H */ diff --git a/include/Engine/Hashing/MD5.h b/include/Engine/Hashing/MD5.h new file mode 100644 index 00000000..5bd935d5 --- /dev/null +++ b/include/Engine/Hashing/MD5.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_HASHING_MD5_H +#define ENGINE_HASHING_MD5_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class MD5 { +private: + static void* Body(Uint32* pa, Uint32* pb, Uint32* pc, Uint32* pd, void *data, unsigned long size); + +public: + static Uint8* EncryptString(Uint8* dest, char* message); + static Uint8* EncryptString(Uint8* dest, const char* message); + static Uint8* EncryptData(Uint8* dest, void* data, size_t size); +}; + +#endif /* ENGINE_HASHING_MD5_H */ diff --git a/include/Engine/Hashing/Murmur.h b/include/Engine/Hashing/Murmur.h new file mode 100644 index 00000000..bcfad1f7 --- /dev/null +++ b/include/Engine/Hashing/Murmur.h @@ -0,0 +1,22 @@ +#ifndef ENGINE_HASHING_MURMUR_H +#define ENGINE_HASHING_MURMUR_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Murmur { +public: + static Uint32 EncryptString(char* message); + static Uint32 EncryptString(const char* message); + static Uint32 EncryptData(const void* data, size_t size); + static Uint32 EncryptData(const void* key, size_t size, Uint32 hash); +}; + +#endif /* ENGINE_HASHING_MURMUR_H */ diff --git a/include/Engine/IO/Compression/Huffman.h b/include/Engine/IO/Compression/Huffman.h new file mode 100644 index 00000000..58c3dc15 --- /dev/null +++ b/include/Engine/IO/Compression/Huffman.h @@ -0,0 +1,19 @@ +#ifndef ENGINE_IO_COMPRESSION_HUFFMAN_H +#define ENGINE_IO_COMPRESSION_HUFFMAN_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Huffman { +public: + static bool Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz); +}; + +#endif /* ENGINE_IO_COMPRESSION_HUFFMAN_H */ diff --git a/include/Engine/IO/Compression/LZ11.h b/include/Engine/IO/Compression/LZ11.h new file mode 100644 index 00000000..d0dff980 --- /dev/null +++ b/include/Engine/IO/Compression/LZ11.h @@ -0,0 +1,19 @@ +#ifndef ENGINE_IO_COMPRESSION_LZ11_H +#define ENGINE_IO_COMPRESSION_LZ11_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class LZ11 { +public: + static bool Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz); +}; + +#endif /* ENGINE_IO_COMPRESSION_LZ11_H */ diff --git a/include/Engine/IO/Compression/LZSS.h b/include/Engine/IO/Compression/LZSS.h new file mode 100644 index 00000000..e9bb487f --- /dev/null +++ b/include/Engine/IO/Compression/LZSS.h @@ -0,0 +1,19 @@ +#ifndef ENGINE_IO_COMPRESSION_LZSS_H +#define ENGINE_IO_COMPRESSION_LZSS_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class LZSS { +public: + static bool Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz); +}; + +#endif /* ENGINE_IO_COMPRESSION_LZSS_H */ diff --git a/include/Engine/IO/Compression/RunLength.h b/include/Engine/IO/Compression/RunLength.h new file mode 100644 index 00000000..b5c6d47d --- /dev/null +++ b/include/Engine/IO/Compression/RunLength.h @@ -0,0 +1,19 @@ +#ifndef ENGINE_IO_COMPRESSION_RUNLENGTH_H +#define ENGINE_IO_COMPRESSION_RUNLENGTH_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class RunLength { +public: + static bool Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz); +}; + +#endif /* ENGINE_IO_COMPRESSION_RUNLENGTH_H */ diff --git a/include/Engine/IO/Compression/ZLibStream.h b/include/Engine/IO/Compression/ZLibStream.h new file mode 100644 index 00000000..9571c74e --- /dev/null +++ b/include/Engine/IO/Compression/ZLibStream.h @@ -0,0 +1,37 @@ +#ifndef ENGINE_IO_COMPRESSION_ZLIBSTREAM_H +#define ENGINE_IO_COMPRESSION_ZLIBSTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ZLibStream : public Stream { +private: + void Decompress(void* in, size_t inLen); + +public: + Stream* other_stream = NULL; + uint32_t mode = 0; + void* memory = NULL; + size_t memory_size = 0; + + static ZLibStream* New(Stream* other_stream, uint32_t mode); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + size_t WriteBytes(void* data, size_t n); + static void Decompress(void* dst, size_t dstLen, void* src, size_t srcLen); +}; + +#endif /* ENGINE_IO_COMPRESSION_ZLIBSTREAM_H */ diff --git a/include/Engine/IO/FileStream.h b/include/Engine/IO/FileStream.h new file mode 100644 index 00000000..0d28e871 --- /dev/null +++ b/include/Engine/IO/FileStream.h @@ -0,0 +1,38 @@ +#ifndef ENGINE_IO_FILESTREAM_H +#define ENGINE_IO_FILESTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class FileStream : public Stream { +public: + FILE* f; + size_t size; + enum { + READ_ACCESS = 0, + WRITE_ACCESS = 1, + APPEND_ACCESS = 2, + SAVEGAME_ACCESS = 16, + PREFERENCES_ACCESS = 32, + }; + + static FileStream* New(const char* filename, Uint32 access); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + size_t WriteBytes(void* data, size_t n); +}; + +#endif /* ENGINE_IO_FILESTREAM_H */ diff --git a/include/Engine/IO/MemoryStream.h b/include/Engine/IO/MemoryStream.h new file mode 100644 index 00000000..a8cc5503 --- /dev/null +++ b/include/Engine/IO/MemoryStream.h @@ -0,0 +1,37 @@ +#ifndef ENGINE_IO_MEMORYSTREAM_H +#define ENGINE_IO_MEMORYSTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class MemoryStream : public Stream { +public: + Uint8* pointer = NULL; + Uint8* pointer_start = NULL; + size_t size = 0; + bool owns_memory = false; + + static MemoryStream* New(size_t size); + static MemoryStream* New(Stream* other); + static MemoryStream* New(void* data, size_t size); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + Uint32 ReadCompressed(void* out); + Uint32 ReadCompressed(void* out, size_t outSz); + size_t WriteBytes(void* data, size_t n); +}; + +#endif /* ENGINE_IO_MEMORYSTREAM_H */ diff --git a/include/Engine/IO/NetworkStream.h b/include/Engine/IO/NetworkStream.h new file mode 100644 index 00000000..a3e55019 --- /dev/null +++ b/include/Engine/IO/NetworkStream.h @@ -0,0 +1,35 @@ +#ifndef ENGINE_IO_NETWORKSTREAM_H +#define ENGINE_IO_NETWORKSTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class NetworkStream : public Stream { +public: + FILE* f; + size_t size; + enum { + SERVER_SOCKET = 0, + CLIENT_SOCKET = 1, + }; + + static NetworkStream* New(const char* filename, Uint32 access); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + size_t WriteBytes(void* data, size_t n); +}; + +#endif /* ENGINE_IO_NETWORKSTREAM_H */ diff --git a/include/Engine/IO/ResourceStream.h b/include/Engine/IO/ResourceStream.h new file mode 100644 index 00000000..307a3adc --- /dev/null +++ b/include/Engine/IO/ResourceStream.h @@ -0,0 +1,32 @@ +#ifndef ENGINE_IO_RESOURCESTREAM_H +#define ENGINE_IO_RESOURCESTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ResourceStream : public Stream { +public: + Uint8* pointer = NULL; + Uint8* pointer_start = NULL; + size_t size = 0; + + static ResourceStream* New(const char* filename); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + size_t WriteBytes(void* data, size_t n); +}; + +#endif /* ENGINE_IO_RESOURCESTREAM_H */ diff --git a/include/Engine/IO/SDLStream.h b/include/Engine/IO/SDLStream.h new file mode 100644 index 00000000..6b2f1ae4 --- /dev/null +++ b/include/Engine/IO/SDLStream.h @@ -0,0 +1,36 @@ +#ifndef ENGINE_IO_SDLSTREAM_H +#define ENGINE_IO_SDLSTREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class SDLStream : public Stream { +public: + SDL_RWops* f; + enum { + READ_ACCESS = 0, + WRITE_ACCESS = 1, + APPEND_ACCESS = 2, + }; + + static SDLStream* New(const char* filename, Uint32 access); + void Close(); + void Seek(Sint64 offset); + void SeekEnd(Sint64 offset); + void Skip(Sint64 offset); + size_t Position(); + size_t Length(); + size_t ReadBytes(void* data, size_t n); + size_t WriteBytes(void* data, size_t n); +}; + +#endif /* ENGINE_IO_SDLSTREAM_H */ diff --git a/include/Engine/IO/Serializer.h b/include/Engine/IO/Serializer.h new file mode 100644 index 00000000..c63769fc --- /dev/null +++ b/include/Engine/IO/Serializer.h @@ -0,0 +1,80 @@ +#ifndef ENGINE_IO_SERIALIZER_H +#define ENGINE_IO_SERIALIZER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Serializer { +private: + void WriteValue(VMValue val); + void WriteObject(Obj* obj); + void WriteObjectsChunk(); + void WriteTextChunk(); + Uint32 GetUniqueObjectID(Obj* obj); + void BeginChunk(Uint32 type); + void FinishChunk(); + void AddChunkToList(); + void WriteObjectPreamble(Uint8 type); + void PatchObjectSize(); + void AddUniqueString(char* chars, size_t length); + Uint32 GetUniqueStringID(char* chars, size_t length); + void AddUniqueObject(Obj* obj); + void GetObject(); + void ReadObject(Obj* obj); + VMValue ReadValue(); + +public: + std::map ObjToID; + std::vector ObjList; + Stream* StreamPtr; + size_t StoredStreamPos; + size_t StoredChunkPos; + Uint32 CurrentChunkType; + struct Chunk { + Uint32 Type; + size_t Offset; + size_t Size; + }; + std::vector ChunkList; + Serializer::Chunk LastChunk; + struct String { + Uint32 Length; + char* Chars; + }; + std::vector StringList; + enum { + CHUNK_OBJS = MakeFourCC("OBJS"), + CHUNK_TEXT = MakeFourCC("TEXT") + }; + enum { + VAL_TYPE_NULL, + VAL_TYPE_INTEGER, + VAL_TYPE_DECIMAL, + VAL_TYPE_OBJECT, + END = 0xFF + }; + enum { + OBJ_TYPE_UNIMPLEMENTED, + OBJ_TYPE_STRING, + OBJ_TYPE_ARRAY, + OBJ_TYPE_MAP + }; + static Uint32 Magic; + static Uint32 Version; + + Serializer(Stream* stream); + void Store(VMValue val); + bool ReadObjectsChunk(); + bool ReadTextChunk(); + VMValue Retrieve(); +}; + +#endif /* ENGINE_IO_SERIALIZER_H */ diff --git a/include/Engine/IO/Stream.h b/include/Engine/IO/Stream.h new file mode 100644 index 00000000..41404568 --- /dev/null +++ b/include/Engine/IO/Stream.h @@ -0,0 +1,62 @@ +#ifndef ENGINE_IO_STREAM_H +#define ENGINE_IO_STREAM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Stream { +public: + virtual void Close(); + virtual void Seek(Sint64 offset); + virtual void SeekEnd(Sint64 offset); + virtual void Skip(Sint64 offset); + virtual size_t Position(); + virtual size_t Length(); + virtual size_t ReadBytes(void* data, size_t n); + Uint8 ReadByte(); + Uint16 ReadUInt16(); + Uint16 ReadUInt16BE(); + Uint32 ReadUInt32(); + Uint32 ReadUInt32BE(); + Uint64 ReadUInt64(); + Sint16 ReadInt16(); + Sint16 ReadInt16BE(); + Sint32 ReadInt32(); + Sint32 ReadInt32BE(); + Sint64 ReadInt64(); + float ReadFloat(); + char* ReadLine(); + char* ReadString(); + void SkipString(); + Uint16* ReadUnicodeString(); + char* ReadHeaderedString(); + virtual Uint32 ReadCompressed(void* out); + virtual Uint32 ReadCompressed(void* out, size_t outSz); + virtual size_t WriteBytes(void* data, size_t n); + void WriteByte(Uint8 data); + void WriteUInt16(Uint16 data); + void WriteUInt16BE(Uint16 data); + void WriteUInt32(Uint32 data); + void WriteUInt32BE(Uint32 data); + void WriteUInt64(Uint64 data); + void WriteInt16(Sint16 data); + void WriteInt16BE(Sint16 data); + void WriteInt32(Sint32 data); + void WriteInt32BE(Sint32 data); + void WriteInt64(Sint64 data); + void WriteFloat(float data); + void WriteString(const char* string); + void WriteHeaderedString(const char* string); + void CopyTo(Stream* dest); + virtual ~Stream(); +}; + +#endif /* ENGINE_IO_STREAM_H */ diff --git a/include/Engine/Input/Controller.h b/include/Engine/Input/Controller.h new file mode 100644 index 00000000..7025a14f --- /dev/null +++ b/include/Engine/Input/Controller.h @@ -0,0 +1,52 @@ +#ifndef ENGINE_INPUT_CONTROLLER_H +#define ENGINE_INPUT_CONTROLLER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class Controller { +private: + static ControllerType DetermineType(void* gamecontroller); + +public: + ControllerType Type; + bool Connected; + bool* ButtonsPressed; + bool* ButtonsHeld; + float* AxisValues; + ControllerRumble* Rumble; + SDL_GameController* Device; + SDL_Joystick* JoystickDevice; + SDL_JoystickID JoystickID; + + Controller(int index); + ~Controller(); + bool Open(int index); + void Close(); + void Reset(); + char* GetName(); + void SetPlayerIndex(int index); + bool GetButton(int button); + bool IsButtonHeld(int button); + bool IsButtonPressed(int button); + float GetAxis(int axis); + void Update(); + bool IsXbox(); + bool IsPlayStation(); + bool IsJoyCon(); + bool HasShareButton(); + bool HasMicrophoneButton(); + bool HasPaddles(); +}; + +#endif /* ENGINE_INPUT_CONTROLLER_H */ diff --git a/include/Engine/Input/InputAction.h b/include/Engine/Input/InputAction.h new file mode 100644 index 00000000..1950d1a2 --- /dev/null +++ b/include/Engine/Input/InputAction.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_INPUT_INPUTACTION_H +#define ENGINE_INPUT_INPUTACTION_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class InputAction { +public: + unsigned ID; + string Name; + + InputAction(const char* name, unsigned id); + ~InputAction(); +}; + +#endif /* ENGINE_INPUT_INPUTACTION_H */ diff --git a/include/Engine/Input/InputPlayer.h b/include/Engine/Input/InputPlayer.h new file mode 100644 index 00000000..5a8f8b4c --- /dev/null +++ b/include/Engine/Input/InputPlayer.h @@ -0,0 +1,86 @@ +#ifndef ENGINE_INPUT_INPUTPLAYER_H +#define ENGINE_INPUT_INPUTPLAYER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class InputPlayer { +private: + size_t PushBindToList(PlayerInputConfig& config, InputBind* def); + bool ReplaceBindInList(PlayerInputConfig& config, InputBind* def, unsigned index); + bool RemoveBindFromList(PlayerInputConfig& config, unsigned index); + InputBind* GetBindAtIndex(PlayerInputConfig& config, unsigned index); + size_t GetBindCount(PlayerInputConfig& config); + void CopyDefaultBinds(InputPlayer& src, bool filter, int filterType); + void ResetBindList(PlayerInputConfig &dest, PlayerInputConfig &src); + bool CheckInputBindState(InputBind* bind, bool held); + bool CheckIfInputHeld(unsigned actionID, unsigned device); + bool CheckIfInputPressed(unsigned actionID, unsigned device); + bool IsControllerBindHeld(unsigned num); + bool IsControllerBindPressed(unsigned num); + void UpdateControllerBind(unsigned num); + bool GetAnalogControllerBind(unsigned num, float& result); + +public: + int ID; + vector Binds; + vector DefaultBinds; + PlayerInputStatus Status[InputDevice_MAX]; + PlayerInputStatus AllStatus; + vector NumHeld; + vector NumPressed; + vector NumReleased; + bool AnyHeld; + bool AnyPressed; + bool AnyReleased; + vector ControllerState; + bool IsUsingDevice[InputDevice_MAX]; + int ControllerIndex = -1; + const char* ConfigFilename = nullptr; + + InputPlayer(int id); + void SetNumActions(size_t num); + void ClearBinds(); + void ResetBinds(); + void Update(); + int AddBind(unsigned num, InputBind* bind); + bool ReplaceBind(unsigned num, InputBind* bind, unsigned index); + bool RemoveBind(unsigned num, unsigned index); + InputBind* GetBind(unsigned num, unsigned index); + size_t GetBindCount(unsigned num); + int AddDefaultBind(unsigned num, InputBind* bind); + void CopyDefaultBinds(InputPlayer& src); + void CopyDefaultBinds(InputPlayer& src, int filterType); + bool ReplaceDefaultBind(unsigned num, InputBind* bind, unsigned index); + bool RemoveDefaultBind(unsigned num, unsigned index); + InputBind* GetDefaultBind(unsigned num, unsigned index); + size_t GetDefaultBindCount(unsigned num); + bool IsBindIndexValid(unsigned num, unsigned index); + void ClearBinds(unsigned num); + void ClearDefaultBinds(unsigned num); + void ResetBind(unsigned num); + bool IsInputHeld(unsigned actionID, unsigned device); + bool IsInputPressed(unsigned actionID, unsigned device); + bool IsInputReleased(unsigned actionID, unsigned device); + bool IsAnyInputHeld(unsigned device); + bool IsAnyInputPressed(unsigned device); + bool IsAnyInputReleased(unsigned device); + bool IsInputHeld(unsigned actionID); + bool IsInputPressed(unsigned actionID); + bool IsInputReleased(unsigned actionID); + bool IsAnyInputHeld(); + bool IsAnyInputPressed(); + bool IsAnyInputReleased(); + float GetAnalogActionInput(unsigned actionID); +}; + +#endif /* ENGINE_INPUT_INPUTPLAYER_H */ diff --git a/include/Engine/InputManager.h b/include/Engine/InputManager.h new file mode 100644 index 00000000..49659fa6 --- /dev/null +++ b/include/Engine/InputManager.h @@ -0,0 +1,128 @@ +#ifndef ENGINE_INPUTMANAGER_H +#define ENGINE_INPUTMANAGER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class InputManager { +private: + static void InitStringLookup(); + static int FindController(int joystickID); + static void ParsePlayerControls(InputPlayer& player, XMLNode* node); + static Uint16 ParseKeyModifiers(string& str, string& actionName); + static void ParseDefaultInputBinds(InputPlayer& player, int actionID, string& actionName, XMLNode* node); + +public: + static float MouseX; + static float MouseY; + static int MouseDown; + static int MousePressed; + static int MouseReleased; + static Uint8 KeyboardState[0x120]; + static Uint8 KeyboardStateLast[0x120]; + static Uint16 KeymodState; + static SDL_Scancode KeyToSDLScancode[NUM_KEYBOARD_KEYS]; + static int NumControllers; + static vector Controllers; + static SDL_TouchID TouchDevice; + static void* TouchStates; + static vector Players; + static vector Actions; + + static void Init(); + static char* GetKeyName(int key); + static char* GetButtonName(int button); + static char* GetAxisName(int axis); + static int ParseKeyName(const char* key); + static int ParseButtonName(const char* button); + static int ParseAxisName(const char* axis); + static Controller* OpenController(int index); + static void InitControllers(); + static bool AddController(int index); + static void RemoveController(int joystickID); + static void Poll(); + static Uint16 CheckKeyModifiers(Uint16 modifiers); + static bool IsKeyDown(int key); + static bool IsKeyPressed(int key); + static bool IsKeyReleased(int key); + static Controller* GetController(int index); + static bool ControllerIsConnected(int index); + static bool ControllerIsXbox(int index); + static bool ControllerIsPlayStation(int index); + static bool ControllerIsJoyCon(int index); + static bool ControllerHasShareButton(int index); + static bool ControllerHasMicrophoneButton(int index); + static bool ControllerHasPaddles(int index); + static bool ControllerIsButtonHeld(int index, int button); + static bool ControllerIsButtonPressed(int index, int button); + static float ControllerGetAxis(int index, int axis); + static int ControllerGetType(int index); + static char* ControllerGetName(int index); + static void ControllerSetPlayerIndex(int index, int player_index); + static bool ControllerHasRumble(int index); + static bool ControllerIsRumbleActive(int index); + static bool ControllerRumble(int index, float large_frequency, float small_frequency, int duration); + static bool ControllerRumble(int index, float strength, int duration); + static void ControllerStopRumble(int index); + static void ControllerStopRumble(); + static bool ControllerIsRumblePaused(int index); + static void ControllerSetRumblePaused(int index, bool paused); + static bool ControllerSetLargeMotorFrequency(int index, float frequency); + static bool ControllerSetSmallMotorFrequency(int index, float frequency); + static float TouchGetX(int touch_index); + static float TouchGetY(int touch_index); + static bool TouchIsDown(int touch_index); + static bool TouchIsPressed(int touch_index); + static bool TouchIsReleased(int touch_index); + static int AddPlayer(); + static int GetPlayerCount(); + static void SetPlayerControllerIndex(unsigned playerID, int index); + static int GetPlayerControllerIndex(unsigned playerID); + static bool IsActionHeld(unsigned playerID, unsigned actionID); + static bool IsActionPressed(unsigned playerID, unsigned actionID); + static bool IsActionReleased(unsigned playerID, unsigned actionID); + static bool IsAnyActionHeld(unsigned playerID); + static bool IsAnyActionPressed(unsigned playerID); + static bool IsAnyActionReleased(unsigned playerID); + static bool IsActionHeld(unsigned playerID, unsigned actionID, unsigned device); + static bool IsActionPressed(unsigned playerID, unsigned actionID, unsigned device); + static bool IsActionReleased(unsigned playerID, unsigned actionID, unsigned device); + static bool IsAnyActionHeld(unsigned playerID, unsigned device); + static bool IsAnyActionPressed(unsigned playerID, unsigned device); + static bool IsAnyActionReleased(unsigned playerID, unsigned device); + static bool IsPlayerUsingDevice(unsigned playerID, unsigned device); + static float GetAnalogActionInput(unsigned playerID, unsigned actionID); + static InputBind* GetPlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault); + static bool SetPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, unsigned index, bool isDefault); + static int AddPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, bool isDefault); + static bool RemovePlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault); + static int GetPlayerInputBindCount(unsigned playerID, unsigned actionID, bool isDefault); + static void ClearPlayerBinds(unsigned playerID, unsigned actionID, bool isDefault); + static bool IsBindIndexValid(unsigned playerID, unsigned actionID, unsigned index); + static void ResetPlayerBinds(unsigned playerID); + static void ClearPlayers(); + static int RegisterAction(const char* name); + static int GetActionID(const char* name); + static void ClearInputs(); + static void InitPlayerControls(); + static void Dispose(); +}; + +#endif /* ENGINE_INPUTMANAGER_H */ diff --git a/include/Engine/Math/Clipper.h b/include/Engine/Math/Clipper.h new file mode 100644 index 00000000..11f96eb1 --- /dev/null +++ b/include/Engine/Math/Clipper.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_MATH_CLIPPER_H +#define ENGINE_MATH_CLIPPER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Clipper { +private: + static void AddPoint(VertexAttribute* buf, VertexAttribute* v1, VertexAttribute* v2, Vector4 p1, Vector4 p2, Sint64 t); + static bool ClipEdge(Frustum frustum, VertexAttribute* v1, VertexAttribute* v2, PolygonClipBuffer* output); + static int ClipPolygon(Frustum frustum, PolygonClipBuffer* output, VertexAttribute* input, int vertexCount); + +public: + static int FrustumClip(PolygonClipBuffer* output, Frustum* frustum, int num, VertexAttribute* input, int vertexCount); +}; + +#endif /* ENGINE_MATH_CLIPPER_H */ diff --git a/include/Engine/Math/Ease.h b/include/Engine/Math/Ease.h new file mode 100644 index 00000000..8f8a22d4 --- /dev/null +++ b/include/Engine/Math/Ease.h @@ -0,0 +1,49 @@ +#ifndef ENGINE_MATH_EASE_H +#define ENGINE_MATH_EASE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Ease { +public: + static float InSine(float t); + static float OutSine(float t); + static float InOutSine(float t); + static float InQuad(float t); + static float OutQuad(float t); + static float InOutQuad(float t); + static float InCubic(float t); + static float OutCubic(float t); + static float InOutCubic(float t); + static float InQuart(float t); + static float OutQuart(float t); + static float InOutQuart(float t); + static float InQuint(float t); + static float OutQuint(float t); + static float InOutQuint(float t); + static float InExpo(float t); + static float OutExpo(float t); + static float InOutExpo(float t); + static float InCirc(float t); + static float OutCirc(float t); + static float InOutCirc(float t); + static float InBack(float t); + static float OutBack(float t); + static float InOutBack(float t); + static float InElastic(float t); + static float OutElastic(float t); + static float InOutElastic(float t); + static float InBounce(float t); + static float OutBounce(float t); + static float InOutBounce(float t); + static float Triangle(float t); +}; + +#endif /* ENGINE_MATH_EASE_H */ diff --git a/include/Engine/Math/Geometry.h b/include/Engine/Math/Geometry.h new file mode 100644 index 00000000..9cd8de13 --- /dev/null +++ b/include/Engine/Math/Geometry.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_MATH_GEOMETRY_H +#define ENGINE_MATH_GEOMETRY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Geometry { +private: + static bool CheckEar(vector& input, unsigned count, unsigned prev, unsigned curr, unsigned next); + static int GetPointForTriangulation(int point, unsigned count); + +public: + static vector* Triangulate(Polygon2D& input, vector holes); + static vector* Intersect(unsigned clipType, unsigned fillRule, vector inputSubjects, vector inputClips); +}; + +#endif /* ENGINE_MATH_GEOMETRY_H */ diff --git a/include/Engine/Math/Math.h b/include/Engine/Math/Math.h new file mode 100644 index 00000000..403bbbab --- /dev/null +++ b/include/Engine/Math/Math.h @@ -0,0 +1,57 @@ +#ifndef ENGINE_MATH_MATH_H +#define ENGINE_MATH_MATH_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Math { +public: + static void Init(); + static float Cos(float n); + static float Sin(float n); + static float Tan(float n); + static float Asin(float x); + static float Acos(float x); + static float Atan(float x, float y); + static float Distance(float x1, float y1, float x2, float y2); + static float Hypot(float a, float b, float c); + static void ClearTrigLookupTables(); + static void CalculateTrigAngles(); + static int Sin1024(int angle); + static int Cos1024(int angle); + static int Tan1024(int angle); + static int ASin1024(int angle); + static int ACos1024(int angle); + static int Sin512(int angle); + static int Cos512(int angle); + static int Tan512(int angle); + static int ASin512(int angle); + static int ACos512(int angle); + static int Sin256(int angle); + static int Cos256(int angle); + static int Tan256(int angle); + static int ASin256(int angle); + static int ACos256(int angle); + static int CeilPOT(int n); + static float Abs(float n); + static float Max(float a, float b); + static float Min(float a, float b); + static float Clamp(float v, float a, float b); + static float Sign(float a); + static float Random(); + static float RandomMax(float max); + static float RandomRange(float min, float max); + static int RSDK_GetRandSeed(); + static void RSDK_SetRandSeed(int key); + static int RSDK_RandomInteger(int min, int max); + static int RSDK_RandomIntegerSeeded(int min, int max, int seed); +}; + +#endif /* ENGINE_MATH_MATH_H */ diff --git a/include/Engine/Math/Matrix4x4.h b/include/Engine/Math/Matrix4x4.h new file mode 100644 index 00000000..fac32ab6 --- /dev/null +++ b/include/Engine/Math/Matrix4x4.h @@ -0,0 +1,39 @@ +#ifndef ENGINE_MATH_MATRIX4X4_H +#define ENGINE_MATH_MATRIX4X4_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class Matrix4x4 { +public: + float Values[16]; + + static Matrix4x4* Create(); + static void Identity(Matrix4x4* mat4); + static void Perspective(Matrix4x4* out, float fovy, float aspect, float near, float far); + static void Ortho(Matrix4x4* out, float left, float right, float bottom, float top, float near, float far); + static void Copy(Matrix4x4* out, Matrix4x4* a); + static bool Equals(Matrix4x4* a, Matrix4x4* b); + static void Multiply(Matrix4x4* out, Matrix4x4* a, Matrix4x4* b); + static void Multiply(Matrix4x4* mat, float* a); + static void Translate(Matrix4x4* out, Matrix4x4* a, float x, float y, float z); + static void Scale(Matrix4x4* out, Matrix4x4* a, float x, float y, float z); + static void Rotate(Matrix4x4* out, Matrix4x4* a, float rad, float x, float y, float z); + static void IdentityScale(Matrix4x4* out, float x, float y, float z); + static void IdentityRotationX(Matrix4x4* out, float x); + static void IdentityRotationY(Matrix4x4* out, float y); + static void IdentityRotationZ(Matrix4x4* out, float z); + static void IdentityRotationXYZ(Matrix4x4* out, float x, float y, float z); + static void Transpose(Matrix4x4* out); + static void LookAt(Matrix4x4* out, float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz); + static void Invert(Matrix4x4* out, Matrix4x4* in); + static void Print(Matrix4x4* out); +}; + +#endif /* ENGINE_MATH_MATRIX4X4_H */ diff --git a/include/Engine/Math/Random.h b/include/Engine/Math/Random.h new file mode 100644 index 00000000..7d50d5cf --- /dev/null +++ b/include/Engine/Math/Random.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_MATH_RANDOM_H +#define ENGINE_MATH_RANDOM_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Random { +public: + static Sint32 Seed; + + static void SetSeed(Sint32 seed); + static float Get(); + static float Max(float max); + static float Range(float min, float max); +}; + +#endif /* ENGINE_MATH_RANDOM_H */ diff --git a/include/Engine/Math/Vector.h b/include/Engine/Math/Vector.h new file mode 100644 index 00000000..5ef6d1a8 --- /dev/null +++ b/include/Engine/Math/Vector.h @@ -0,0 +1,32 @@ +#ifndef ENGINE_MATH_VECTOR_H +#define ENGINE_MATH_VECTOR_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class Vector { +public: + static Vector4 Add(Vector4 v1, Vector4 v2); + static Vector4 Subtract(Vector4 v1, Vector4 v2); + static Vector4 Multiply(Vector4 v, Sint64 t); + static Vector3 Multiply(Vector3 v, Matrix4x4* m); + static Vector2 Interpolate(Vector2 v1, Vector2 v2, Sint64 t); + static Vector3 Interpolate(Vector3 v1, Vector3 v2, Sint64 t); + static Vector4 Interpolate(Vector4 v1, Vector4 v2, Sint64 t); + static Sint64 DotProduct(Vector4 v1, Vector4 v2); + static Sint64 Length(Vector4 v); + static Vector4 Normalize(Vector4 v); + static Sint64 IntersectWithPlane(Vector4 plane, Vector4 normal, Vector4 v1, Vector4 v2); + static Sint64 DistanceToPlane(Vector4 v, Vector4 plane, Vector4 normal); +}; + +#endif /* ENGINE_MATH_VECTOR_H */ diff --git a/include/Engine/Media/Decoder.h b/include/Engine/Media/Decoder.h new file mode 100644 index 00000000..f638fd9b --- /dev/null +++ b/include/Engine/Media/Decoder.h @@ -0,0 +1,64 @@ +#ifndef ENGINE_MEDIA_DECODER_H +#define ENGINE_MEDIA_DECODER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include + +class Decoder { +public: + bool Successful; + int StreamIndex; + double ClockSync; + double ClockPos; + PtrBuffer* Buffer[2]; + SDL_mutex* OutputLock; + AVCodecContext* CodecCtx; + AVFormatContext* FormatCtx; + Uint32 Format; // SDL_Format + int (*DecodeFunc)(void*, AVPacket*); + void (*CloseFunc)(void*); + + static void FreeInVideoPacketFunc(void* packet); + void Create(MediaSource* src, int stream_index, int outBufferLength, void (*freeOutFunc)(void*), int thread_count); + void Close(); + ~Decoder(); + int Run(); + int GetCodecInfo(Codec* codec); + int GetOutputFormat(OutputFormat* output); + int GetStreamIndex(); + void SetClockSync(double sync); + void ChangeClockSync(double sync); + int WriteInput(AVPacket* packet); + AVPacket* PeekInput(); + AVPacket* ReadInput(); + bool CanWriteInput(); + void AdvanceInput(); + void ClearInput(); + int WriteOutput(void* packet); + void* PeekOutput(); + void* ReadOutput(); + bool CanWriteOutput(); + void AdvanceOutput(); + void ClearOutput(); + void ForEachOutput(void (*cb)(void*, void*), void* userdata); + Uint32 GetInputLength(); + Uint32 GetOutputLength(); + void ClearBuffers(); + int LockOutput(); + void UnlockOutput(); +}; + +#endif /* ENGINE_MEDIA_DECODER_H */ diff --git a/include/Engine/Media/Decoders/AudioDecoder.h b/include/Engine/Media/Decoders/AudioDecoder.h new file mode 100644 index 00000000..d7cbc4fb --- /dev/null +++ b/include/Engine/Media/Decoders/AudioDecoder.h @@ -0,0 +1,42 @@ +#ifndef ENGINE_MEDIA_DECODERS_AUDIODECODER_H +#define ENGINE_MEDIA_DECODERS_AUDIODECODER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class AudioDecoder : public Decoder { +public: + SwrContext* SWR; + AVFrame* ScratchFrame; + int SampleRate; + int Channels; + int Bytes; + int IsSigned; + + AudioDecoder(MediaSource* src, int stream_index); + void* CreateAudioPacket(const char* data, size_t len, double pts); + static void FreeAudioPacket(void* p); + AVSampleFormat FindAVSampleFormat(int format); + Sint64 FindAVChannelLayout(int channels); + int FindChannelLayout(uint64_t channel_layout); + int FindBytes(AVSampleFormat fmt); + int FindSignedness(AVSampleFormat fmt); + int FindSDLSampleFormat(AVSampleFormat fmt); + int GetOutputFormat(OutputFormat* output); + static void ReadAudio(void* ptr); + static int DecodeFunction(void* ptr, AVPacket* in_packet); + static void CloseFunction(void* ptr); + double GetPTS(); + int GetAudioDecoderData(Uint8* buf, int len); +}; + +#endif /* ENGINE_MEDIA_DECODERS_AUDIODECODER_H */ diff --git a/include/Engine/Media/Decoders/VideoDecoder.h b/include/Engine/Media/Decoders/VideoDecoder.h new file mode 100644 index 00000000..0cdb6296 --- /dev/null +++ b/include/Engine/Media/Decoders/VideoDecoder.h @@ -0,0 +1,37 @@ +#ifndef ENGINE_MEDIA_DECODERS_VIDEODECODER_H +#define ENGINE_MEDIA_DECODERS_VIDEODECODER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class VideoDecoder : public Decoder { +public: + SwsContext* SWS; + AVFrame* ScratchFrame; + int Width; + int Height; + + VideoDecoder(MediaSource* src, int stream_index); + void* CreateVideoPacket(AVFrame* frame, double pts); + static void FreeVideoPacket(void* p); + AVPixelFormat FindAVPixelFormat(Uint32 format); + int FindSDLPixelFormat(AVPixelFormat fmt); + int GetOutputFormat(OutputFormat* output); + static void ReadVideo(void* ptr); + static int DecodeFunction(void* ptr, AVPacket* in_packet); + static void CloseFunction(void* ptr); + double GetPTS(); + int GetVideoDecoderData(Texture* texture); +}; + +#endif /* ENGINE_MEDIA_DECODERS_VIDEODECODER_H */ diff --git a/include/Engine/Media/MediaPlayer.h b/include/Engine/Media/MediaPlayer.h new file mode 100644 index 00000000..aa486633 --- /dev/null +++ b/include/Engine/Media/MediaPlayer.h @@ -0,0 +1,68 @@ +#ifndef ENGINE_MEDIA_MEDIAPLAYER_H +#define ENGINE_MEDIA_MEDIAPLAYER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class MediaPlayer { +public: + enum { + KIT_WAITING_TO_BE_PLAYABLE = 0, ///< Playback stopped or has not started yet. + KIT_PLAYING, ///< Playback started & player is actively decoding. + KIT_PAUSED, ///< Playback paused; player is actively decoding but no new data is given out. + KIT_CLOSED, ///< Playback is stopped and player is closing. + KIT_STOPPED, + }; + Uint32 State; + Decoder* Decoders[3]; + SDL_Thread* DecoderThread; + SDL_mutex* DecoderLock; + MediaSource* Source; + double PauseStarted; + double PausedPosition; + double SeekStarted; + Uint32 WaitState; + + static int DemuxAllStreams(MediaPlayer* player); + static int RunAllDecoders(MediaPlayer* player); + static int DecoderThreadFunc(void* ptr); + static MediaPlayer* Create(MediaSource* src, int video_stream_index, int audio_stream_index, int subtitle_stream_index, int screen_w, int screen_h); + void Close(); + void SetScreenSize(int w, int h); + int GetVideoStream(); + int GetAudioStream(); + int GetSubtitleStream(); + void GetInfo(PlayerInfo* info); + double GetDuration(); + double GetPosition(); + double GetBufferPosition(); + bool ManageWaiting(); + int GetVideoData(Texture* texture); + int GetVideoDataForPaused(Texture* texture); + int GetAudioData(unsigned char* buffer, int length); + int GetSubtitleData(Texture* texture, SDL_Rect* sources, SDL_Rect* targets, int limit); + void SetClockSync(); + void SetClockSyncOffset(double offset); + void ChangeClockSync(double delta); + void Play(); + void Stop(); + void Pause(); + int Seek(double seek_set); + Uint32 GetPlayerState(); + bool IsInputEmpty(); + bool IsOutputEmpty(); + static Uint32 GetInputLength(MediaPlayer* player, int i); + static Uint32 GetOutputLength(MediaPlayer* player, int i); +}; + +#endif /* ENGINE_MEDIA_MEDIAPLAYER_H */ diff --git a/include/Engine/Media/MediaSource.h b/include/Engine/Media/MediaSource.h new file mode 100644 index 00000000..ff70789a --- /dev/null +++ b/include/Engine/Media/MediaSource.h @@ -0,0 +1,38 @@ +#ifndef ENGINE_MEDIA_MEDIASOURCE_H +#define ENGINE_MEDIA_MEDIASOURCE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class MediaSource { +public: + enum { + STREAMTYPE_UNKNOWN, + STREAMTYPE_VIDEO, + STREAMTYPE_AUDIO, + STREAMTYPE_DATA, + STREAMTYPE_SUBTITLE, + STREAMTYPE_ATTACHMENT + }; + void* FormatCtx; + void* AvioCtx; + Stream* StreamPtr; + + static MediaSource* CreateSourceFromUrl(const char* url); + static MediaSource* CreateSourceFromStream(Stream* stream); + int GetStreamInfo(Uint32* info, int index); + int GetStreamCount(); + int GetBestStream(Uint32 type); + void Close(); +}; + +#endif /* ENGINE_MEDIA_MEDIASOURCE_H */ diff --git a/include/Engine/Media/Utils/MediaPlayerState.h b/include/Engine/Media/Utils/MediaPlayerState.h new file mode 100644 index 00000000..77ff6f3a --- /dev/null +++ b/include/Engine/Media/Utils/MediaPlayerState.h @@ -0,0 +1,29 @@ +#ifndef ENGINE_MEDIA_UTILS_MEDIAPLAYERSTATE_H +#define ENGINE_MEDIA_UTILS_MEDIAPLAYERSTATE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class MediaPlayerState { +public: + static Uint32 InitFlags; + static Uint32 ThreadCount; + static Uint32 FontHinting; + static Uint32 VideoBufFrames; + static Uint32 AudioBufFrames; + static Uint32 SubtitleBufFrames; + static void* LibassHandle; + static void* AssSharedObjectHandle; + + static double GetSystemTime(); + static bool AttachmentIsFont(void* p); +}; + +#endif /* ENGINE_MEDIA_UTILS_MEDIAPLAYERSTATE_H */ diff --git a/include/Engine/Media/Utils/PtrBuffer.h b/include/Engine/Media/Utils/PtrBuffer.h new file mode 100644 index 00000000..5b1ecec2 --- /dev/null +++ b/include/Engine/Media/Utils/PtrBuffer.h @@ -0,0 +1,36 @@ +#ifndef ENGINE_MEDIA_UTILS_PTRBUFFER_H +#define ENGINE_MEDIA_UTILS_PTRBUFFER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class PtrBuffer { +public: + Uint32 ReadPtr; + Uint32 WritePtr; + Uint32 Size; + void** Data; + void (*FreeFunc)(void*); + + PtrBuffer(Uint32 size, void (*freeFunc)(void*)); + ~PtrBuffer(); + Uint32 GetLength(); + void Clear(); + void* Read(); + void* Peek(); + void Advance(); + int Write(void* ptr); + void ForEachItemInBuffer(void (*callback)(void*, void*), void* userdata); + void WithEachItemInBuffer(std::function callback, void* userdata); + int IsFull(); +}; + +#endif /* ENGINE_MEDIA_UTILS_PTRBUFFER_H */ diff --git a/include/Engine/Media/Utils/RingBuffer.h b/include/Engine/Media/Utils/RingBuffer.h new file mode 100644 index 00000000..a2356b1d --- /dev/null +++ b/include/Engine/Media/Utils/RingBuffer.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_MEDIA_UTILS_RINGBUFFER_H +#define ENGINE_MEDIA_UTILS_RINGBUFFER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class RingBuffer { +public: + int Size; + int Length; + int WritePos; + int ReadPos; + char* Data; + + RingBuffer(Uint32 size); + ~RingBuffer(); + int Write(const char* data, int len); + void ReadData(char* data, const int len); + int Read(char* data, int len); + int Peek(char *data, int len); + int Advance(int len); + int GetLength(); + int GetSize(); + int GetFree(); +}; + +#endif /* ENGINE_MEDIA_UTILS_RINGBUFFER_H */ diff --git a/include/Engine/Network/HTTP.h b/include/Engine/Network/HTTP.h new file mode 100644 index 00000000..2c2dade1 --- /dev/null +++ b/include/Engine/Network/HTTP.h @@ -0,0 +1,21 @@ +#ifndef ENGINE_NETWORK_HTTP_H +#define ENGINE_NETWORK_HTTP_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class HTTP { +public: + static bool GET(const char* url, Uint8** outBuf, size_t* outLen, ObjBoundMethod* callback); +}; + +#endif /* ENGINE_NETWORK_HTTP_H */ diff --git a/include/Engine/Network/WebSocketClient.h b/include/Engine/Network/WebSocketClient.h new file mode 100644 index 00000000..b96ccf02 --- /dev/null +++ b/include/Engine/Network/WebSocketClient.h @@ -0,0 +1,47 @@ +#ifndef ENGINE_NETWORK_WEBSOCKETCLIENT_H +#define ENGINE_NETWORK_WEBSOCKETCLIENT_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class WebSocketClient { +public: + enum { + CLOSING = 0, + CLOSED = 1, + CONNECTING = 2, + OPEN = 3, + }; + std::vector rxbuf; + std::vector txbuf; + std::vector receivedData; + socket_t socket; + int readyState; + bool useMask; + bool isRxBad; + + static WebSocketClient* New(const char* url); + void Poll(int timeout); + void Dispatch(void(*callback)(void* mem, size_t size)); + size_t BytesToRead(); + size_t ReadBytes(void* data, size_t n); + Uint32 ReadUint32(); + Sint32 ReadSint32(); + float ReadFloat(); + char* ReadString(); + void SendData(int type, const void* message, int64_t message_size); + void SendBinary(const void* message, int64_t message_size); + void SendText(const char* message); + void Close(); +}; + +#endif /* ENGINE_NETWORK_WEBSOCKETCLIENT_H */ diff --git a/include/Engine/Rendering/D3D/D3DRenderer.h b/include/Engine/Rendering/D3D/D3DRenderer.h new file mode 100644 index 00000000..22713e20 --- /dev/null +++ b/include/Engine/Rendering/D3D/D3DRenderer.h @@ -0,0 +1,76 @@ +#ifndef ENGINE_RENDERING_D3D_D3DRENDERER_H +#define ENGINE_RENDERING_D3D_D3DRENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include + +class D3DRenderer { +public: + static void Init(); + static Uint32 GetWindowFlags(); + static void SetVSync(bool enabled); + static void SetGraphicsFunctions(); + static void Dispose(); + static Texture* CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + static int LockTexture(Texture* texture, void** pixels, int* pitch); + static int UpdateTexture(Texture* texture, SDL_Rect* r, void* pixels, int pitch); + static void UnlockTexture(Texture* texture); + static void DisposeTexture(Texture* texture); + static void SetRenderTarget(Texture* texture); + static void UpdateWindowSize(int width, int height); + static void UpdateViewport(); + static void UpdateClipRect(); + static void UpdateOrtho(float left, float top, float right, float bottom); + static void UpdatePerspective(float fovy, float aspect, float nearv, float farv); + static void UpdateProjectionMatrix(); + static void MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect); + static void UseShader(void* shader); + static void SetUniformF(int location, int count, float* values); + static void SetUniformI(int location, int count, int* values); + static void SetUniformTexture(Texture* texture, int uniform_index, int slot); + static void Clear(); + static void Present(); + static void SetBlendColor(float r, float g, float b, float a); + static void SetBlendMode(int srcC, int dstC, int srcA, int dstA); + static void SetTintColor(float r, float g, float b, float a); + static void SetTintMode(int mode); + static void SetTintEnabled(bool enabled); + static void SetLineWidth(float n); + static void StrokeLine(float x1, float y1, float x2, float y2); + static void StrokeCircle(float x, float y, float rad, float thickness); + static void StrokeEllipse(float x, float y, float w, float h); + static void StrokeRectangle(float x, float y, float w, float h); + static void FillCircle(float x, float y, float rad); + static void FillEllipse(float x, float y, float w, float h); + static void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void FillRectangle(float x, float y, float w, float h); + static void DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void BindVertexBuffer(Uint32 vertexBufferIndex); + static void UnbindVertexBuffer(); + static void BindScene3D(Uint32 sceneIndex); + static void ClearScene3D(Uint32 sceneIndex); + static void DrawScene3D(Uint32 sceneIndex, Uint32 drawMode); + static Uint32 CreateTexturedShapeBuffer(float** data, int vertexCount); + static void DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount); +}; + +#endif /* ENGINE_RENDERING_D3D_D3DRENDERER_H */ diff --git a/include/Engine/Rendering/FaceInfo.h b/include/Engine/Rendering/FaceInfo.h new file mode 100644 index 00000000..9973276a --- /dev/null +++ b/include/Engine/Rendering/FaceInfo.h @@ -0,0 +1,33 @@ +#ifndef ENGINE_RENDERING_FACEINFO_H +#define ENGINE_RENDERING_FACEINFO_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class FaceInfo { +public: + Uint32 DrawMode; + Uint32 NumVertices; + Uint32 VerticesStartIndex; + bool UseMaterial; + FaceMaterial MaterialInfo; + BlendState Blend; + Uint8 CullMode; + int Depth; + + void SetMaterial(Material* material); + void SetMaterial(Texture* texture); + void SetBlendState(BlendState blendState); +}; + +#endif /* ENGINE_RENDERING_FACEINFO_H */ diff --git a/include/Engine/Rendering/GL/GLRenderer.h b/include/Engine/Rendering/GL/GLRenderer.h new file mode 100644 index 00000000..e40ddde5 --- /dev/null +++ b/include/Engine/Rendering/GL/GLRenderer.h @@ -0,0 +1,100 @@ +#ifndef ENGINE_RENDERING_GL_GLRENDERER_H +#define ENGINE_RENDERING_GL_GLRENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class GLRenderer { +public: + static SDL_GLContext Context; + static GLShader* CurrentShader; + static GLShaderContainer* ShaderShape; + static GLShaderContainer* ShaderShape3D; + static GLShaderContainer* ShaderFogLinear; + static GLShaderContainer* ShaderFogExp; + static GLShaderContainer* ShaderYUV; + static GLint DefaultFramebuffer; + static GLint DefaultRenderbuffer; + static GLuint BufferCircleFill; + static GLuint BufferCircleStroke; + static GLuint BufferSquareFill; + + static void Init(); + static Uint32 GetWindowFlags(); + static void SetVSync(bool enabled); + static void SetGraphicsFunctions(); + static void Dispose(); + static Texture* CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + static int LockTexture(Texture* texture, void** pixels, int* pitch); + static int UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch); + static int UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV); + static void UnlockTexture(Texture* texture); + static void DisposeTexture(Texture* texture); + static void SetRenderTarget(Texture* texture); + static void ReadFramebuffer(void* pixels, int width, int height); + static void UpdateWindowSize(int width, int height); + static void UpdateViewport(); + static void UpdateClipRect(); + static void UpdateOrtho(float left, float top, float right, float bottom); + static void UpdatePerspective(float fovy, float aspect, float nearv, float farv); + static void UpdateProjectionMatrix(); + static void MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect); + static void UseShader(void* shader); + static void SetUniformF(int location, int count, float* values); + static void SetUniformI(int location, int count, int* values); + static void SetUniformTexture(Texture* texture, int uniform_index, int slot); + static void UpdateGlobalPalette(); + static void Clear(); + static void Present(); + static void SetBlendColor(float r, float g, float b, float a); + static void SetBlendMode(int srcC, int dstC, int srcA, int dstA); + static void SetTintColor(float r, float g, float b, float a); + static void SetTintMode(int mode); + static void SetTintEnabled(bool enabled); + static void SetLineWidth(float n); + static void StrokeLine(float x1, float y1, float x2, float y2); + static void StrokeCircle(float x, float y, float rad, float thickness); + static void StrokeEllipse(float x, float y, float w, float h); + static void StrokeRectangle(float x, float y, float w, float h); + static void FillCircle(float x, float y, float rad); + static void FillEllipse(float x, float y, float w, float h); + static void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void FillRectangle(float x, float y, float w, float h); + static Uint32 CreateTexturedShapeBuffer(float* data, int vertexCount); + static void DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount); + static void DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModel(void* inModel, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModelSkinned(void* inModel, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void BindVertexBuffer(Uint32 vertexBufferIndex); + static void UnbindVertexBuffer(); + static void ClearScene3D(Uint32 sceneIndex); + static void DrawScene3D(Uint32 sceneIndex, Uint32 drawMode); + static void* CreateVertexBuffer(Uint32 maxVertices); + static void DeleteVertexBuffer(void* vtxBuf); + static void MakeFrameBufferID(ISprite* sprite, AnimFrame* frame); + static void DeleteFrameBufferID(AnimFrame* frame); + static void SetDepthTesting(bool enable); +}; + +#endif /* ENGINE_RENDERING_GL_GLRENDERER_H */ diff --git a/include/Engine/Rendering/GL/GLShader.h b/include/Engine/Rendering/GL/GLShader.h new file mode 100644 index 00000000..19f8d99d --- /dev/null +++ b/include/Engine/Rendering/GL/GLShader.h @@ -0,0 +1,58 @@ +#ifndef ENGINE_RENDERING_GL_GLSHADER_H +#define ENGINE_RENDERING_GL_GLSHADER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class GLShader { +private: + void AttachAndLink(); + +public: + GLuint ProgramID = 0; + GLuint VertexProgramID = 0; + GLuint FragmentProgramID = 0; + GLint LocProjectionMatrix; + GLint LocModelViewMatrix; + GLint LocPosition; + GLint LocTexCoord; + GLint LocTexture; + GLint LocTextureU; + GLint LocTextureV; + GLint LocPalette; + GLint LocColor; + GLint LocVaryingColor; + GLint LocFogColor; + GLint LocFogLinearStart; + GLint LocFogLinearEnd; + GLint LocFogDensity; + GLint LocFogTable; + char FilenameV[256]; + char FilenameF[256]; + // Cache stuff + float CachedBlendColors[4]; + Matrix4x4* CachedProjectionMatrix = NULL; + Matrix4x4* CachedModelViewMatrix = NULL; + + GLShader(std::string vertexShaderSource, std::string fragmentShaderSource); + GLShader(Stream* streamVS, Stream* streamFS); + bool CheckShaderError(GLuint shader); + bool CheckProgramError(GLuint prog); + GLuint Use(); + GLint GetAttribLocation(const GLchar* identifier); + GLint GetUniformLocation(const GLchar* identifier); + ~GLShader(); + static bool CheckGLError(int line); +}; + +#endif /* ENGINE_RENDERING_GL_GLSHADER_H */ diff --git a/include/Engine/Rendering/GL/GLShaderBuilder.h b/include/Engine/Rendering/GL/GLShaderBuilder.h new file mode 100644 index 00000000..f201fa0c --- /dev/null +++ b/include/Engine/Rendering/GL/GLShaderBuilder.h @@ -0,0 +1,29 @@ +#ifndef ENGINE_RENDERING_GL_GLSHADERBUILDER_H +#define ENGINE_RENDERING_GL_GLSHADERBUILDER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class GLShaderBuilder { +private: + static void AddUniformsToShaderText(std::string& shaderText, GLShaderUniforms uniforms); + static void AddInputsToVertexShaderText(std::string& shaderText, GLShaderLinkage inputs); + static void AddOutputsToVertexShaderText(std::string& shaderText, GLShaderLinkage outputs); + static void AddInputsToFragmentShaderText(std::string& shaderText, GLShaderLinkage& inputs); + static string BuildFragmentShaderMainFunc(GLShaderLinkage& inputs, GLShaderUniforms& uniforms); + +public: + static string Vertex(GLShaderLinkage& inputs, GLShaderLinkage& outputs, GLShaderUniforms& uniforms); + static string Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms, std::string mainText); + static string Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms); +}; + +#endif /* ENGINE_RENDERING_GL_GLSHADERBUILDER_H */ diff --git a/include/Engine/Rendering/GL/GLShaderContainer.h b/include/Engine/Rendering/GL/GLShaderContainer.h new file mode 100644 index 00000000..dee66008 --- /dev/null +++ b/include/Engine/Rendering/GL/GLShaderContainer.h @@ -0,0 +1,35 @@ +#ifndef ENGINE_RENDERING_GL_GLSHADERCONTAINER_H +#define ENGINE_RENDERING_GL_GLSHADERCONTAINER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class GLShader; +class GLShader; +class GLShader; + +#include +#include + +class GLShaderContainer { +public: + GLShader *Base = nullptr; + GLShader *Textured = nullptr; + GLShader *PalettizedTextured = nullptr; + + GLShaderContainer(); + GLShaderContainer(GLShaderLinkage vsIn, GLShaderLinkage vsOut, GLShaderLinkage fsIn, GLShaderUniforms vsUni, GLShaderUniforms fsUni); + GLShader* Get(bool useTexturing, bool usePalette); + GLShader* Get(bool useTexturing); + GLShader* Get(); + static GLShaderContainer* Make(bool use_vertex_colors); + static GLShaderContainer* MakeFog(int fog_type); + static GLShaderContainer* MakeYUV(); + ~GLShaderContainer(); +}; + +#endif /* ENGINE_RENDERING_GL_GLSHADERCONTAINER_H */ diff --git a/include/Engine/Rendering/GameTexture.h b/include/Engine/Rendering/GameTexture.h new file mode 100644 index 00000000..d0101fc3 --- /dev/null +++ b/include/Engine/Rendering/GameTexture.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_RENDERING_GAMETEXTURE_H +#define ENGINE_RENDERING_GAMETEXTURE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class GameTexture { +public: + Texture* TexturePtr = nullptr; + int UnloadPolicy; + bool OwnsTexture = true; + + GameTexture(); + GameTexture(Uint32 width, Uint32 height, int unloadPolicy); + virtual Texture* GetTexture(); + virtual int GetID(); + ~GameTexture(); +}; + +#endif /* ENGINE_RENDERING_GAMETEXTURE_H */ diff --git a/include/Engine/Rendering/Material.h b/include/Engine/Rendering/Material.h new file mode 100644 index 00000000..b0f8c177 --- /dev/null +++ b/include/Engine/Rendering/Material.h @@ -0,0 +1,39 @@ +#ifndef ENGINE_RENDERING_MATERIAL_H +#define ENGINE_RENDERING_MATERIAL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Material { +public: + char* Name = nullptr; + float ColorDiffuse[4]; + float ColorSpecular[4]; + float ColorAmbient[4]; + float ColorEmissive[4]; + float Shininess = 0.0f; + float ShininessStrength = 1.0f; + float Opacity = 1.0f; + char* TextureDiffuseName = nullptr; + char* TextureSpecularName = nullptr; + char* TextureAmbientName = nullptr; + char* TextureEmissiveName = nullptr; + Image* TextureDiffuse = nullptr; + Image* TextureSpecular = nullptr; + Image* TextureAmbient = nullptr; + Image* TextureEmissive = nullptr; + + Material(); + void Dispose(); + ~Material(); +}; + +#endif /* ENGINE_RENDERING_MATERIAL_H */ diff --git a/include/Engine/Rendering/ModelRenderer.h b/include/Engine/Rendering/ModelRenderer.h new file mode 100644 index 00000000..8b899ef3 --- /dev/null +++ b/include/Engine/Rendering/ModelRenderer.h @@ -0,0 +1,56 @@ +#ifndef ENGINE_RENDERING_MODELRENDERER_H +#define ENGINE_RENDERING_MODELRENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class Matrix4x4; + +#include +#include +#include +#include +#include +#include +#include + +class ModelRenderer { +private: + void Init(); + void AddFace(int faceVertexCount, Material* material); + int ClipFace(int faceVertexCount); + void DrawMesh(IModel* model, Mesh* mesh, Skeleton* skeleton, Matrix4x4& mvpMatrix); + void DrawMesh(IModel* model, Mesh* mesh, Uint16 animation, Uint32 frame, Matrix4x4& mvpMatrix); + void DrawMesh(IModel* model, Mesh* mesh, Vector3* positionBuffer, Vector3* normalBuffer, Vector2* uvBuffer, Matrix4x4& mvpMatrix); + void DrawNode(IModel* model, ModelNode* node, Matrix4x4* world); + void DrawModelInternal(IModel* model, Uint16 animation, Uint32 frame); + +public: + PolygonRenderer* PolyRenderer; + VertexBuffer* Buffer; + VertexAttribute* AttribBuffer; + VertexAttribute* Vertex; + FaceInfo* FaceItem; + Matrix4x4* ModelMatrix; + Matrix4x4* ViewMatrix; + Matrix4x4* ProjectionMatrix; + Matrix4x4* NormalMatrix; + Matrix4x4 MVPMatrix; + bool DoProjection; + bool ClipFaces; + Armature* ArmaturePtr; + Uint32 DrawMode; + Uint8 FaceCullMode; + Uint32 CurrentColor; + + ModelRenderer(PolygonRenderer* polyRenderer); + ModelRenderer(VertexBuffer* buffer); + void SetMatrices(Matrix4x4* model, Matrix4x4* view, Matrix4x4* projection, Matrix4x4* normal); + void DrawModel(IModel* model, Uint16 animation, Uint32 frame); +}; + +#endif /* ENGINE_RENDERING_MODELRENDERER_H */ diff --git a/include/Engine/Rendering/PolygonRenderer.h b/include/Engine/Rendering/PolygonRenderer.h new file mode 100644 index 00000000..e27a4600 --- /dev/null +++ b/include/Engine/Rendering/PolygonRenderer.h @@ -0,0 +1,51 @@ +#ifndef ENGINE_RENDERING_POLYGONRENDERER_H +#define ENGINE_RENDERING_POLYGONRENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include +#include + +class PolygonRenderer { +public: + Scene3D* ScenePtr = nullptr; + VertexBuffer* VertexBuf = nullptr; + Matrix4x4* ModelMatrix = nullptr; + Matrix4x4* NormalMatrix = nullptr; + Matrix4x4* ViewMatrix = nullptr; + Matrix4x4* ProjectionMatrix = nullptr; + Uint32 DrawMode = 0; + Uint8 FaceCullMode = 0; + Uint32 CurrentColor = 0; + bool DoProjection = false; + bool DoClipping = false; + bool ClipPolygonsByFrustum = false; + int NumFrustumPlanes = 0; + Frustum ViewFrustum[NUM_FRUSTUM_PLANES]; + + static int FaceSortFunction(const void *a, const void *b); + void BuildFrustumPlanes(float nearClippingPlane, float farClippingPlane); + bool SetBuffers(); + void DrawPolygon3D(VertexAttribute* data, int vertexCount, int vertexFlag, Texture* texture); + void DrawSceneLayer3D(SceneLayer* layer, int sx, int sy, int sw, int sh); + void DrawModel(IModel* model, Uint16 animation, Uint32 frame); + void DrawModelSkinned(IModel* model, Uint16 armature); + void DrawVertexBuffer(); + int ClipPolygon(PolygonClipBuffer& clipper, VertexAttribute* input, int numVertices); + static bool CheckPolygonVisible(VertexAttribute* vertex, int vertexCount); + static void CopyVertices(VertexAttribute* buffer, VertexAttribute* output, int numVertices); +}; + +#endif /* ENGINE_RENDERING_POLYGONRENDERER_H */ diff --git a/include/Engine/Rendering/SDL2/SDL2Renderer.h b/include/Engine/Rendering/SDL2/SDL2Renderer.h new file mode 100644 index 00000000..12c12c54 --- /dev/null +++ b/include/Engine/Rendering/SDL2/SDL2Renderer.h @@ -0,0 +1,73 @@ +#ifndef ENGINE_RENDERING_SDL2_SDL2RENDERER_H +#define ENGINE_RENDERING_SDL2_SDL2RENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include + +class SDL2Renderer { +private: + static SDL_BlendMode GetCustomBlendMode(int srcC, int dstC, int srcA, int dstA); + +public: + static float RenderScale; + + static void Init(); + static Uint32 GetWindowFlags(); + static void SetVSync(bool enabled); + static void SetGraphicsFunctions(); + static void Dispose(); + static Texture* CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + static int LockTexture(Texture* texture, void** pixels, int* pitch); + static int UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch); + static int UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV); + static void UnlockTexture(Texture* texture); + static void DisposeTexture(Texture* texture); + static void SetRenderTarget(Texture* texture); + static void CopyScreen(void* pixels, int width, int height); + static void UpdateWindowSize(int width, int height); + static void UpdateViewport(); + static void UpdateClipRect(); + static void UpdateOrtho(float left, float top, float right, float bottom); + static void UpdatePerspective(float fovy, float aspect, float nearv, float farv); + static void UpdateProjectionMatrix(); + static void MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect); + static void GetMetalSize(int* width, int* height); + static void UseShader(void* shader); + static void SetUniformF(int location, int count, float* values); + static void SetUniformI(int location, int count, int* values); + static void SetUniformTexture(Texture* texture, int uniform_index, int slot); + static void Clear(); + static void Present(); + static void SetBlendColor(float r, float g, float b, float a); + static void SetBlendMode(int srcC, int dstC, int srcA, int dstA); + static void SetTintColor(float r, float g, float b, float a); + static void SetTintMode(int mode); + static void SetTintEnabled(bool enabled); + static void SetLineWidth(float n); + static void StrokeLine(float x1, float y1, float x2, float y2); + static void StrokeCircle(float x, float y, float rad, float thickness); + static void StrokeEllipse(float x, float y, float w, float h); + static void StrokeRectangle(float x, float y, float w, float h); + static void FillCircle(float x, float y, float rad); + static void FillEllipse(float x, float y, float w, float h); + static void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void FillRectangle(float x, float y, float w, float h); + static void DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void MakeFrameBufferID(ISprite* sprite, AnimFrame* frame); +}; + +#endif /* ENGINE_RENDERING_SDL2_SDL2RENDERER_H */ diff --git a/include/Engine/Rendering/Shader.h b/include/Engine/Rendering/Shader.h new file mode 100644 index 00000000..7a7be261 --- /dev/null +++ b/include/Engine/Rendering/Shader.h @@ -0,0 +1,19 @@ +#ifndef ENGINE_RENDERING_SHADER_H +#define ENGINE_RENDERING_SHADER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class Shader { +public: + static Shader* New(); +}; + +#endif /* ENGINE_RENDERING_SHADER_H */ diff --git a/include/Engine/Rendering/Software/PolygonRasterizer.h b/include/Engine/Rendering/Software/PolygonRasterizer.h new file mode 100644 index 00000000..1a4ff086 --- /dev/null +++ b/include/Engine/Rendering/Software/PolygonRasterizer.h @@ -0,0 +1,52 @@ +#ifndef ENGINE_RENDERING_SOFTWARE_POLYGONRASTERIZER_H +#define ENGINE_RENDERING_SOFTWARE_POLYGONRASTERIZER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class PolygonRasterizer { +public: + static bool DepthTest; + static size_t DepthBufferSize; + static Uint32* DepthBuffer; + static bool UseDepthBuffer; + static bool UseFog; + static float FogStart; + static float FogEnd; + static float FogDensity; + static int FogColor; + static Uint16 FogTable[0x100 + 1]; + + static void DrawBasic(Vector2* positions, Uint32 color, int count, BlendState blendState); + static void DrawBasicBlend(Vector2* positions, int* colors, int count, BlendState blendState); + static void DrawShaded(Vector3* positions, Uint32 color, int count, BlendState blendState); + static void DrawBlendShaded(Vector3* positions, int* colors, int count, BlendState blendState); + static void DrawAffine(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState); + static void DrawBlendAffine(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState); + static void DrawPerspective(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState); + static void DrawBlendPerspective(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState); + static void DrawDepth(Vector3* positions, Uint32 color, int count, BlendState blendState); + static void DrawBlendDepth(Vector3* positions, int* colors, int count, BlendState blendState); + static void SetDepthTest(bool enabled); + static void FreeDepthBuffer(void); + static void SetUseDepthBuffer(bool enabled); + static void SetUseFog(bool enabled); + static void SetFogEquation(FogEquation equation); + static void SetFogStart(float start); + static void SetFogEnd(float end); + static void SetFogDensity(float density); + static void SetFogColor(float r, float g, float b); + static void SetFogSmoothness(float smoothness); +}; + +#endif /* ENGINE_RENDERING_SOFTWARE_POLYGONRASTERIZER_H */ diff --git a/include/Engine/Rendering/Software/Scanline.h b/include/Engine/Rendering/Software/Scanline.h new file mode 100644 index 00000000..f17bb4d0 --- /dev/null +++ b/include/Engine/Rendering/Software/Scanline.h @@ -0,0 +1,30 @@ +#ifndef ENGINE_RENDERING_SOFTWARE_SCANLINE_H +#define ENGINE_RENDERING_SOFTWARE_SCANLINE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class Scanline { +public: + static void Prepare(int y1, int y2); + static void Process(int x1, int y1, int x2, int y2); + static void Process(int color1, int color2, int x1, int y1, int x2, int y2); + static void ProcessDepth(int x1, int y1, int z1, int x2, int y2, int z2); + static void ProcessDepth(int color1, int color2, int x1, int y1, int z1, int x2, int y2, int z2); + static void ProcessUVAffine(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2); + static void ProcessUVAffine(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2); + static void ProcessUV(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2); + static void ProcessUV(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2); +}; + +#endif /* ENGINE_RENDERING_SOFTWARE_SCANLINE_H */ diff --git a/include/Engine/Rendering/Software/SoftwareRenderer.h b/include/Engine/Rendering/Software/SoftwareRenderer.h new file mode 100644 index 00000000..6dd1a76d --- /dev/null +++ b/include/Engine/Rendering/Software/SoftwareRenderer.h @@ -0,0 +1,155 @@ +#ifndef ENGINE_RENDERING_SOFTWARE_SOFTWARERENDERER_H +#define ENGINE_RENDERING_SOFTWARE_SOFTWARERENDERER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SoftwareRenderer { +private: + static void SetColor(Uint32 color); + static Uint32 GetBlendColor(); + static bool SetupPolygonRenderer(Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void InitContour(Contour *contourBuffer, int dst_y1, int scanLineCount); + static void RasterizeCircle(int ccx, int ccy, int dst_x1, int dst_y1, int dst_x2, int dst_y2, float rad, Contour *contourBuffer); + static void StrokeThickCircle(float x, float y, float rad, float thickness); + static void DrawShapeTextured(Texture* texturePtr, unsigned numPoints, float* px, float* py, int* pc, float* pu, float* pv); + +public: + static GraphicsFunctions BackendFunctions; + static Uint32 CompareColor; + static TileScanLine TileScanLineBuffer[MAX_FRAMEBUFFER_HEIGHT]; + static Sint32 SpriteDeformBuffer[MAX_FRAMEBUFFER_HEIGHT]; + static bool UseSpriteDeform; + static Contour ContourBuffer[MAX_FRAMEBUFFER_HEIGHT]; + static int MultTable[0x10000]; + static int MultTableInv[0x10000]; + static int MultSubTable[0x10000]; + + static void Init(); + static Uint32 GetWindowFlags(); + static void SetGraphicsFunctions(); + static void Dispose(); + static void RenderStart(); + static void RenderEnd(); + static Texture* CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + static int LockTexture(Texture* texture, void** pixels, int* pitch); + static int UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch); + static void UnlockTexture(Texture* texture); + static void DisposeTexture(Texture* texture); + static void SetRenderTarget(Texture* texture); + static void ReadFramebuffer(void* pixels, int width, int height); + static void UpdateWindowSize(int width, int height); + static void UpdateViewport(); + static void UpdateClipRect(); + static void UpdateOrtho(float left, float top, float right, float bottom); + static void UpdatePerspective(float fovy, float aspect, float nearv, float farv); + static void UpdateProjectionMatrix(); + static void MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect); + static void UseShader(void* shader); + static void SetUniformF(int location, int count, float* values); + static void SetUniformI(int location, int count, int* values); + static void SetUniformTexture(Texture* texture, int uniform_index, int slot); + static void SetFilter(int filter); + static void Clear(); + static void Present(); + static void SetBlendColor(float r, float g, float b, float a); + static void SetBlendMode(int srcC, int dstC, int srcA, int dstA); + static void SetTintColor(float r, float g, float b, float a); + static void SetTintMode(int mode); + static void SetTintEnabled(bool enabled); + static void Resize(int width, int height); + static void SetClip(float x, float y, float width, float height); + static void ClearClip(); + static void Save(); + static void Translate(float x, float y, float z); + static void Rotate(float x, float y, float z); + static void Scale(float x, float y, float z); + static void Restore(); + static int ConvertBlendMode(int blendMode); + static BlendState GetBlendState(); + static bool AlterBlendState(BlendState& state); + static void PixelNoFiltSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelNoFiltSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelNoFiltSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelNoFiltSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelNoFiltSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelNoFiltSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelTintSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void SetTintFunction(int blendFlags); + static void SetStencilEnabled(bool enabled); + static bool IsStencilEnabled(); + static void SetStencilTestFunc(int stencilTest); + static void SetStencilPassFunc(int stencilOp); + static void SetStencilFailFunc(int stencilOp); + static void SetStencilValue(int value); + static void SetStencilMask(int mask); + static void ClearStencil(); + static void PixelStencil(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void SetDotMask(int mask); + static void SetDotMaskH(int mask); + static void SetDotMaskV(int mask); + static void SetDotMaskOffsetH(int offset); + static void SetDotMaskOffsetV(int offset); + static void PixelDotMaskH(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelDotMaskV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void PixelDotMaskHV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt); + static void BindVertexBuffer(Uint32 vertexBufferIndex); + static void UnbindVertexBuffer(); + static void BindScene3D(Uint32 sceneIndex); + static void DrawScene3D(Uint32 sceneIndex, Uint32 drawMode); + static void DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static void DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix); + static PixelFunction GetPixelFunction(int blendFlag); + static void SetLineWidth(float n); + static void StrokeLine(float x1, float y1, float x2, float y2); + static void StrokeCircle(float x, float y, float rad, float thickness); + static void StrokeEllipse(float x, float y, float w, float h); + static void StrokeRectangle(float x, float y, float w, float h); + static void FillCircle(float x, float y, float rad); + static void FillEllipse(float x, float y, float w, float h); + static void FillRectangle(float x, float y, float w, float h); + static void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3); + static void FillTriangleBlend(float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3); + static void FillQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4); + static void FillQuadBlend(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4); + static void DrawTriangleTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3, float u1, float v1, float u2, float v2, float u3, float v3); + static void DrawQuadTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4, float u1, float v1, float u2, float v2, float u3, float v3, float u4, float v4); + static void DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h); + static void DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID); + static void DrawTile(int tile, int x, int y, bool flipX, bool flipY); + static void DrawSceneLayer_InitTileScanLines(SceneLayer* layer, View* currentView); + static void DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView); + static void DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView); + static void DrawSceneLayer_CustomTileScanLines(SceneLayer* layer, View* currentView); + static void DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction); + static void MakeFrameBufferID(ISprite* sprite, AnimFrame* frame); +}; + +#endif /* ENGINE_RENDERING_SOFTWARE_SOFTWARERENDERER_H */ diff --git a/include/Engine/Rendering/Texture.h b/include/Engine/Rendering/Texture.h new file mode 100644 index 00000000..812e71e3 --- /dev/null +++ b/include/Engine/Rendering/Texture.h @@ -0,0 +1,39 @@ +#ifndef ENGINE_RENDERING_TEXTURE_H +#define ENGINE_RENDERING_TEXTURE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class Texture; + +#include + +class Texture { +public: + Uint32 Format; + Uint32 Access; + Uint32 Width; + Uint32 Height; + void* Pixels; + int Pitch; + Uint32 ID; + void* DriverData; + Texture* Prev; + Texture* Next; + bool Paletted; + Uint32* PaletteColors; + unsigned NumPaletteColors; + + static Texture* New(Uint32 format, Uint32 access, Uint32 width, Uint32 height); + void SetPalette(Uint32* palette, unsigned numPaletteColors); + bool ConvertToRGBA(); + bool ConvertToPalette(Uint32 *palColors, unsigned numPaletteColors); + void Copy(Texture* source); + void Dispose(); +}; + +#endif /* ENGINE_RENDERING_TEXTURE_H */ diff --git a/include/Engine/Rendering/TextureReference.h b/include/Engine/Rendering/TextureReference.h new file mode 100644 index 00000000..30432674 --- /dev/null +++ b/include/Engine/Rendering/TextureReference.h @@ -0,0 +1,25 @@ +#ifndef ENGINE_RENDERING_TEXTUREREFERENCE_H +#define ENGINE_RENDERING_TEXTUREREFERENCE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class Texture; + +#include + +class TextureReference { +public: + Texture* TexturePtr; + unsigned References; + + TextureReference(Texture *ptr); + void AddRef(); + bool TakeRef(); +}; + +#endif /* ENGINE_RENDERING_TEXTUREREFERENCE_H */ diff --git a/include/Engine/Rendering/VertexBuffer.h b/include/Engine/Rendering/VertexBuffer.h new file mode 100644 index 00000000..37469ad2 --- /dev/null +++ b/include/Engine/Rendering/VertexBuffer.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_RENDERING_VERTEXBUFFER_H +#define ENGINE_RENDERING_VERTEXBUFFER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class VertexBuffer { +public: + VertexAttribute* Vertices = nullptr; // count = max vertex count + FaceInfo* FaceInfoBuffer = nullptr; // count = max face count + void* DriverData = nullptr; + Uint32 Capacity = 0; + Uint32 VertexCount = 0; + Uint32 FaceCount = 0; + Uint32 UnloadPolicy; + + VertexBuffer(); + VertexBuffer(Uint32 numVertices); + void Init(Uint32 numVertices); + void Clear(); + void Resize(Uint32 numVertices); + ~VertexBuffer(); +}; + +#endif /* ENGINE_RENDERING_VERTEXBUFFER_H */ diff --git a/include/Engine/Rendering/ViewTexture.h b/include/Engine/Rendering/ViewTexture.h new file mode 100644 index 00000000..90fdf197 --- /dev/null +++ b/include/Engine/Rendering/ViewTexture.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_RENDERING_VIEWTEXTURE_H +#define ENGINE_RENDERING_VIEWTEXTURE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ViewTexture : public GameTexture { +public: + int ViewIndex; + + ViewTexture(int viewIndex); + virtual Texture* GetTexture(); + virtual int GetID(); +}; + +#endif /* ENGINE_RENDERING_VIEWTEXTURE_H */ diff --git a/include/Engine/ResourceTypes/IModel.h b/include/Engine/ResourceTypes/IModel.h new file mode 100644 index 00000000..4cb5d5de --- /dev/null +++ b/include/Engine/ResourceTypes/IModel.h @@ -0,0 +1,62 @@ +#ifndef ENGINE_RESOURCETYPES_IMODEL_H +#define ENGINE_RESOURCETYPES_IMODEL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include + +class IModel { +private: + static Image* TryLoadMaterialImage(std::string imagePath, const char *parentDirectory); + void UpdateChannel(Matrix4x4* out, NodeAnim* channel, Uint32 frame); + +public: + Mesh** Meshes; + size_t MeshCount; + size_t VertexCount; + size_t VertexIndexCount; + Uint8 VertexPerFace; + Material** Materials; + size_t MaterialCount; + ModelAnim** Animations; + size_t AnimationCount; + Armature** ArmatureList; + size_t ArmatureCount; + bool UseVertexAnimation; + Armature* BaseArmature; + Matrix4x4* GlobalInverseMatrix; + + IModel(); + IModel(const char* filename); + bool Load(Stream* stream, const char* filename); + bool HasMaterials(); + static Image* LoadMaterialImage(string imagePath, const char *parentDirectory); + static Image* LoadMaterialImage(const char *imagePath, const char *parentDirectory); + bool HasBones(); + void AnimateNode(ModelNode* node, SkeletalAnim* animation, Uint32 frame, Matrix4x4* parentMatrix); + void Pose(); + void Pose(Armature* armature, SkeletalAnim* animation, Uint32 frame); + Uint32 GetKeyFrame(Uint32 frame); + Sint64 GetInBetween(Uint32 frame); + void DoVertexFrameInterpolation(Mesh* mesh, ModelAnim* animation, Uint32 frame, Vector3** positionBuffer, Vector3** normalBuffer, Vector2** uvBuffer); + void Animate(Armature* armature, ModelAnim* animation, Uint32 frame); + void Animate(Uint16 animation, Uint32 frame); + int GetAnimationIndex(const char* animationName); + int NewArmature(); + void DeleteArmature(size_t index); + void Dispose(); + ~IModel(); +}; + +#endif /* ENGINE_RESOURCETYPES_IMODEL_H */ diff --git a/include/Engine/ResourceTypes/ISound.h b/include/Engine/ResourceTypes/ISound.h new file mode 100644 index 00000000..b235e796 --- /dev/null +++ b/include/Engine/ResourceTypes/ISound.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_RESOURCETYPES_ISOUND_H +#define ENGINE_RESOURCETYPES_ISOUND_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include + +class ISound { +public: + SDL_AudioSpec Format; + int BytesPerSample; + SoundFormat* SoundData = NULL; + char Filename[256]; + bool LoadFailed = false; + bool StreamFromFile = false; + + ISound(const char* filename); + ISound(const char* filename, bool streamFromFile); + void Load(const char* filename, bool streamFromFile); + AudioPlayback* CreatePlayer(); + void Dispose(); +}; + +#endif /* ENGINE_RESOURCETYPES_ISOUND_H */ diff --git a/include/Engine/ResourceTypes/ISprite.h b/include/Engine/ResourceTypes/ISprite.h new file mode 100644 index 00000000..e384f2af --- /dev/null +++ b/include/Engine/ResourceTypes/ISprite.h @@ -0,0 +1,45 @@ +#ifndef ENGINE_RESOURCETYPES_ISPRITE_H +#define ENGINE_RESOURCETYPES_ISPRITE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class ISprite { +public: + char* Filename = nullptr; + bool LoadFailed = true; + vector Spritesheets; + vector SpritesheetFilenames; + int CollisionBoxCount = 0; + vector Animations; + + ISprite(); + ISprite(const char* filename); + Texture* AddSpriteSheet(const char* filename); + void ReserveAnimationCount(int count); + void AddAnimation(const char* name, int animationSpeed, int frameToLoop); + void AddAnimation(const char* name, int animationSpeed, int frameToLoop, int frmAlloc); + void AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY); + void AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id); + void AddFrame(int animID, int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id); + void RemoveFrames(int animID); + void ConvertToRGBA(); + void ConvertToPalette(unsigned paletteNumber); + bool LoadAnimation(const char* filename); + int FindAnimation(const char* animname); + void LinkAnimation(vector ani); + bool SaveAnimation(const char* filename); + void Dispose(); + ~ISprite(); +}; + +#endif /* ENGINE_RESOURCETYPES_ISPRITE_H */ diff --git a/include/Engine/ResourceTypes/Image.h b/include/Engine/ResourceTypes/Image.h new file mode 100644 index 00000000..f07a81b5 --- /dev/null +++ b/include/Engine/ResourceTypes/Image.h @@ -0,0 +1,26 @@ +#ifndef ENGINE_RESOURCETYPES_IMAGE_H +#define ENGINE_RESOURCETYPES_IMAGE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class Image { +public: + char Filename[256]; + Texture* TexturePtr = NULL; + + Image(const char* filename); + void Dispose(); + ~Image(); + static Texture* LoadTextureFromResource(const char* filename); +}; + +#endif /* ENGINE_RESOURCETYPES_IMAGE_H */ diff --git a/include/Engine/ResourceTypes/ImageFormats/GIF.h b/include/Engine/ResourceTypes/ImageFormats/GIF.h new file mode 100644 index 00000000..5f086aae --- /dev/null +++ b/include/Engine/ResourceTypes/ImageFormats/GIF.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_GIF_H +#define ENGINE_RESOURCETYPES_IMAGEFORMATS_GIF_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class GIF : public ImageFormat { +private: + static inline Uint32 ReadCode(Stream* stream, int codeSize, int* blockLength, int* bitCache, int* bitCacheLength); + static inline void WriteCode(Stream* stream, int* offset, int* partial, Uint8* buffer, uint16_t key, int key_size); + inline void WriteFrame(Stream* stream, Uint32* data); + static void* NewNode(Uint16 key, int degree); + static void* NewTree(int degree, int* nkeys); + static void FreeTree(void* root, int degree); + +public: + vector Frames; + + static GIF* Load(const char* filename); + static bool Save(GIF* gif, const char* filename); + bool Save(const char* filename); + ~GIF(); +}; + +#endif /* ENGINE_RESOURCETYPES_IMAGEFORMATS_GIF_H */ diff --git a/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h b/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h new file mode 100644 index 00000000..0aeaa103 --- /dev/null +++ b/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_IMAGEFORMAT_H +#define ENGINE_RESOURCETYPES_IMAGEFORMATS_IMAGEFORMAT_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class ImageFormat { +public: + Uint32* Colors = NULL; + Uint32* Data = NULL; + Uint32 Width = 0; + Uint32 Height = 0; + bool Paletted = false; + Uint16 NumPaletteColors = 0; + + Uint32* GetPalette(); + virtual bool Save(const char* filename); + virtual ~ImageFormat(); +}; + +#endif /* ENGINE_RESOURCETYPES_IMAGEFORMATS_IMAGEFORMAT_H */ diff --git a/include/Engine/ResourceTypes/ImageFormats/JPEG.h b/include/Engine/ResourceTypes/ImageFormats/JPEG.h new file mode 100644 index 00000000..bb282089 --- /dev/null +++ b/include/Engine/ResourceTypes/ImageFormats/JPEG.h @@ -0,0 +1,24 @@ +#ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_JPEG_H +#define ENGINE_RESOURCETYPES_IMAGEFORMATS_JPEG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class JPEG : public ImageFormat { +public: + static JPEG* Load(const char* filename); + static bool Save(JPEG* jpeg, const char* filename); + bool Save(const char* filename); + ~JPEG(); +}; + +#endif /* ENGINE_RESOURCETYPES_IMAGEFORMATS_JPEG_H */ diff --git a/include/Engine/ResourceTypes/ImageFormats/PNG.h b/include/Engine/ResourceTypes/ImageFormats/PNG.h new file mode 100644 index 00000000..873b5a2d --- /dev/null +++ b/include/Engine/ResourceTypes/ImageFormats/PNG.h @@ -0,0 +1,26 @@ +#ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_PNG_H +#define ENGINE_RESOURCETYPES_IMAGEFORMATS_PNG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class PNG : public ImageFormat { +public: + static PNG* Load(const char* filename); + void ReadPixelDataARGB(Uint32* pixelData, int num_channels); + void ReadPixelBitstream(Uint8* pixelData, size_t bit_depth); + static bool Save(PNG* png, const char* filename); + bool Save(const char* filename); + ~PNG(); +}; + +#endif /* ENGINE_RESOURCETYPES_IMAGEFORMATS_PNG_H */ diff --git a/include/Engine/ResourceTypes/ModelFormats/HatchModel.h b/include/Engine/ResourceTypes/ModelFormats/HatchModel.h new file mode 100644 index 00000000..0de23bdf --- /dev/null +++ b/include/Engine/ResourceTypes/ModelFormats/HatchModel.h @@ -0,0 +1,50 @@ +#ifndef ENGINE_RESOURCETYPES_MODELFORMATS_HATCHMODEL_H +#define ENGINE_RESOURCETYPES_MODELFORMATS_HATCHMODEL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class HatchModel { +private: + static Material* ReadMaterial(Stream* stream, const char *parentDirectory); + static void ReadVertexStore(Stream* stream); + static void ReadNormalStore(Stream* stream); + static void ReadTexCoordStore(Stream* stream); + static void ReadColorStore(Stream* stream); + static Vector3 GetStoredVertex(Uint32 idx); + static Vector3 GetStoredNormal(Uint32 idx); + static Vector2 GetStoredTexCoord(Uint32 idx); + static Uint32 GetStoredColor(Uint32 idx); + static void ReadVertexIndices(Sint32* indices, Uint32 triangleCount, Stream* stream); + static Mesh* ReadMesh(IModel* model, Stream* stream); + static void WriteMesh(Mesh* mesh, Stream* stream); + static char* GetMaterialTextureName(const char* name, const char* parentDirectory); + static void WriteColorIndex(Uint32* color, Stream* stream); + static void WriteMaterial(Material* material, Stream* stream, const char* parentDirectory); + +public: + static Sint32 Version; + static Uint32 NumVertexStore; + static Uint32 NumNormalStore; + static Uint32 NumTexCoordStore; + static Uint32 NumColorStore; + static Vector3* VertexStore; + static Vector3* NormalStore; + static Vector2* TexCoordStore; + static Uint32* ColorStore; + + static bool IsMagic(Stream* stream); + static void ReadMaterialInfo(Stream* stream, Uint8 *destColors, char **texName); + static bool Convert(IModel* model, Stream* stream, const char* path); + static bool Save(IModel* model, const char* filename); +}; + +#endif /* ENGINE_RESOURCETYPES_MODELFORMATS_HATCHMODEL_H */ diff --git a/include/Engine/ResourceTypes/ModelFormats/Importer.h b/include/Engine/ResourceTypes/ModelFormats/Importer.h new file mode 100644 index 00000000..2c8958c0 --- /dev/null +++ b/include/Engine/ResourceTypes/ModelFormats/Importer.h @@ -0,0 +1,32 @@ +#ifndef ENGINE_RESOURCETYPES_MODELFORMATS_IMPORTER_H +#define ENGINE_RESOURCETYPES_MODELFORMATS_IMPORTER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class ModelImporter { +private: + static Mesh* LoadMesh(IModel* imodel, struct aiMesh* amesh); + static Material* LoadMaterial(IModel* imodel, struct aiMaterial* mat, unsigned i); + static ModelNode* LoadNode(IModel* imodel, ModelNode* parent, const struct aiNode* anode); + static Skeleton* LoadBones(IModel* imodel, Mesh* mesh, struct aiMesh* amesh); + static SkeletalAnim* LoadAnimation(IModel* imodel, ModelAnim* parentAnim, struct aiAnimation* aanim); + static bool DoConversion(const struct aiScene* scene, IModel* imodel); + +public: + static vector MeshIDs; + static char* ParentDirectory; + + static bool Convert(IModel* model, Stream* stream, const char* path); +}; + +#endif /* ENGINE_RESOURCETYPES_MODELFORMATS_IMPORTER_H */ diff --git a/include/Engine/ResourceTypes/ModelFormats/MD3Model.h b/include/Engine/ResourceTypes/ModelFormats/MD3Model.h new file mode 100644 index 00000000..ae68b6f1 --- /dev/null +++ b/include/Engine/ResourceTypes/ModelFormats/MD3Model.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_RESOURCETYPES_MODELFORMATS_MD3MODEL_H +#define ENGINE_RESOURCETYPES_MODELFORMATS_MD3MODEL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class MD3Model { +private: + static void DecodeNormal(Uint16 index, float& x, float& y, float& z); + static void ReadShader(Stream* stream); + static void ReadVerticesAndNormals(Vector3* vert, Vector3* norm, Sint32 vertexCount, Stream* stream); + static void ReadUVs(Vector2* uvs, Sint32 vertexCount, Stream* stream); + static void ReadVertexIndices(Sint32* indices, Sint32 triangleCount, Stream* stream); + static Mesh* ReadSurface(IModel* model, Stream* stream, size_t surfaceDataOffset); + +public: + static Sint32 Version; + static bool UseUVKeyframes; + static Sint32 DataEndOffset; + static vector MaterialNames; + + static bool IsMagic(Stream* stream); + static bool Convert(IModel* model, Stream* stream, const char* path); +}; + +#endif /* ENGINE_RESOURCETYPES_MODELFORMATS_MD3MODEL_H */ diff --git a/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h b/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h new file mode 100644 index 00000000..126b3c50 --- /dev/null +++ b/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h @@ -0,0 +1,21 @@ +#ifndef ENGINE_RESOURCETYPES_MODELFORMATS_RSDKMODEL_H +#define ENGINE_RESOURCETYPES_MODELFORMATS_RSDKMODEL_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class RSDKModel { +public: + static bool IsMagic(Stream* stream); + static bool Convert(IModel* model, Stream* stream); +}; + +#endif /* ENGINE_RESOURCETYPES_MODELFORMATS_RSDKMODEL_H */ diff --git a/include/Engine/ResourceTypes/ResourceManager.h b/include/Engine/ResourceTypes/ResourceManager.h new file mode 100644 index 00000000..700adcbf --- /dev/null +++ b/include/Engine/ResourceTypes/ResourceManager.h @@ -0,0 +1,29 @@ +#ifndef ENGINE_RESOURCETYPES_RESOURCEMANAGER_H +#define ENGINE_RESOURCETYPES_RESOURCEMANAGER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ResourceManager { +public: + static bool UsingDataFolder; + static bool UsingModPack; + + static void PrefixResourcePath(char* out, size_t outSize, const char* path); + static void PrefixParentPath(char* out, size_t outSize, const char* path); + static void Init(const char* filename); + static void Load(const char* filename); + static bool LoadResource(const char* filename, Uint8** out, size_t* size); + static bool ResourceExists(const char* filename); + static void Dispose(); +}; + +#endif /* ENGINE_RESOURCETYPES_RESOURCEMANAGER_H */ diff --git a/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h b/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h new file mode 100644 index 00000000..8ece0810 --- /dev/null +++ b/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h @@ -0,0 +1,39 @@ +#ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_HATCHSCENEREADER_H +#define ENGINE_RESOURCETYPES_SCENEFORMATS_HATCHSCENEREADER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class HatchSceneReader { +private: + static SceneLayer ReadLayer(Stream* r); + static void ReadTileData(Stream* r, SceneLayer layer); + static void ConvertTileData(SceneLayer* layer); + static void ReadScrollData(Stream* r, SceneLayer layer); + static SceneClass* FindClass(SceneHash hash); + static SceneClassProperty* FindProperty(SceneClass* scnClass, SceneHash hash); + static void HashString(char* string, SceneHash* hash); + static void ReadClasses(Stream *r); + static void FreeClasses(); + static bool LoadTileset(const char* parentFolder); + static void ReadEntities(Stream *r); + static void SkipEntityProperties(Stream *r, Uint8 numProps); + static void SkipProperty(Stream *r, Uint8 varType); + +public: + static Uint32 Magic; + + static bool Read(const char* filename, const char* parentFolder); + static bool Read(Stream* r, const char* parentFolder); +}; + +#endif /* ENGINE_RESOURCETYPES_SCENEFORMATS_HATCHSCENEREADER_H */ diff --git a/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h b/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h new file mode 100644 index 00000000..395e9265 --- /dev/null +++ b/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h @@ -0,0 +1,33 @@ +#ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_RSDKSCENEREADER_H +#define ENGINE_RESOURCETYPES_SCENEFORMATS_RSDKSCENEREADER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class RSDKSceneReader { +private: + static void LoadObjectList(); + static void LoadPropertyList(); + static SceneLayer ReadLayer(Stream* r); + static bool LoadTileset(const char* parentFolder); + +public: + static Uint32 Magic; + static bool Initialized; + + static void StageConfig_GetColors(const char* filename); + static void GameConfig_GetColors(const char* filename); + static bool Read(const char* filename, const char* parentFolder); + static bool ReadObjectDefinition(Stream* r, Entity** objSlots, const int maxObjSlots); + static bool Read(Stream* r, const char* parentFolder); +}; + +#endif /* ENGINE_RESOURCETYPES_SCENEFORMATS_RSDKSCENEREADER_H */ diff --git a/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h b/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h new file mode 100644 index 00000000..ae0cd7d1 --- /dev/null +++ b/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h @@ -0,0 +1,29 @@ +#ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_TILEDMAPREADER_H +#define ENGINE_RESOURCETYPES_SCENEFORMATS_TILEDMAPREADER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class TiledMapReader { +private: + static VMValue ParseProperty(XMLNode* property); + static void ParsePropertyNode(XMLNode* node, HashMap* properties); + static ObjArray* ParsePolyPoints(XMLNode* node); + static Tileset* ParseTilesetImage(XMLNode* node, int firstgid, const char* parentFolder); + static void ParseTileAnimation(int tileID, int firstgid, Tileset* tilesetPtr, XMLNode* node); + static void ParseTile(Tileset* tilesetPtr, XMLNode* node); + static void LoadTileset(XMLNode* tileset, const char* parentFolder); + +public: + static void Read(const char* sourceF, const char* parentFolder); +}; + +#endif /* ENGINE_RESOURCETYPES_SCENEFORMATS_TILEDMAPREADER_H */ diff --git a/include/Engine/ResourceTypes/SoundFormats/OGG.h b/include/Engine/ResourceTypes/SoundFormats/OGG.h new file mode 100644 index 00000000..710b2d18 --- /dev/null +++ b/include/Engine/ResourceTypes/SoundFormats/OGG.h @@ -0,0 +1,36 @@ +#ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_OGG_H +#define ENGINE_RESOURCETYPES_SOUNDFORMATS_OGG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class OGG : public SoundFormat { +private: + // OGG Specific + char Vorbis[0x800]; + + static size_t StaticRead(void* mem, size_t size, size_t nmemb, void* ptr); + static Sint32 StaticSeek(void* ptr, Sint64 offset, int whence); + static Sint32 StaticCloseFree(void* ptr); + static Sint32 StaticCloseNoFree(void* ptr); + static long StaticTell(void* ptr); + +public: + static SoundFormat* Load(const char* filename); + size_t SeekSample(int index); + int LoadSamples(size_t count); + int GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex); + virtual void LoadAllSamples(); + void Dispose(); +}; + +#endif /* ENGINE_RESOURCETYPES_SOUNDFORMATS_OGG_H */ diff --git a/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h b/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h new file mode 100644 index 00000000..ef1e05a1 --- /dev/null +++ b/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h @@ -0,0 +1,43 @@ +#ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_SOUNDFORMAT_H +#define ENGINE_RESOURCETYPES_SOUNDFORMATS_SOUNDFORMAT_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class SoundFormat { +public: + // Common + Stream* StreamPtr = NULL; + SDL_AudioSpec InputFormat; + vector Samples; + size_t SampleSize; + size_t SampleIndex = 0; + int TotalPossibleSamples; + Uint8* SampleBuffer = NULL; + + virtual int LoadSamples(size_t count); + virtual int GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex); + virtual size_t SeekSample(int index); + virtual size_t TellSample(); + virtual void LoadAllSamples(); + void CopySamples(SoundFormat* dest); + virtual double GetPosition(); + virtual double SetPosition(double seconds); + virtual double GetDuration(); + virtual ~SoundFormat(); + virtual void Close(); + virtual void Dispose(); +protected: + void LoadFinish(); +}; + +#endif /* ENGINE_RESOURCETYPES_SOUNDFORMATS_SOUNDFORMAT_H */ diff --git a/include/Engine/ResourceTypes/SoundFormats/WAV.h b/include/Engine/ResourceTypes/SoundFormats/WAV.h new file mode 100644 index 00000000..0fd0536f --- /dev/null +++ b/include/Engine/ResourceTypes/SoundFormats/WAV.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_WAV_H +#define ENGINE_RESOURCETYPES_SOUNDFORMATS_WAV_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class WAV : public SoundFormat { +private: + // WAV Specific + int DataStart = 0; + + +public: + static SoundFormat* Load(const char* filename); + int LoadSamples(size_t count); + void Dispose(); +}; + +#endif /* ENGINE_RESOURCETYPES_SOUNDFORMATS_WAV_H */ diff --git a/include/Engine/Scene.h b/include/Engine/Scene.h new file mode 100644 index 00000000..a0b35065 --- /dev/null +++ b/include/Engine/Scene.h @@ -0,0 +1,212 @@ +#ifndef ENGINE_SCENE_H +#define ENGINE_SCENE_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class Entity; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Scene { +private: + static void RemoveObject(Entity* obj); + static void RunTileAnimations(); + static void ResetViews(); + static void Iterate(Entity* first, std::function func); + static void IterateAll(Entity* first, std::function func); + static void ResetPriorityListIndex(Entity* first); + static int GetPersistenceScopeForObjectDeletion(); + static void ClearPriorityLists(); + static void DeleteObjects(Entity** first, Entity** last, int* count); + static void RemoveNonPersistentObjects(Entity** first, Entity** last, int* count); + static void DeleteAllObjects(); + static void AddStaticClass(); + static void CallGameStart(); + static void SpawnStaticObject(const char* objectName); + static void ReadRSDKTile(TileConfig* tile, Uint8* line); + static void LoadRSDKTileConfig(int tilesetID, Stream* tileColReader); + static void LoadHCOLTileConfig(size_t tilesetID, Stream* tileColReader); + static void InitTileCollisions(); + static void ClearTileCollisions(TileConfig* cfg, size_t numTiles); + static void SetTileCount(size_t tileCount); + +public: + static int ShowTileCollisionFlag; + static int ShowObjectRegions; + static HashMap* Properties; + static HashMap* ObjectLists; + static HashMap* ObjectRegistries; + static HashMap* StaticObjectLists; + static int StaticObjectCount; + static Entity* StaticObjectFirst; + static Entity* StaticObjectLast; + static int DynamicObjectCount; + static Entity* DynamicObjectFirst; + static Entity* DynamicObjectLast; + static int ObjectCount; + static Entity* ObjectFirst; + static Entity* ObjectLast; + static int BasePriorityPerLayer; + static int PriorityPerLayer; + static DrawGroupList* PriorityLists; + static vector Tilesets; + static vector TileSpriteInfos; + static Uint16 EmptyTile; + static vector Layers; + static bool AnyLayerTileChange; + static int TileCount; + static int TileWidth; + static int TileHeight; + static int BaseTileCount; + static int BaseTilesetCount; + static bool TileCfgLoaded; + static vector TileCfg; + static vector SpriteList; + static vector ImageList; + static vector SoundList; + static vector MusicList; + static vector ModelList; + static vector MediaList; + static vector TextureList; + static vector AnimatorList; + static int Frame; + static bool Paused; + static bool Loaded; + static int TileAnimationEnabled; + static View Views[MAX_SCENE_VIEWS]; + static int ViewCurrent; + static int ViewsActive; + static int CurrentDrawGroup; + static int ObjectViewRenderFlag; + static int TileViewRenderFlag; + static Perf_ViewRender PERF_ViewRender[MAX_SCENE_VIEWS]; + static char NextScene[256]; + static char CurrentScene[256]; + static bool DoRestart; + static bool NoPersistency; + static int TimeEnabled; + static int TimeCounter; + static int Minutes; + static int Seconds; + static int Milliseconds; + static int Filter; + static int CurrentSceneInList; + static char CurrentFolder[256]; + static char CurrentID[256]; + static char CurrentResourceFolder[256]; + static char CurrentCategory[256]; + static int ActiveCategory; + static int DebugMode; + static float CollisionTolerance; + static bool UseCollisionOffset; + static float CollisionMaskAir; + static CollisionBox CollisionOuter; + static CollisionBox CollisionInner; + static Entity* CollisionEntity; + static CollisionSensor Sensors[6]; + static float CollisionMinimumDistance; + static float LowCollisionTolerance; + static float HighCollisionTolerance; + static int FloorAngleTolerance; + static int WallAngleTolerance; + static int RoofAngleTolerance; + static bool ShowHitboxes; + static int DebugHitboxCount; + static DebugHitboxInfo DebugHitboxList[DEBUG_HITBOX_COUNT]; + + static void Add(Entity** first, Entity** last, int* count, Entity* obj); + static void Remove(Entity** first, Entity** last, int* count, Entity* obj); + static void AddToScene(Entity* obj); + static void RemoveFromScene(Entity* obj); + static void Clear(Entity** first, Entity** last, int* count); + static void AddStatic(ObjectList* objectList, Entity* obj); + static void AddDynamic(ObjectList* objectList, Entity* obj); + static void DeleteRemoved(Entity* obj); + static void OnEvent(Uint32 event); + static void SetCurrent(const char* categoryName, const char* sceneName); + static void SetInfoFromCurrentID(); + static void Init(); + static void InitObjectListsAndRegistries(); + static void ResetPerf(); + static void Update(); + static Tileset* GetTileset(int tileID); + static TileAnimator* GetTileAnimator(int tileID); + static void SetViewActive(int viewIndex, bool active); + static void SetViewPriority(int viewIndex, int priority); + static void SortViews(); + static void SetView(int viewIndex); + static bool CheckPosOnScreen(float posX, float posY, float rangeX, float rangeY); + static void RenderView(int viewIndex, bool doPerf); + static void Render(); + static void AfterScene(); + static void Restart(); + static void LoadScene(const char* filename); + static void ProcessSceneTimer(); + static ObjectList* NewObjectList(const char* objectName); + static ObjectList* GetObjectList(const char* objectName, bool callListLoadFunction); + static ObjectList* GetObjectList(const char* objectName); + static ObjectList* GetStaticObjectList(const char* objectName); + static void AddManagers(); + static void FreePriorityLists(); + static void InitPriorityLists(); + static void SetPriorityPerLayer(int count); + static bool AddTileset(char* path); + static void LoadTileCollisions(const char* filename, size_t tilesetID); + static void UnloadTileCollisions(); + static bool GetResourceListSpace(vector* list, ResourceType* resource, size_t& index, bool& foundEmpty); + static bool GetResource(vector* list, ResourceType* resource, size_t& index); + static ISprite* GetSpriteResource(int index); + static void DisposeInScope(Uint32 scope); + static void Dispose(); + static void UnloadTilesets(); + static void SetTile(int layer, int x, int y, int tileID, int flip_x, int flip_y, int collA, int collB); + static int CollisionAt(int x, int y, int collisionField, int collideSide, int* angle); + static int CollisionInLine(int x, int y, int angleMode, int checkLen, int collisionField, bool compareAngle, Sensor* sensor); + static void SetupCollisionConfig(float minDistance, float lowTolerance, float highTolerance, int floorAngleTolerance, int wallAngleTolerance, int roofAngleTolerance); + static int AddDebugHitbox(int type, int dir, Entity* entity, CollisionBox* hitbox); + static bool CheckObjectCollisionTouch(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox); + static bool CheckObjectCollisionCircle(Entity* thisEntity, float thisRadius, Entity* otherEntity, float otherRadius); + static bool CheckObjectCollisionBox(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues); + static bool CheckObjectCollisionPlatform(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues); + static bool ObjectTileCollision(Entity* entity, int cLayers, int cMode, int cPlane, int xOffset, int yOffset, bool setPos); + static bool ObjectTileGrip(Entity* entity, int cLayers, int cMode, int cPlane, float xOffset, float yOffset, float tolerance); + static void ProcessObjectMovement(Entity* entity, CollisionBox* outerBox, CollisionBox* innerBox); + static void ProcessPathGrip(); + static void ProcessAirCollision_Down(); + static void ProcessAirCollision_Up(); + static void SetPathGripSensors(CollisionSensor* sensors); + static void FindFloorPosition(CollisionSensor* sensor); + static void FindLWallPosition(CollisionSensor* sensor); + static void FindRoofPosition(CollisionSensor* sensor); + static void FindRWallPosition(CollisionSensor* sensor); + static void FloorCollision(CollisionSensor* sensor); + static void LWallCollision(CollisionSensor* sensor); + static void RoofCollision(CollisionSensor* sensor); + static void RWallCollision(CollisionSensor* sensor); +}; + +#endif /* ENGINE_SCENE_H */ diff --git a/include/Engine/Scene/SceneInfo.h b/include/Engine/Scene/SceneInfo.h new file mode 100644 index 00000000..10d7c46b --- /dev/null +++ b/include/Engine/Scene/SceneInfo.h @@ -0,0 +1,46 @@ +#ifndef ENGINE_SCENE_SCENEINFO_H +#define ENGINE_SCENE_SCENEINFO_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class SceneInfo { +private: + static void FillAttributesHashMap(XMLAttributes* attr, HashMap* map); + +public: + static vector Entries; + static vector Categories; + + static void Dispose(); + static bool IsCategoryValid(int categoryID); + static bool IsEntryValid(int entryID); + static bool IsEntryValidInCategory(size_t categoryID, size_t entryID); + static int GetCategoryID(const char* categoryName); + static int GetEntryID(const char* categoryName, const char* entryName); + static int GetEntryID(const char* categoryName, size_t entryID); + static int GetEntryID(size_t categoryID, size_t entryID); + static int GetEntryPosInCategory(const char *categoryName, const char* entryName); + static int GetEntryPosInCategory(size_t categoryID, const char* entryName); + static int GetEntryIDWithinRange(size_t start, size_t end, const char* entryName); + static string GetParentPath(int entryID); + static string GetFilename(int entryID); + static string GetTileConfigFilename(int entryID); + static char* GetEntryProperty(int entryID, char* property); + static char* GetCategoryProperty(int categoryID, char* property); + static bool HasEntryProperty(int entryID, char* property); + static bool HasCategoryProperty(int categoryID, char* property); + static bool Load(XMLNode* node); +}; + +#endif /* ENGINE_SCENE_SCENEINFO_H */ diff --git a/include/Engine/Scene/SceneLayer.h b/include/Engine/Scene/SceneLayer.h new file mode 100644 index 00000000..d4a2accd --- /dev/null +++ b/include/Engine/Scene/SceneLayer.h @@ -0,0 +1,76 @@ +#ifndef ENGINE_SCENE_SCENELAYER_H +#define ENGINE_SCENE_SCENELAYER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class SceneLayer { +public: + char Name[50]; + bool Visible = true; + int Width = 0; + int Height = 0; + Uint32 WidthMask = 0; + Uint32 HeightMask = 0; + Uint32 WidthInBits = 0; + Uint32 HeightInBits = 0; + Uint32 WidthData = 0; + Uint32 HeightData = 0; + Uint32 DataSize = 0; + Uint32 ScrollIndexCount = 0; + int RelativeY = 0x0100; + int ConstantY = 0x0000; + int OffsetX = 0x0000; + int OffsetY = 0x0000; + Uint32* Tiles = NULL; + Uint32* TilesBackup = NULL; + Uint16* TileOffsetY = NULL; + int DeformOffsetA = 0; + int DeformOffsetB = 0; + int DeformSetA[MAX_DEFORM_LINES]; + int DeformSetB[MAX_DEFORM_LINES]; + int DeformSplitLine = 0; + int Flags = 0x0000; + int DrawGroup = 0; + Uint8 DrawBehavior = 0; + HashMap* Properties = NULL; + bool Blending = false; + Uint8 BlendMode = 0; // BlendMode_NORMAL + float Opacity = 1.0f; + bool UsePaletteIndexLines = false; + bool UsingCustomScanlineFunction = false; + ObjFunction CustomScanlineFunction; + bool UsingCustomRenderFunction = false; + ObjFunction CustomRenderFunction; + int ScrollInfoCount = 0; + ScrollingInfo* ScrollInfos = NULL; + int ScrollInfosSplitIndexesCount = 0; + Uint16* ScrollInfosSplitIndexes = NULL; + Uint8* ScrollIndexes = NULL; + Uint32 BufferID = 0; + int VertexCount = 0; + void* TileBatches = NULL; + enum { + FLAGS_COLLIDEABLE = 1, + FLAGS_REPEAT_X = 2, + FLAGS_REPEAT_Y = 4, + }; + + SceneLayer(); + SceneLayer(int w, int h); + bool PropertyExists(char* property); + VMValue PropertyGet(char* property); + void Dispose(); +}; + +#endif /* ENGINE_SCENE_SCENELAYER_H */ diff --git a/include/Engine/Scene/ScrollingIndex.h b/include/Engine/Scene/ScrollingIndex.h new file mode 100644 index 00000000..4f1d22c3 --- /dev/null +++ b/include/Engine/Scene/ScrollingIndex.h @@ -0,0 +1,21 @@ +#ifndef ENGINE_SCENE_SCROLLINGINDEX_H +#define ENGINE_SCENE_SCROLLINGINDEX_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class ScrollingIndex { +public: + int Index; + int Size; + int* TileBuffers = NULL; + +}; + +#endif /* ENGINE_SCENE_SCROLLINGINDEX_H */ diff --git a/include/Engine/Scene/ScrollingInfo.h b/include/Engine/Scene/ScrollingInfo.h new file mode 100644 index 00000000..cfa118a9 --- /dev/null +++ b/include/Engine/Scene/ScrollingInfo.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_SCENE_SCROLLINGINFO_H +#define ENGINE_SCENE_SCROLLINGINFO_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class ScrollingInfo { +public: + int RelativeParallax; + int ConstantParallax; + char CanDeform; + int Position; + int Offset; + +}; + +#endif /* ENGINE_SCENE_SCROLLINGINFO_H */ diff --git a/include/Engine/Scene/TileConfig.h b/include/Engine/Scene/TileConfig.h new file mode 100644 index 00000000..c4b4f35e --- /dev/null +++ b/include/Engine/Scene/TileConfig.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_SCENE_TILECONFIG_H +#define ENGINE_SCENE_TILECONFIG_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class TileConfig { +public: + Uint8 CollisionTop[16]; + Uint8 CollisionLeft[16]; + Uint8 CollisionRight[16]; + Uint8 CollisionBottom[16]; + Uint8 AngleTop; + Uint8 AngleLeft; + Uint8 AngleRight; + Uint8 AngleBottom; + Uint8 Behavior; + Uint8 IsCeiling; + +}; + +#endif /* ENGINE_SCENE_TILECONFIG_H */ diff --git a/include/Engine/Scene/TileSpriteInfo.h b/include/Engine/Scene/TileSpriteInfo.h new file mode 100644 index 00000000..a72212fb --- /dev/null +++ b/include/Engine/Scene/TileSpriteInfo.h @@ -0,0 +1,22 @@ +#ifndef ENGINE_SCENE_TILESPRITEINFO_H +#define ENGINE_SCENE_TILESPRITEINFO_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + + +class TileSpriteInfo { +public: + ISprite* Sprite; + int AnimationIndex; + int FrameIndex; + size_t TilesetID; + +}; + +#endif /* ENGINE_SCENE_TILESPRITEINFO_H */ diff --git a/include/Engine/Scene/View.h b/include/Engine/Scene/View.h new file mode 100644 index 00000000..0572b123 --- /dev/null +++ b/include/Engine/Scene/View.h @@ -0,0 +1,54 @@ +#ifndef ENGINE_SCENE_VIEW_H +#define ENGINE_SCENE_VIEW_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class View { +public: + bool Active = false; + bool Visible = true; + bool Software = false; + int Priority = 0; + float X = 0.0f; + float Y = 0.0f; + float Z = 0.0f; + float RotateX = 0.0f; + float RotateY = 0.0f; + float RotateZ = 0.0f; + float Width = 1.0f; + float Height = 1.0f; + float OutputX = 0.0f; + float OutputY = 0.0f; + float OutputWidth = 1.0f; + float OutputHeight = 1.0f; + int Stride = 1; + float FOV = 45.0f; + float NearPlane = 0.1f; + float FarPlane = 1000.f; + bool UsePerspective = false; + bool UseDrawTarget = false; + bool UseStencil = false; + Texture* DrawTarget = NULL; + Uint8* StencilBuffer = NULL; + size_t StencilBufferSize = 0; + Matrix4x4* ProjectionMatrix = NULL; + Matrix4x4* BaseProjectionMatrix = NULL; + + void SetSize(float w, float h); + void SetStencilEnabled(bool enabled); + void ReallocStencil(); + void ClearStencil(); + void DeleteStencil(); +}; + +#endif /* ENGINE_SCENE_VIEW_H */ diff --git a/include/Engine/TextFormats/INI/INI.h b/include/Engine/TextFormats/INI/INI.h new file mode 100644 index 00000000..b542a9d1 --- /dev/null +++ b/include/Engine/TextFormats/INI/INI.h @@ -0,0 +1,50 @@ +#ifndef ENGINE_TEXTFORMATS_INI_INI_H +#define ENGINE_TEXTFORMATS_INI_INI_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include + +class INI { +public: + char* Filename = nullptr; + vector Sections; + + static INI* New(const char* filename); + static INI* Load(const char* filename); + bool Reload(); + bool Save(const char* filename); + bool Save(); + void SetFilename(const char* filename); + bool Read(Stream* stream); + bool Write(Stream* stream); + INISection* FindSection(const char* name); + bool GetString(const char* sectionName, const char* key, char* dest, size_t destSize); + bool GetInteger(const char* sectionName, const char* key, int* dest); + bool GetDecimal(const char* sectionName, const char* key, double* dest); + bool GetBool(const char* sectionName, const char* key, bool* dest); + bool SetString(const char* sectionName, const char* key, const char* value); + bool SetInteger(const char* section, const char* key, int value); + bool SetDecimal(const char* section, const char* key, double value); + bool SetBool(const char* section, const char* key, bool value); + INISection* AddSection(const char* name); + bool RemoveSection(const char* sectionName); + bool SectionExists(const char* sectionName); + int GetSectionCount(); + char* GetProperty(const char* sectionName, const char* key); + bool PropertyExists(const char* sectionName, const char* key); + bool RemoveProperty(const char* sectionName, const char* key); + int GetPropertyCount(const char* sectionName); + void Dispose(); +}; + +#endif /* ENGINE_TEXTFORMATS_INI_INI_H */ diff --git a/include/Engine/TextFormats/XML/XMLParser.h b/include/Engine/TextFormats/XML/XMLParser.h new file mode 100644 index 00000000..cdfe3ea4 --- /dev/null +++ b/include/Engine/TextFormats/XML/XMLParser.h @@ -0,0 +1,33 @@ +#ifndef ENGINE_TEXTFORMATS_XML_XMLPARSER_H +#define ENGINE_TEXTFORMATS_XML_XMLPARSER_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include +#include +#include +#include + +class XMLParser { +public: + static bool MatchToken(Token tok, const char* string); + static float TokenToNumber(Token tok); + static XMLNode* Parse(); + static XMLNode* ParseFromStream(MemoryStream* stream); + static XMLNode* ParseFromStream(Stream* streamSrc); + static XMLNode* ParseFromResource(const char* filename); + static char* TokenToString(Token tok); + static void CopyTokenToString(Token tok, char* buffer, size_t size); + static XMLNode* SearchNode(XMLNode* root, const char* search); + static void Free(XMLNode* root); +}; + +#endif /* ENGINE_TEXTFORMATS_XML_XMLPARSER_H */ diff --git a/include/Engine/Types/DrawGroupList.h b/include/Engine/Types/DrawGroupList.h new file mode 100644 index 00000000..7966b651 --- /dev/null +++ b/include/Engine/Types/DrawGroupList.h @@ -0,0 +1,34 @@ +#ifndef ENGINE_TYPES_DRAWGROUPLIST_H +#define ENGINE_TYPES_DRAWGROUPLIST_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class DrawGroupList { +public: + vector* Entities = nullptr; + bool EntityDepthSortingEnabled = false; + bool NeedsSorting = false; + + DrawGroupList(); + int Add(Entity* obj); + bool Contains(Entity* obj); + int GetEntityIndex(Entity* obj); + void Remove(Entity* obj); + void Clear(); + void Sort(); + void Init(); + void Dispose(); + ~DrawGroupList(); + int Count(); +}; + +#endif /* ENGINE_TYPES_DRAWGROUPLIST_H */ diff --git a/include/Engine/Types/Entity.h b/include/Engine/Types/Entity.h new file mode 100644 index 00000000..d496a9ac --- /dev/null +++ b/include/Engine/Types/Entity.h @@ -0,0 +1,137 @@ +#ifndef ENGINE_TYPES_ENTITY_H +#define ENGINE_TYPES_ENTITY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + +class ObjectList; +class ObjectRegistry; +class DrawGroupList; + +#include +#include +#include +#include +#include +#include +#include + +class Entity { +public: + float InitialX = 0; + float InitialY = 0; + int Active = true; + int Pauseable = true; + int Interactable = true; + int Persistence = Persistence_NONE; + int Activity = ACTIVE_BOUNDS; + int InRange = false; + bool Created = false; + bool PostCreated = false; + float X = 0.0f; + float Y = 0.0f; + float Z = 0.0f; + float XSpeed = 0.0f; + float YSpeed = 0.0f; + float GroundSpeed = 0.0f; + float Gravity = 0.0f; + int Ground = false; + int WasOffScreen = false; + int OnScreen = true; + float OnScreenHitboxW = 0.0f; + float OnScreenHitboxH = 0.0f; + float OnScreenRegionTop = 0.0f; + float OnScreenRegionLeft = 0.0f; + float OnScreenRegionRight = 0.0f; + float OnScreenRegionBottom = 0.0f; + int ViewRenderFlag = 0xFFFFFFFF; + int ViewOverrideFlag = 0; + float RenderRegionW = 0.0f; + float RenderRegionH = 0.0f; + float RenderRegionTop = 0.0f; + float RenderRegionLeft = 0.0f; + float RenderRegionRight = 0.0f; + float RenderRegionBottom = 0.0f; + int Angle = 0; + int AngleMode = 0; + float ScaleX = 1.0; + float ScaleY = 1.0; + float Rotation = 0.0; + float Alpha = 1.0; + int AutoPhysics = false; + int Priority = 0; + int PriorityListIndex = -1; + int PriorityOld = -1; + float Depth = 0.0f; + float OldDepth = 0.0f; + float ZDepth = 0.0; + int Sprite = -1; + int CurrentAnimation = -1; + int CurrentFrame = -1; + int CurrentFrameCount = 0; + float AnimationSpeedMult = 1.0; + int AnimationSpeedAdd = 0; + int AutoAnimate = true; + float AnimationSpeed = 0.0; + float AnimationTimer = 0.0; + int AnimationFrameDuration = 0; + int AnimationLoopIndex = 0; + EntityHitbox Hitbox; + int FlipFlag = 0; + float SensorX = 0.0f; + float SensorY = 0.0f; + int SensorCollided = false; + int SensorAngle = 0; + float VelocityX = 0.0f; + float VelocityY = 0.0f; + float GroundVel = 0.0f; + float GravityStrength = 0.0f; + int OnGround = false; + int Direction = 0; + int TileCollisions = false; + int CollisionLayers = 0; + int CollisionPlane = 0; + int CollisionMode = 0; + int SlotID = -1; + bool Removed = false; + Entity* PrevEntity = NULL; + Entity* NextEntity = NULL; + ObjectList* List = NULL; + Entity* PrevEntityInList = NULL; + Entity* NextEntityInList = NULL; + Entity* PrevSceneEntity = NULL; + Entity* NextSceneEntity = NULL; + + void ApplyMotion(); + void Animate(); + void SetAnimation(int animation, int frame); + void ResetAnimation(int animation, int frame); + bool BasicCollideWithObject(Entity* other); + bool CollideWithObject(Entity* other); + int SolidCollideWithObject(Entity* other, int flag); + bool TopSolidCollideWithObject(Entity* other, int flag); + void Copy(Entity* other); + void CopyFields(Entity* other); + void ApplyPhysics(); + virtual void Initialize(); + virtual void Create(); + virtual void PostCreate(); + virtual void UpdateEarly(); + virtual void Update(); + virtual void UpdateLate(); + virtual void OnAnimationFinish(); + virtual void OnSceneLoad(); + virtual void OnSceneRestart(); + virtual void GameStart(); + virtual void RenderEarly(); + virtual void Render(int CamX, int CamY); + virtual void RenderLate(); + virtual void Remove(); + virtual void Dispose(); +}; + +#endif /* ENGINE_TYPES_ENTITY_H */ diff --git a/include/Engine/Types/ObjectList.h b/include/Engine/Types/ObjectList.h new file mode 100644 index 00000000..e0b49d65 --- /dev/null +++ b/include/Engine/Types/ObjectList.h @@ -0,0 +1,43 @@ +#ifndef ENGINE_TYPES_OBJECTLIST_H +#define ENGINE_TYPES_OBJECTLIST_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ObjectList { +public: + int EntityCount = 0; + int Activity = ACTIVE_NORMAL; + Entity* EntityFirst = nullptr; + Entity* EntityLast = nullptr; + char* ObjectName; + char* LoadFunctionName; + char* GlobalUpdateFunctionName; + ObjectListPerformance Performance; + Entity* (*SpawnFunction)(ObjectList*) = nullptr; + + ObjectList(const char* name); + ~ObjectList(); + void Add(Entity* obj); + bool Contains(Entity* obj); + void Remove(Entity* obj); + void Clear(); + Entity* Spawn(); + void Iterate(std::function func); + void RemoveNonPersistentFromLinkedList(Entity* first, int persistence); + void RemoveNonPersistentFromLinkedList(Entity* first); + void ResetPerf(); + Entity* GetNth(int n); + Entity* GetClosest(int x, int y); + int Count(); +}; + +#endif /* ENGINE_TYPES_OBJECTLIST_H */ diff --git a/include/Engine/Types/ObjectRegistry.h b/include/Engine/Types/ObjectRegistry.h new file mode 100644 index 00000000..0264c7f6 --- /dev/null +++ b/include/Engine/Types/ObjectRegistry.h @@ -0,0 +1,33 @@ +#ifndef ENGINE_TYPES_OBJECTREGISTRY_H +#define ENGINE_TYPES_OBJECTREGISTRY_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class ObjectRegistry { +public: + vector List; + + void Add(Entity* obj); + bool Contains(Entity* obj); + void Remove(Entity* obj); + void Clear(); + void Iterate(std::function func); + void RemoveNonPersistentFromLinkedList(Entity* first, int persistence); + void RemoveNonPersistentFromLinkedList(Entity* first); + Entity* GetNth(int n); + Entity* GetClosest(int x, int y); + void Dispose(); + ~ObjectRegistry(); + int Count(); +}; + +#endif /* ENGINE_TYPES_OBJECTREGISTRY_H */ diff --git a/include/Engine/Types/Tileset.h b/include/Engine/Types/Tileset.h new file mode 100644 index 00000000..2dbc5def --- /dev/null +++ b/include/Engine/Types/Tileset.h @@ -0,0 +1,38 @@ +#ifndef ENGINE_TYPES_TILESET_H +#define ENGINE_TYPES_TILESET_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include +#include + +class Tileset { +public: + ISprite* Sprite = nullptr; + char* Filename = nullptr; + int NumCols = 0; + int NumRows = 0; + int TileWidth = 0; + int TileHeight = 0; + size_t StartTile = 0; + size_t FirstGlobalTileID = 0; + size_t TileCount = 0; + unsigned PaletteID = 0; + std::map AnimatorMap; + + Tileset(ISprite* sprite, int tileWidth, int tileHeight, size_t firstgid, size_t startTile, size_t tileCount, char* filename); + void RunAnimations(); + void RestartAnimations(); + void AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, vector& tileIDs, vector& durations); + void AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, ISprite* animSprite, int animID); + TileAnimator* GetTileAnimSequence(int tileID); +}; + +#endif /* ENGINE_TYPES_TILESET_H */ diff --git a/include/Engine/Utilities/ColorUtils.h b/include/Engine/Utilities/ColorUtils.h new file mode 100644 index 00000000..751ffeec --- /dev/null +++ b/include/Engine/Utilities/ColorUtils.h @@ -0,0 +1,37 @@ +#ifndef ENGINE_UTILITIES_COLORUTILS_H +#define ENGINE_UTILITIES_COLORUTILS_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include + +class ColorUtils { +public: + static Uint32 ToRGB(int r, int g, int b); + static Uint32 ToRGB(int r, int g, int b, int a); + static Uint32 ToRGB(float r, float g, float b); + static Uint32 ToRGB(float r, float g, float b, float a); + static Uint32 ToRGB(float *r); + static Uint32 ToRGBA(float *r); + static void SeparateRGB(Uint32 color, float* dest); + static void Separate(Uint32 color, float* dest); + static void SeparateRGB(Uint32 color, Uint8* dest); + static void Separate(Uint32 color, Uint8* dest); + static void SeparateRGB(float* color, Uint8* dest); + static void Separate(float* color, Uint8* dest); + static Uint32 Tint(Uint32 color, Uint32 colorMult); + static Uint32 Tint(Uint32 color, Uint32 colorMult, Uint16 percentage); + static Uint32 Multiply(Uint32 color, Uint32 colorMult); + static Uint32 Blend(Uint32 color1, Uint32 color2, int percent); + static void ConvertFromARGBtoABGR(Uint32* argb, int count); + static void ConvertFromABGRtoARGB(Uint32* argb, int count); + static int NearestColor(Uint8 r, Uint8 g, Uint8 b, Uint32* palette, unsigned numColors); +}; + +#endif /* ENGINE_UTILITIES_COLORUTILS_H */ diff --git a/include/Engine/Utilities/StringUtils.h b/include/Engine/Utilities/StringUtils.h new file mode 100644 index 00000000..130bcc58 --- /dev/null +++ b/include/Engine/Utilities/StringUtils.h @@ -0,0 +1,38 @@ +#ifndef ENGINE_UTILITIES_STRINGUTILS_H +#define ENGINE_UTILITIES_STRINGUTILS_H + +#define PUBLIC +#define PRIVATE +#define PROTECTED +#define STATIC +#define VIRTUAL +#define EXPOSED + + +#include +#include + +class StringUtils { +public: + static char* Create(void* src, size_t length); + static char* Create(string src); + static char* Create(Token token); + static char* Duplicate(const char* src); + static char* Duplicate(const char* src, size_t length); + static char* Resize(char* src, size_t length); + static bool WildcardMatch(const char* first, const char* second); + static bool StartsWith(const char* string, const char* compare); + static char* StrCaseStr(const char* haystack, const char* needle); + static size_t Copy(char* dst, const char* src, size_t sz); + static size_t Concat(char* dst, const char* src, size_t sz); + static bool ToNumber(int* dst, const char* src); + static bool ToDecimal(double* dst, const char* src); + static bool ToNumber(int* dst, string src); + static bool ToDecimal(double* dst, string src); + static char* GetPath(const char* filename); + static char* ConcatPaths(const char* pathA, const char* pathB); + static char* ReplacePathSeparators(const char* path); + static void ReplacePathSeparatorsInPlace(char* path); +}; + +#endif /* ENGINE_UTILITIES_STRINGUTILS_H */ diff --git a/tools/makeheaders b/tools/makeheaders deleted file mode 100755 index cb6c99a4a625cd6c18b5314efd712511ef95501a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85736 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 z 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 8); - } - return crc32val; -} -uint32_t crc32_inc(char* c, uint32_t len, uint32_t crc32val) { - uint8_t* s = (uint8_t*)c; - for (uint32_t i = 0; i < len; i++) { - if (c[i] == '\r') continue; - if (!c[i]) break; - crc32val = crc32_t[(crc32val ^ s[i]) & 0xFF] ^ (crc32val >> 8); - } - return crc32val; -} - -uint32_t crc32_file(FILE* f) { - if (!f) return 0; - - char* buf; - size_t filelen; - - fseek(f, 0, SEEK_END); - filelen = ftell(f); - rewind(f); - - buf = (char*)malloc(filelen); // Enough memory for file + \0 - fread(buf, filelen, 1, f); // Read in the entire file - rewind(f); - - return crc32(buf, filelen); -} diff --git a/tools/makeheaders-src/main.cpp b/tools/makeheaders-src/main.cpp deleted file mode 100644 index 96e441a8..00000000 --- a/tools/makeheaders-src/main.cpp +++ /dev/null @@ -1,852 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if !MSVC - #include - #include - #include "crc32.h" -#else - #include - #include - #include - #include - #include - #include -#endif - -using namespace std; - -char finalpath[4096]; - -static void MakeDir(const char *dir) { - struct stat st = {0}; - if (stat(dir, &st) == -1) - mkdir(dir, 0700); -} - -static void RecursiveMakeDir(const char *path) { - char tmp[4096]; - - snprintf(tmp, sizeof(tmp), "%s", path); - size_t len = strlen(tmp); - - if (tmp[len - 1] == '/') - tmp[len - 1] = 0; - - for (char *p = tmp + 1; *p; p++) { - if (*p == '/') { - *p = '\0'; - MakeDir(tmp); - *p = '/'; - } - } - - MakeDir(tmp); -} - -struct VARIABLE { - std::string class_type; - std::string variable_name; -}; - -struct CLASSFILE { - std::vector includes; - std::string class_name; - std::string parent_class_name; - std::string file_name; - std::vector public_vars; - std::vector private_vars; - std::vector protected_vars; - std::vector public_funcs; - std::vector private_funcs; - std::vector protected_funcs; - vector classes_needed; -}; - -int class_count_alpha = 0; -bool any_class_changed = false; - -int FindChar(char* str, char c) { - char* strln = str; - do { - if (*strln == c) - return strln - str; - strln++; - } while (*strln != 0); - return -1; -} -int FindLastChar(char* str, char c) { - char* strln = str + strlen(str); - do { - if (*strln == c) - return strln - str; - strln--; - } while (strln != str); - return -1; -} - -string replaceFirstOccurrence(string& s, const string& toReplace, const string& replaceWith) { - std::size_t pos = s.find(toReplace); - if (pos == string::npos) return s; - return s.replace(pos, toReplace.length(), replaceWith); -} - -void print_class(const char* directory, CLASSFILE data) { - string class_name(data.class_name); - if (class_name == string("\x01\x01\x01\x01")) - return; - if (class_name == string("")) - return; - - FILE *fp; - char filename[4096]; - - string direc = string(directory); - string basedirec = string(finalpath); - - direc = replaceFirstOccurrence(direc, "source", "include"); - basedirec = replaceFirstOccurrence(basedirec, "source", "include"); - - - struct stat st = {0}; - - if (direc.find("include") != std::string::npos) { - if (stat(direc.substr(0, direc.find("include") + 7).c_str(), &st) == -1) { - RecursiveMakeDir(direc.substr(0, direc.find("include") + 7).c_str()); - } - } - - if (stat(direc.c_str(), &st) == -1) - RecursiveMakeDir(direc.c_str()); - - snprintf(filename, 4096, "%s%s.h", direc.c_str(), data.file_name.c_str()); - // printf("%s\n", filename); - fp = fopen(filename, "wb"); - int err = errno; - if (!fp) { - printf("Could not open %s because %s\n", filename, strerror(err)); - return; - } - - class_count_alpha++; - - class_name = (direc.c_str() + basedirec.length() + 1); - class_name += data.file_name; - std::transform(class_name.begin(), class_name.end(), class_name.begin(), [](unsigned char c) -> unsigned char { - if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) - return '_'; - return ::toupper(c); - }); - - fprintf(fp, "#ifndef %s_H\n", class_name.c_str()); - fprintf(fp, "#define %s_H\n", class_name.c_str()); - fprintf(fp, "\n"); - fprintf(fp, "#define PUBLIC\n"); - fprintf(fp, "#define PRIVATE\n"); - fprintf(fp, "#define PROTECTED\n"); - fprintf(fp, "#define STATIC\n"); - fprintf(fp, "#define VIRTUAL\n"); - fprintf(fp, "#define EXPOSED\n"); - fprintf(fp, "\n"); - for (int i = 0; i < data.classes_needed.size(); i++) { - fprintf(fp, "class %s;\n", data.classes_needed[i].c_str()); - } - fprintf(fp, "\n"); - - for (std::vector::iterator it = data.includes.begin(); it != data.includes.end(); ++it) { - fprintf(fp, "#include %s\n", (*it).c_str()); - } - fprintf(fp, "\n"); - fprintf(fp, "class %s%s%s {\n", data.class_name.c_str(), data.parent_class_name != string("") ? " : public " : "", data.parent_class_name != string("") ? data.parent_class_name.c_str() : ""); - bool damada = 0; - if (data.private_vars.size() > 0 || data.private_funcs.size() > 0) { - fprintf(fp, "private:\n"); - bool yamero = 0; - for (std::vector::iterator it = - data.private_vars.begin(); it != - data.private_vars.end(); ++it) { - fprintf(fp, " %s %s\n", (*it).class_type.c_str(), (*it).variable_name.c_str()); - yamero = 1; - } - - if (yamero) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.private_funcs.begin(); it != - data.private_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - damada = 1; - } - if (data.public_vars.size() > 0 || data.public_funcs.size() > 0) { - if (damada) - fprintf(fp, "\n"); - - fprintf(fp, "public:\n"); - bool yamero = 0; - for (std::vector::iterator it = - data.public_vars.begin(); it != - data.public_vars.end(); ++it) { - fprintf(fp, " %s %s\n", (*it).class_type.c_str(), (*it).variable_name.c_str()); - yamero = 1; - } - - if (yamero) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.public_funcs.begin(); it != - data.public_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - } - if (data.protected_vars.size() > 0 || data.protected_funcs.size() > 0) { - if (damada) - fprintf(fp, "\n"); - - fprintf(fp, "protected:\n"); - bool yamero = 0; - for (std::vector::iterator it = - data.protected_vars.begin(); it != - data.protected_vars.end(); ++it) { - fprintf(fp, " %s %s\n", (*it).class_type.c_str(), (*it).variable_name.c_str()); - yamero = 1; - } - - if (yamero) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.protected_funcs.begin(); it != - data.protected_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - } - fprintf(fp, "};\n"); - - fprintf(fp, "\n"); - fprintf(fp, "#endif /* %s_H */\n", class_name.c_str()); - - fclose(fp); -} - -vector ClassNames; -string find_classname(char* filename) { - FILE *fp; - fp = fopen(filename, "rb"); - if (!fp) { - printf("Could not load file (find_classname): %s!\n", filename); - exit(EXIT_FAILURE); - } - - bool in_interface = false; - bool in_interfaced = false; - int in_variables = 0; - - // printf("find: %s\n", filename); - - while (true) { - char first_token[255]; - if (fscanf(fp, "%s", first_token) <= 0) { - break; - } - - if (!strcmp(first_token, "#if")) { - char rest_of_line[255]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - if (!strncmp(rest_of_line, "INTERFACE", 9)) { - in_interface = true; - in_interfaced = true; - } - } - else { - if (!in_interfaced) { - fclose(fp); - return string(""); - } - } - if (!strcmp(first_token, "#endif")) { - char rest_of_line[255]; - fgets(rest_of_line, 255, fp); - if (in_interface) { - in_interface = false; - in_variables = 0; - } - } - else if (!strcmp(first_token, "class")) { - char rest_of_line[255]; - fscanf(fp, "%s", rest_of_line); - fclose(fp); - - return string(rest_of_line); - } - } - return string(""); -} - -CLASSFILE load_class(char* filename) { - FILE *fp; - CLASSFILE test; - fp = fopen(filename, "rb"); - if (!fp) { - printf("Could not load file (load_class): %s!\n", filename); - exit(EXIT_FAILURE); - } - //printf("Loading file: %s\n", filename); - - bool in_interface = false; - bool in_interfaced = false; - int in_variables = 0; - - char ObjectName[256]; - int found = FindLastChar(filename, '/'); - memset(ObjectName, 0, 256); - strcpy(ObjectName, filename + found + 1); - int nextfind = FindChar(ObjectName, '.'); - memset(ObjectName + nextfind, 0, 256 - nextfind); - - test.file_name = string(ObjectName); - - int brackscope = 0; - - while (true) { - char first_token[255]; - if (fscanf(fp, "%s", first_token) <= 0) - break; - - if (!strcmp(first_token, "#if")) { - char rest_of_line[255]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - if (!strncmp(rest_of_line, "INTERFACE", 9)) { - in_interface = true; - in_interfaced = true; - } - } - else { - if (!in_interfaced) { - test.class_name = string("\x01\x01\x01\x01"); - break; - } - } - if (!strcmp(first_token, "#endif")) { - char rest_of_line[255]; - fgets(rest_of_line, 255, fp); - if (in_interface) { - in_interface = false; - in_variables = 0; - } - } - else if (!strcmp(first_token, "#include")) { - char rest_of_line[255]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - if (in_interface) - test.includes.push_back(rest_of_line); - } - else if (!strcmp(first_token, "need_t")) { - char rest_of_line[255]; - fscanf(fp, " "); - fscanf(fp, "%[^;]", rest_of_line); - - test.classes_needed.push_back(string(rest_of_line)); - } - else if (!strcmp(first_token, "class")) { - if (test.class_name.empty()) { - char rest_of_line[255]; - fscanf(fp, "%s", rest_of_line); - - test.class_name = std::string(rest_of_line); - - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - char enws[255]; - if (sscanf(rest_of_line, " : public %s", enws) > 0) { - test.parent_class_name = std::string(enws); - } - - in_variables = 1; - } - } - else if (!strcmp(first_token, "{") || !strcmp(first_token, "}") || !strcmp(first_token, "};")) { - if (!strcmp(first_token, "};")) { - if (brackscope > 0) { - char rest_of_line[255]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - if (in_interface) { - if (in_variables == 1) - test.private_vars.push_back(VARIABLE { string(first_token), string() }); - else if (in_variables == 2) - test.public_vars.push_back(VARIABLE { string(first_token), string() }); - else if (in_variables == 3) - test.protected_vars.push_back(VARIABLE { string(first_token), string() }); - } - brackscope--; - } - else { - in_variables = 0; - continue; - } - } - } - else if (!strcmp(first_token, "private:")) { - in_variables = 1; - } - else if (!strcmp(first_token, "public:")) { - in_variables = 2; - } - else if (!strcmp(first_token, "protected:")) { - in_variables = 3; - } - else if (in_variables) { - char nom[255]; - sscanf(first_token, "%[A-Za-z0-9_]", nom); - - if (!strcmp(nom, "struct") || !strcmp(nom, "enum")) - brackscope++; - - char rest_of_line[255]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 255, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - for (int i = 0; i < ClassNames.size(); i++) { - if (string(nom) == ClassNames[i]) { - test.classes_needed.push_back(string(nom)); - break; - } - } - - if (in_interface) { - if (in_variables == 1) - test.private_vars.push_back(VARIABLE { string(first_token), string(rest_of_line) }); - else if (in_variables == 2) - test.public_vars.push_back(VARIABLE { string(first_token), string(rest_of_line) }); - else if (in_variables == 3) - test.protected_vars.push_back(VARIABLE { string(first_token), string(rest_of_line) }); - } - } - else if ((!strcmp(first_token, "PUBLIC") || !strcmp(first_token, "PRIVATE") || !strcmp(first_token, "PROTECTED")) && !in_interface) { - char* rest_of_line = (char*)malloc(512); - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 512, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - bool statik = false; - bool virtua = false; - if (!strncmp(rest_of_line, "STATIC", 6)) { - statik = true; - char temp[512]; - sprintf(temp, "%s", rest_of_line + 7); - strcpy(rest_of_line, temp); - } - if (!strncmp(rest_of_line, "VIRTUAL", 7)) { - virtua = true; - char temp[512]; - sprintf(temp, "%s", rest_of_line + 8); - strcpy(rest_of_line, temp); - } - - if (FindChar(rest_of_line, ':') < 0) { - printf("\x1b[1;32mFatal Error: \x1b[0mCould not find class name for line '%s'.\n", rest_of_line); - exit(1); - } - - char* wherefunc = strstr(rest_of_line, (test.class_name + "::").c_str()); - if (!wherefunc) { - printf("\x1b[1;32mFatal Error: \x1b[0mIncorrect class name `%.*s` (should be `%s`.)\n", FindChar(rest_of_line, ':'), rest_of_line, test.class_name.c_str()); - exit(1); - } - char* function_name = wherefunc + test.class_name.size() + 2; - int ind = strlen(function_name) - 2; - char* couldbe = strstr(function_name, ": "); - if (couldbe != NULL) { - ind = couldbe - function_name - 1; - } - if (function_name[ind] != ' ') - ind++; - function_name[ind] = ';'; - function_name[ind + 1] = 0; - - char type[500]; - if (wherefunc - rest_of_line > 0) { - sprintf(type, "%s", rest_of_line); - //printf("%s\n", type); - type[wherefunc - rest_of_line] = 0; - } - else { - sprintf(type, "%s", ""); - } - - char finalfunname[500]; - if (statik) - sprintf(finalfunname, "%s%s%s", "static ", type, function_name); - else if (virtua) - sprintf(finalfunname, "%s%s%s", "virtual ", type, function_name); - else - sprintf(finalfunname, "%s%s", type, function_name); - - if (!strcmp(first_token, "PRIVATE")) - test.private_funcs.push_back(string(finalfunname)); - else if (!strcmp(first_token, "PUBLIC")) - test.public_funcs.push_back(string(finalfunname)); - else if (!strcmp(first_token, "PROTECTED")) - test.protected_funcs.push_back(string(finalfunname)); - - free(rest_of_line); - } - else if (!strcmp(first_token, "//") && !in_interface) { - char rest_of_line[512]; - fscanf(fp, "%c", rest_of_line); // clears space - fgets(rest_of_line, 512, fp); - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - } - } - - fclose(fp); - return test; -} - -bool prelistdir(const char *name, int indent) { - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir(name))) - return false; - - while ((entry = readdir(dir)) != NULL) { - if (entry->d_type == DT_DIR) { - char path[4096]; - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); - prelistdir(path, indent + 2); - } - else if (indent == 0) { - continue; - } - else if (strstr(entry->d_name, ".cpp")) { - char path[4096]; - snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); - - char newname[1024]; - snprintf(newname, sizeof(newname), "%s", name); - size_t sz = strlen(name); - if (newname[sz - 1] != '/') { - newname[sz] = '/'; - newname[sz + 1] = 0; - } - - string str = find_classname(path); - if (str != "") { - ClassNames.push_back(str); - } - } - } - closedir(dir); - return true; -} - -struct ClassHash { - uint32_t FilenameHash; - uint32_t InterfaceChecksum; -}; -vector ClassHashes; -int GetClassHash(uint32_t filenameHash) { - for (int i = 0; i < ClassHashes.size(); i++) { - if (ClassHashes[i].FilenameHash == filenameHash) - return i; - } - return -1; -} -int PutClassHash(uint32_t filenameHash, uint32_t checkSum) { - int idx = GetClassHash(filenameHash); - if (idx >= 0) { - ClassHashes[idx].FilenameHash = filenameHash; - ClassHashes[idx].InterfaceChecksum = checkSum; - return 0; - } - - ClassHash ch; - ch.FilenameHash = filenameHash; - ch.InterfaceChecksum = checkSum; - ClassHashes.push_back(ch); - return 1; -} -void LoadClassHashTable() { - #if MSVC - FILE* f = fopen("../makeheaders.bin", "rb"); - #else - FILE* f = fopen("makeheaders.bin", "rb"); - #endif - if (f) { - for (;;) { - ClassHash ch; - if (fread(&ch, sizeof(ClassHash), 1, f) <= 0) - break; - - ClassHashes.push_back(ch); - } - fclose(f); - } -} -void SaveClassHashTable() { - #if MSVC - FILE* f = fopen("../makeheaders.bin", "wb"); - #else - FILE* f = fopen("makeheaders.bin", "wb"); - #endif - if (f) { - for (int i = 0; i < ClassHashes.size(); i++) { - fwrite(&ClassHashes[i], sizeof(ClassHash), 1, f); - } - fclose(f); - } -} - -// Printing -enum class PrintColor { - Default = 0, - Red, - Yellow, - Green, - Purple, -}; -void PrintHeader(FILE* f, const char* str, PrintColor col) { - int color = 0; - #if MSVC - switch (col) { - case PrintColor::Red: color = 4; break; - case PrintColor::Yellow: color = 14; break; - case PrintColor::Green: color = 2; break; - case PrintColor::Purple: color = 5; break; - default: color = 0xF; break; - } - CONSOLE_SCREEN_BUFFER_INFO csbi; - HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) { - SetConsoleTextAttribute(hStdOut, (csbi.wAttributes & 0xF0) | color); - } - fprintf(f, str); - SetConsoleTextAttribute(hStdOut, csbi.wAttributes); - #else - switch (col) { - case PrintColor::Red: color = 91; break; - case PrintColor::Yellow: color = 93; break; - case PrintColor::Green: color = 92; break; - case PrintColor::Purple: color = 95; break; - default: color = 37; break; - } - fprintf(f, "\x1b[1;%dm%s\x1b[0m", color, str); - #endif -} - -bool MakeHeaderCheck(char* filename) { - if (FindChar(filename, '.') < 0) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Could not find '.' in '%s'!\n", filename); - exit(EXIT_FAILURE); - return false; - } - - bool didChange = false; - - FILE* f = fopen(filename, "rb"); - if (!f) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Could not open file '%s'!\n", filename); - exit(EXIT_FAILURE); - } - - int interfaceStart = -1; - int interfaceEnd = -1; - - int found, nextfind; - char* HeaderName = (char*)calloc(1, 256); - - found = FindLastChar(filename, '/'); - nextfind = FindChar(filename + found + 1, '.'); - strncpy(HeaderName, filename + found + 1, nextfind); - memset(HeaderName + nextfind, 0, 256 - nextfind); - - int ifScope = 0; - while (true) { - int64_t tokenStart = ftell(f); - - char first_token[255]; - if (fscanf(f, "%s", first_token) <= 0) { - // printf("reached EOF\n"); - break; - } - - if (!strcmp(first_token, "#if")) { - fscanf(f, " "); - char rest_of_line[255]; - fgets(rest_of_line, 255, f); - rest_of_line[strcspn(rest_of_line, "\n")] = 0; - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; - - if (!strncmp(rest_of_line, "INTERFACE", 9)) { - interfaceStart = ftell(f); - } - - ifScope++; - } - else if (!strcmp(first_token, "#endif")) { - ifScope--; - if (ifScope == 0) { - interfaceEnd = tokenStart; - break; - } - } - } - - // get function descriptors - // rewind(f); - uint32_t FDChecksum = 0x00000000; - while (true) { - char rest_of_line[1024]; - if (!fgets(rest_of_line, 1024, f)) { - break; - } - - if ((!strncmp(rest_of_line, "PUBLIC", 6) || !strncmp(rest_of_line, "PRIVATE", 7) || !strncmp(rest_of_line, "PROTECTED", 9))) { - rest_of_line[strcspn(rest_of_line, "\r\n")] = 0; rest_of_line[strcspn(rest_of_line, "\n")] = 0; - - FDChecksum = crc32_inc(rest_of_line, strlen(rest_of_line), FDChecksum); - } - } - - if (interfaceStart == -1) { - return false; - } - if (interfaceStart != -1 && interfaceEnd == -1) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Missing matching #endif in file '%s'!\n", filename); - exit(EXIT_FAILURE); - return false; - } - - char* interfaceField = (char*)calloc(1, interfaceEnd - interfaceStart + 1); - fseek(f, interfaceStart, SEEK_SET); - fread(interfaceField, interfaceEnd - interfaceStart, 1, f); - - uint32_t Namehash = crc32(filename, strlen(filename)); - - uint32_t Checksum = 0x00000000; - uint32_t ComparisonHash = 0x00000000; - - int idx = -1; - if ((idx = GetClassHash(Namehash)) != -1) - ComparisonHash = ClassHashes[idx].InterfaceChecksum; - - Checksum = crc32_inc(interfaceField, interfaceEnd - interfaceStart, FDChecksum); - didChange = Checksum != ComparisonHash; - - if (!didChange) { - SaveClassHashTable(); - return didChange; - } - - PutClassHash(Namehash, Checksum); - - return didChange; -} -bool ListClassDir(const char* name, const char* parent, int indent) { - DIR* dir; - struct dirent* entry; - - if (!(dir = opendir(name))) - return false; - - char path[4096]; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - sprintf(path, "%s/%s", name, entry->d_name); - - if (entry->d_type == DT_DIR) { - ListClassDir(path, parent, indent + 2); - } - else if (strstr(entry->d_name, ".cpp")) { - if (MakeHeaderCheck(path)) { - char parentFolder[4096]; - snprintf(parentFolder, sizeof(parentFolder), "%s", name); - size_t sz = strlen(name); - if (parentFolder[sz - 1] != '/') { - parentFolder[sz] = '/'; - parentFolder[sz + 1] = 0; - } - - // printf("path: %s parentFolder: %s\n", path, parentFolder); - - print_class(parentFolder, load_class(path)); - } - } - } - closedir(dir); - return true; -} - -int main(int argc, char **argv) { - if (argc <= 1) { - printf("No source code path!\n"); - printf("Usage:\n"); - printf(" %s [options] path\n", argv[0]); - return 0; - } - - printf("\n"); - // printf("Desired Directory: '%s' (%s)\n", argv[1], argv[1][0] == '/' ? "ABSOLUTE" : "RELATIVE"); - - if (argv[1][0] == '/') { - sprintf(finalpath, "%s%s", argv[1], ""); - } - else { - char cwd[4096]; - getcwd(cwd, sizeof(cwd)); - sprintf(finalpath, "%s/%s%s", cwd, argv[1], ""); - } - #if MSVC - _fullpath(finalpath, argv[1], 4096); - #else - realpath(argv[1], finalpath); - #endif - // printf("Final Directory: '%s'\n", finalpath); - - clock_t start, stop; - start = clock(); - - LoadClassHashTable(); - if (prelistdir(finalpath, 0)) { - ListClassDir(finalpath, finalpath, 0); - } - SaveClassHashTable(); - - stop = clock(); - PrintHeader(stdout, "makeheaders: ", PrintColor::Green); - printf("Generated %d header(s) in %.3f milliseconds.\n\n", class_count_alpha, (stop - start) * 1000.f / CLOCKS_PER_SEC); - - return 0; -} diff --git a/tools/makeheaders.exe b/tools/makeheaders.exe deleted file mode 100644 index 596d2a6d6f4182685d72eadadad744ce7893f8a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2215483 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

7>qitTtk~mneroABT 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 z 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

TR;> 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

  • 4B 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�+R*Pu8oPn6v4G?VupfHK{E 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 z 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

    v(W=_B6Cd}KtY7gHnLghQ-J+ot%$pf zUlzL8_{{kt9CO%2@0cN;GNcs3A(Q{pr(EK2&#)ovAs}i~Z`nS;606rCZmU91vV+%cN z?B$04YIMh0^5PiFs!>QKEkw&}a?$A;1aAZAk3yF#1|T^zLCQkE1F$n$pSJ98`Id#`zSzPi8M|3% znUPIGX9IM%vnnD~*VK$J2KmK4pL`F- zbfY-EH=I|k9#y*u{aXPXxeau$BlVF*J!BO|N=bhp6KSl+qQ1IFZpY;&9VM|J08Fq# z4T#kf!1ozj5h-8HFV4MRX>zrpkD{wW(Ud}I*-r2}RV~a1uaJJ)GA#?KwD=YbAgfXB z&)FW`pOM+ejJF6K3~(*L+zN4w<0~Tp#Sr=!V3!Lb^!-ryLV6t8`1y0mRc&pB%JNm! zt~WPZh2$z>;pWvMROQsn(duKPv8oa?_ve1J=6-O|ko(b^`vE`qqqVw1)py#>W~0#M zK(|W-<=}csHUQijR}C(w)F*@w0O&PSLC()CXjW&MpRHpf~c&U zECY4dm3RV)fPqsZ}eA~d>SBgnUpO^`Ea)*g`D*sUE*pP?au+K zt-Xd`V7RQIxE@q=^GKd?;7LaNNvhDbT=CB3t8G?^6ns4Kdh>#07Z^w1ln zuyI|`8xsBpT3)meoriffTv)wvG#LNiXqBFOT8PDI1(K-WX@#r=QLIK2zk9>S$lABy zG#2zRxVr&5sgQ2-Fk7Ee5%F%SmkOJy#i4gD!=y`BomKcl0L?7)1%Q?9;))2_VXuxa zD|a)Zx31iW<;p^Osh-JKXdM}2IO`q^M$2q}(wJ8h;mIbRi4;uWKqt`Py{rqkD>JU8 zrYrp2(AdkF5?bzZK3Z5n?FpR;P^8rr5tlf=Q0izntzi6Z7`nu4&Jfb0=#=KT!62-N<}6IBBZH$?Qg7K?@+5D?i*5_ja7= zIFc7Ck{U?(myVwHEVu=2_|tr8L{JLw(xZA6z8jJQc2U_EBNyPK=DNQUVxz{ zbRWPq=IV+FXLp9|)|;(xiz6K{xkY`3hlUq&&UG{h{|aEN#1#?FVp$er^R%NuIQ9Aj z;i&*o<^;V$E!veL8`!RM`VtVE24zL)$D()AXg-p_0?C&J-fGWN`E_8_s^B@i@Rcu* zl#@RIQ&` zR_MkoLDT~-fxp?Ib-{c9o09mVBl+tNy?YXCO|uA4y9;aAMDv{Rxkl$-z>duqS*@N4 z<(Ig{sO~0~SHVQ^1l+#?c)(vf3igX4N~n5oJmc0HF)s^GA^(!;xcgD=?W2hmVMpg~ zVmKNPUqDse4f>-a&4KU_9rh5Cjp072+68yUs#Yz`OK<%ROrv%fj{Br zs^VxFR^){$LEmk0Iph_>ZZnrA_3k1&_g^2ham*mp{W4=_7d>&NZY#*(sz04RqpzX# zkQ52VY_N!Y1Ykz8yL!6%*LlG_XcFoN@UxzlY!~~yc$$0WtjTF=LrCJay8@Z`Hc*-d zgvSB&9HHG)HmK?t#Tnv>uw<$>J(P{UKbc#6gNbDQh%-AH_^V8XM*@0(cA~y(S5*uW zIJO0pqwq+8fgt1^fwV(?TZc0}q2f&kJwnNofl~mADYO`nBl*z|`Q2_@Zppy=DuAL; zPadV{cDN7_pI{R+I_O!>f zxw;~?)@G$*(YQh`t5#+8tZ`d~l$|Y4M7(7DCPTQu>LRWvzN-pM$mcFxL|D@ijtZsK zbaW_^)4HR)wG$R{(^adGtD|N)eyItx3f*U9vz&d-k@7FGda2pr%`*|T4PtvZ4Ix)8 zO|pKm;|i$}SdAt{5w40_^D1gmO??kwB_kv!Oj^WGjNc@0>dc#LHdF3j1bzZgnY0E)x$Wh?-hyOqy(q>z*y=!BUsHyf>IgIq4H zwYltKrdxz$KFwtxNV%8Ug;3FVF?(g9w0^Rhkm&C4CpZzIRAhQ+#nBT*FK+Ce>}hg8l5)JDQ< z0o3(Ve>XW&NG6y{8lGo{5`Cvj;%|1m5o$7kve4mx?SFu)j>+s&on$*zU5T)E9+kQ9 zsQ~&yON^b5a(SGqI&mix_AUKf*rfn1=`)QJF$Dp$&KNb4sRoi00F7kfy-l+$bXdyv zrt@0V`ezrwJ|`hUnk-m^bg6E95eGZIkgOTsn{&7y?5%-5+MpgYad<^1GRf9XQY;!v z>W79hxd|^#HF{}iO?>VU!zcJ zYH?s{u~YYdA3#B-&{f`la-@)~)@J=pcuu-8m(DLm5~T}p%4fitu^w~m9@Heco>;ag z{ahL9>QT@3*Jd8bB!LXY^oO`d0{nth@sIKIT;x_?wh)@`;( z_E^)c-h6>Yab;C=3F{OgUzAzU?lpxTR!TdO_-4~-IwO-SOZ+0oy$s~$)TS38KWjCZ z1svzBa@xnloAsISzc?}%&+<(O0`gM1;-x%WPfR!B=KwS^ux3;kEapc3GM~y5CrK?NXnLuvH?hSIQ)vU@$ zv_npO6wnPP(3c%4-ASg~n(JoESPIRdBFG*lRBdKt`97mmSDgevcOf)_Uh7#zuo(YbZ!s;+~S;$G`YKVLW_7?%316*AZ@i@Q^ zRVn;^>Npb%GYzx}R9=_r3yP3uKnDm!!g^r`@Uvw474LY-r8%C5#1$r07W%u9%~BX`3e7^}jLgPj9B+%5?AH|a09bD}c3H?tWWh{MasQWu zznM&{(2D?#ljJ#OU4^I8NW9Zz^Sm)}N2a%T#p~64=AXRo8#N`mbhMTKa?pDKb=gmX zA9HN;$Np>yW2`Z=l}CcKOi0%jz#^nryBdzKMd~hqiWZWRMr&}y;(ysh%0dze+OU9V zBbJwX>ks#om8vh7>e#Q6OL5|JlP%fl0LbDiAjt)}dC4tyo)QfQ2tS6LPa{G5IC4MG zWsdYZEMm}jtJCsKW%*55zXhyvE=(1xYD(_sQh1z8)wnM^&sr8uCt+!EwF|BnJu-4i zblXl=uCIc==g3Dvzi^~?PP3C2Hh&~8nJVX^_+uE9TuqPu4y=cbT^4c@S&xq51}qJ- z9J3y(>bL~f4L+0qf#{Z_ijhlE1G!XHb;wFuP+ufv;E(6FpAwDV(e-TMNdOHhbhVK! z?*rWisP7AxTp>>ftp&m;URS_0@k$`WNA2L!g--|QL_+TbEF6ir%ALd&<#RJ&DI%0v z58duX3=cvHFNLl#sa9z(HqTn+*@qnIOIa_cIONnbD9LGIm6!$#i|ET0v}0UkX65(^ z8lm>zIIm|VxZm)K$OvQl&7~sevT{CS&e(yhYJDz}Y0Id;Tnhx#xoa008C0AS-2td=gm>&?Z6mY@5L@^&jxBV1%Jwc; zzqXc^t^YM!U1rA_=!%x1aiwW>8I~0p&aLHP*LkMw-wg0F;hKsFnWBVV!}#6-JyY|VM~8PQ3Q>@9@5{k$k;GDtLx&q7(&>JjL07&2U>FEpWn|NPKtFb* z&`$uKxtv$|ABd-npZS%W{M!ifafw3P7}+!!bfP1LP6Eu-EQp21@4?i~gQrAa1@KDf zF(aFVUIg6gT2ws5WQ6ttT!Qz=)%+8P{avE`5(Xk;O`}Oj8bpbCS>JOF&rK}Ed(K_P zy5;Wk1IKdlN0wVzNb*5HE+l2@NKoMW&t5O&=KY4fSL6;c*?hODit7y!Cx5!#l;~+d zOBl}%x%sdUxp{7d5p~_Oleprn_`3`X%KFt2dwxl^~nxC^MwC60C?|J{Jv6tByk4*l(T>waaSSw=R^2ff#k zLRSMeKCXfIs^jM-cBMZZ;kuV+#{7)SlxTl|4djNbQ^nC_SclfKrS-xf#wiKZc3;pi zM|ykuL>1xDn0alGdOWOIPF6@#LD%NW3&vSMZ3WnDLfs(4WXq* zHmw3(>qw!`0umPfo@3{Ziux-Szh((7LJtG#XTnZCyPorUbtLr#RD95OMm7oU4kS^> z+SL_N@-HYLducGXHfGREuOR<-167hyyb#vKjx8jq+O@d&mzzjgNFr56ro%YarF++f zpWk{)^j84)g?=;8EFTw&h<=&0B58;T9bjaW&_MvR_Vmh|A*5cF>(q={buIW-*b7az zEOZ4xc}@s(Jp}-1Kk7b31hbk{n*H?x?OhfhxuWb zAoN2cn}nVOxT2jNjDiSOvy<@7#?b&6I{@lgo+~_ID^`^NMN2*czP`cHp^T&7O6pR8 zO&Os}jBFHo55T)rk@Rmfn)NRDn?SJ8BEF@I$tOwpIbhGOkFJRPe8wt>X zgk+_*#hv((TTbDNt0pMaX=KYepn+D5mN6g!@%N+UsnLBvbtq1=orub0(=H251N45O ztc*1Evd~Td&nO#~Rc@pca{OV_Mi-jbIzxHhW#uiPKwdhEKaSX~PBdqJ9maR7nQ^oT zMp`y6S(hUY%wKzKcI0hTr`WVLM6an1(~S3`00<4i#f!}_zYa=l%a2#p$Qe? zrvWO^%ZGXEDw8zJySqx$OK1uh@jYoPyOAW%1Y}isxrt}H5vtz>uoeNjD495>B668Y z<@G8zI6k!Pl;|daDi`{?kxkzKecy5a04mxXn@u$u7~BD1=G)SVPXO%$$fH*9Dxm7} z!sW%oCg>DNRLBF3HL_(fsNHde-s!kr2OR$zy{Dy{J{>Gt`4^+6?oSJw;x+M<=u-go zD0GXFWuaREHMsDd#%>b2D`op^RgLbro|IQ)${SkuzlTJ(0+e3p7e=-S{St7CR#At( zB$=w9>rL=%Is#t-D45VUj4TWN+;N5e?zk_4wlHI5p*I@YB;>NldPDxRM)L7qKusy^ z>^BKLoU-L&KWA#k)Ku8PovX=!DbcO~ZpP|)*87^SW^fDO<|T?^3GQyfy!1OI+QaGP z5_`j#S<8%Ku}&~{S?I*>5~sjgW9&wuYk-;v8D9nOY7;37Nu=7l%#AXIU2Nqp3+=~c z9NV!%`vb1|M0L3Yp^szKekQnOLJtNsD>bE7x`&X*%f{l6LlIc>5m9=J95zJUde;OW{1n6;c)@Hfnev zlQ8I2<7hqg@vTVl<8OK)vgefZt5c-ifzAa0djY#tM63g-xi5ia&-gwYj~^o8XHHIN z7Z-Dcb^}}ui@Mw;cr}loLT6h`DobiFN49_#JMtYMryFz}*9_8q0Zq)P`dE81sfki!;CBo?d-UtK~0Wq1}$@>FNk6K^TDtWv!t?+B#CzO zK<$nc>Pa^Oot@jYLYAVtB9Bl z&})U91^BrIPMn_qy9AeZ>1S>OGGr*XW9J zjc}(?Pbgf7SMRgRDhvI|$fmyd=X?#X;U(~4C+i(8MC((nsyegrX-PjPnSJ2>DkA=$ zQx;N2#?LLiOr{M~M2)4K9o#ch1~Kw-l&-Zht;3*~#e55e-78Da;%Xs!6Ou=E&qQ7* z=^#rYBN5X88d%7w1P&CUg|L-xjk`HJke0V!LiQd2i$eDr87`)yp=?O)>^7ywf+ls} zpZYwkdmUToet>Vsb!NSwkVNch3&NXGA-Agi)2_W6cp`vjLI)bzJQuXcafLb^S7^E8 zs?OZ8BMcew7kQrVp08eJDJ@qetyksS=O!|WlwAOtO-Lq~dX@hPj?4{Bg0U}9n?-C| zO66|dol}Fmb#b%}T)9@8f>pRWuB9Jc2T*dMPa4^**BQRyxI%i7fHj1WUW-H4DeLdM zV8}?VTf9^Q_Yq6!spLw%8ldDtGC|3e|DBG^v-mKK8-Us@V$)J8<(qnFRmt@wNx9ZN zg~tUk-C}9Zv6;||g7ZA*D87f2-vTUagrv$8!{6+PAA)=a@DE5zM&QpO-4U+_3%aFP z`kDbet`5k)@J9ivTIhz9?d-U}fp{Wu$xwr#2=5ERT#zaYFE^pG(2A5@tuO)ZA!&-R z`*c@X=q)L`TA}ANeST>@fd4-Q{Xa(v{ng0E7eW2|o4_8ReH|&Zz{p0S%K>U*n((`g z-K?*Wf5FJI&=Za;v>womFZ^3$mxZ1;cGooF!IU6a3(NIK@MBw(Zjm2OBAXv$^HE>A zVtH7~f{YZe?902-0R8tF(A8F~s$iCmFbUgn9%3Ib4f}GtzS}H+e*%8W*sVhPQWMSi zH_*P=l!Wl%X20ADYICH}IRF)OwD9?keI-cFgo_{gw)yM68*l!~KCY*(1xTN+y1^35 zLi*f1H^PIj&a1S4aRNflP_SxKxl|_Rwy?(5;Kav(n$cr9>m8>L0yre(#e_cvU}1|XJ6XQ4vNeSJ;#13X$R+@J zp~ZmRU<++_r}ZxB?=6?I4EHqyO+xzg8||+gb~LiQGf2Pn!&nlUWMq?&Tu?g;%MT=k zW*gZgG|zE`-tM@eF9*VM#VF5*l<%1E5`}0ijBx-33UB@W499;BRE>#(u~e9_=c#oh z+Eb1Ce1!jk%-;dBH)Ng!z4Jw-88dS)S06~?$)?;Qv;^P|)Z$7f#08Eoq+gb?FBME5 zQ4y`*Rif2$J1J#XRiXoQ3HLOzlx$%RNDMw#2uMCdkf`l${R)w60EkcgWYqM}^56slq z+&)+VD27lMU=@5d#LpaG=sBPVHv*5eCD@46VpA%g3cApdva8=ZAzfBK?YMV(^@GQf?*P1rSk%^eH8-&lgv|0`W#Om<7_X)cE* z0;yKjV(huW<5O~9S?vJeyO8vPmWtvXGiH#n_lAt~0HoT`@d%He{}sTDA?M)Yiaz?( z2*4Mb4fN26&W8I-ue=XKPnxmvk3oNSr0nXkI`vx64n~%D0ZnkEkbAhjS?B=A6*|Gl zW+8bHl$DPWU{>GRs_B)7rfOC7iK_TPfn>6W0>u(>UjQo$IR}DX*_ttf8V;+050!9v z;(p(xN$59#4RjH|wG$>^5qnzwGzlGI1tHvuxYF^3K45$%OA()P{Oa5|Q>?Xk`!S4u z3ZQ!k-EL&l4?#~E*&?Kz5va%5BtZ2ftc>WtqCsIU(fgAaf!v42S8;k$(|P(OvwYf+b?D z5Y%2lFCmTt$XrM=K^Kb((s#_fu?ug3>1)Uvi!*NZa*)YG?`h65!(}09l82BZGs{t7 zb`MOSLyA8`t^WeRVz}AmnG^6!pA$d(6W@R?BDO$LUKXUS#}w5 zFDVZ@L80f2Y!Z4Aa2vm(23W6Y5*iBhw0A9~;FZI_b4qOq$pEFvGKKghrFS2LC=a2$ zZ*WBqB|NPUSfDI)q>)WR#{kX=Q5U%c{&qW@dZW-$03Acft2b71^{mI^OLpuBrSU6# zG{9^jBrTls$~BRY#BqRhQlZlvsf%joYgJ{yP5YlJ! ztDD06E@SSe*C$kjzXi}5LflgeyYn8*xH zIH-Rhg6{~81!PBf0)PV(K~o&b-{2Sxy>arcw`_rYt?x2N(Up(TBLE^j1P~I^!-+Qv zT?)`Igx(3L#TqN3KI#&LK9(hjy4@uRJ!lCX(T){S%Gv2d^m4eIX9!&Zu*eqjInS`1 zZ*mDjKIa+sS%QaMf{@Q^M!tB2dl;Zgyo6iaJ61%whMWOqN5Mpnfeyw(&J3%To@m*t zoIGQRJy9B%`N!t&(iL zp=kOgVJ*UNNl0H-7>2JMJbic6=$)5GLk0=Ehww&JmXdrkK+dImz;21(^leB1MuZ*# z^b-p!^?@qr$6b;Z_m{dNl!V^{Y#=XPXZ+hms?#8OsuE|_8~9H90OLnh*sfr5hz;jy0*&KQ$eHAV0^sL zw^8Uomgj_u+H1Y}!cHQ%&ef+}am~n6V$frJo%z9*G`A6QM5HqG&o9 zkhEUa7=TnY{KAn3QKB{gu1ebJ$SXiMIx_E^W!1n_j;pc{Fkj0m`a(ylgenEb)LQOZ zyQ~8I)p5Q12-JG&&eaNgTNcei8bm{S9zxbM(Pur6)H=Sl*37GQo4l zpInvoZ&Rc<_MZp;w! zMVe8`i&V31bsAQ`1>o(St9`B6i8o*;-fces-1*p4nJ6bm*ILd^LUPac%S6a4L}c&< zM+(U$6UluG`q8o2I~l0GlgL+M;HoZaQ#5HrvGNO=`a70ii?Wzd-J<$NCxHl*D0D4=OHomT zvWD+-=IS5DuEs2TW|D3EJJ3s)g|LBj_}qG)zM ze#?_msWO_tSEaPiy|yyWL|(t#ir02K4{^wCKnFQe=q-R%hKNQWs|;mv5`d1-Y``i* zgtD%x4BeuA%JRx8BX{SwEGV|HTQ5!9g1+cTp}PUwh@|pGKj)I(jHS0a&wb%S>@DkN zm$O@z-BG4o7V0pvMJB)JNTJ7#EDO1eS{le?AfQGP9%Grd2<>WQS*{%GxSkquT9quE*fav+?4{_JbKbQW% zH=eZhCGZhWwD!TOrMwxBKaCyP^ID=Gv~&0D#6!@s;vZ=^6k2;{Uf$brcmmQ#0Qj5; zHv^Pgs3m1rDy#{eh@jZN91!aj7ag8@XAg3fScC=o^X!h9G|-3$NN2?^z5M7s!P5g_H`X z`;D}dPq&gP9NflR7P`pDY^sT)_rv%E5Pnk~)9G<9e(2#X zl|tC5x8zC_DpI};pk9RT01E7x1V{WJRvJvCNt%MNfjN8ZA4sV0KLrGZ<0qnEd>jZ} zC)-$`s%Q zz-%CYIF!9{U?^}1;Exf=HzM~L;GRJK3i$5< zjz@MW@D<=8;3=RXkW-p&eraiPF5r({k=X-K84eHR*W>GNfXUb{1ODLhB~rg135)~$ z(SWRAAfVZMGH?{&kL`Qm9}T|=I1V@-m<1@_ECTd6nLkwTf-8Z~05=0)0{o#z#(LsE z1Yht2;BNqfHR>Of=V!g}Rc1jWuoP%d!RL2kFZ{Le1y=$J^7jJY0{rp8UijaJ|2;tS z*m~esKq+XakOSPyK+wz)(OdH-9`2y%l+H0}M++-^Jbym;m^nX7Td6K`h_r0}E5= z0{cVvy_-{*2_A{_V}RX(sVTe#yoP0mp2HG+9MHpZrvPh!OH;T4yqK$p6)Bt!_Q&j^ z+XOxx{4U^1;C;Y4;1<9i4?t^Acs;NU`TC;^TUP-$0v`wNOyR5G-=^>kcnt&R8V#QG zxR^@GIaqfPP5&FF<`D-vB)d7!S-2_>XYGekzT+9(X~Gn;s*fwQZ<< z$bEtR0qsB@3CsYF15O6~aS*|8HZYmZj@f`et{cSlA#fjXKj4oy4dxyQa6E7#;Ey%X zR{<5^p@83a2>k_k1F$>bkC_CMM}YOfZo`<9`Pqec0#9*6`URkYn^q%%iNFDXKNcX{ z4tx;!2=E190(vt6+3<(>&j5eyCB1<>b_VtUrUUl^%G)14{h=Cuv_0_>xEFXF@W)93 z?*-_F9f;Sv`c%q4lKBAm!x*kffzOYn&j4ePnHI=R97X&GrUI>iKeidor8}?>I@43# z$HBkbh4n8W8*PD|Gm*U-I5?H}b{3NN2Z0K31F#-l+3?4a5Q0Xa6IcnH4x9z(F1_Z* z&jJ4U1BAYzKD&-~0sOHXo-W_cPGJrB9e_XXW)DN~Rp2{-Kc+)m1}LA~JQMs>3QvRe z^AG+w6k2mhBcQoN`JE5ww|z8M_+un-YAT@EJ{$0d9T1 zfX`Y$k8t=y@k~1bnrkJeE13I$hk)k*e|)!|*D(NnclAfWx2*jky`6wi?+nSM$1rHE^<+;Mr2cpS8;=0$ zL;6^`KTc2F8uBLaEr35t^eH`CHW@e+@Q2<-d;++*JT=m*vHsB8=z^aDPXW&WdYjxI z`T)g^z{i140{R%m=K+80THyUlU?HIQrv0&N9UpE4ZUXd{vp*(7>kVE1dama$fOlpO z{Ppmj0-j0X_h7wf>W|^jdd>AY;Dvy%w?MxD_}6H?y#LUj|FWLv>xE9e<>_Ct4Eaj? zI-nOmv!lejugDJq^s1(RZL(Hh?_3H_0NxI?1A5mol$VY_^v2`_Uin)K=$%S`=p{wL zuK>MysMidK2I=An{s!o^LjTU8*ALV5%HbMxL;HGlP%s&o4fta{v_7Dr7f zTNQHvedR)MDxmLI_+uoWs?pbV{3m@pe+~S{fLi{5fqe4@m<;HvQ~uD$_C5#Pk-`_j z`fQ#*^mP_}jb;9})Gy$Vr}%7)z6bXr5D%l?0euwCANrQv=YY=xcLCWkf_H#{60il} z4}F#IIAA7lV!+oIEk6z10_e+@`tYPa3+fMj%~PN3Tmw%Zru4@F@ZJiX0L%i`0}VmC z|DL7)n5Ea#$5;jL0SgF zzIHo%6m<#sLthmZtONADV1MWnz=D~;Two!f5B~bE0eiVHZ58Pcq%uBT-&TGW_&x9^ zVB}Z_KD~jjZ0G~yifj6Gls|5PxE;6$cm~iq!5YLB=|?CzA2)NZ8^Ge}F0Vg!q7B9Zeg{?kL2x~A6W|ZOf7)C6WMsA9(OdeLNz=ZO-xyv; z-w|97+!XX9zb)Kbx}GO)NOgPC*R{CTvf6cj9QaQ=#?M{8Xz{%9r!HEuVC5bw_uYGs z1#NBPJC?PL7hb$*Zb#?5wsGV3Sh1I#EN|yz{Ji;#XDw~-*t4xI>Q&v$?y+d!{q{Ah zW`D0q&f>MV+k0_0voDL5v@KpfZ+`chn7gR6BMPcEAgT1WrAtm;v|!JL(USQq zH?v1-0&Cdb?e<{rpvJ^V>TYEnPCJy>nSAKX3lYQO1{17$mu@AY^ONl9QK473(q8ev zS+IEN+&PP1pFsNGq0@cNdnJQ^{N@-sL5E=Q1ZP?2-sthsZDeVLbsI71FtqV8YtfQL zowKq5m5roy&}PHxUv)IK&tKNDbjh5>i#kvLmz#_>dX=^3o?2)zI5%^wst)k~og1rG zr8N^+O-EuR)^O6vtbKm%7|8}tJ})7X&vI^(6U$Nm^mLa^X<0yUqj6T}%K39n>5yeV z*Jb0i*GaGUDL|{b&iTuTkaIfczb=DmlS1(;nvnmyV*IDB)v5zZZ}F{{W~>=-Rb8#N z>t#LtRhjy-QId_UbZ|3{!qK#;gJ|Khr7QnCfVkj&b>_2I$LjyNORi4e%`|uddQRuk zQx~;qTBz#P|NM}08u_f2Uu3x~X02ShY#!NUqbQq(dL1~ugoanVL$u*pZTXV{F|4KuK?MC)`|K&!?Ke^u6 za8RjU%KV#O8|4jJMdhKLC{FiJHwL=zA_QB}|4RL|W6`X(#dA73X4xuHyMF(2efG8Q zSg++eChEBbdggXo16fCNd$w7S4EKDq7@1!{`%SD~yI$|p>v)&xX5U%ah>OnGeyQ_% ztR-I4-j+3HPWavaZ1N7eO%Szw-^+Vfy13nxKDDCi(zRC$uT}?mwe0pjie8V7_3v_# zSKV2v&+-76O}Y6j?5KZgvv85W>(zZ%KkN9IU9^p)BI znca0*w4^iANqUnVt8LCc))&uepR-7J*R7V6WFaD&JEvn&+pLbxWjrMWR~HU*7E7yh zsieEnxoz~FFH!rl`4nu?lKJ!O*`ZV`moyJC*0HjkY&uWgbJ3E;DloLTX{eHqioI}9mMcSdAHG`)bZ2zVo3l*4 zx#v}4IB@^PI+qQ@Jr*tL=zLvf-fpwqMs&wl6jnFs!HSLB@lnL?HE?t*XfUn6_Sf>g z`}vA0w_82EinZhdnswM3BAj2lP0Bq?xan4)7Afw^Vb;k@m$l8;-JVStI^*Zg zndcS{n?HC3v_wT%{hG*9=|TV?=|lw8)(X~BCI(>h7IV3-GBwt?F*&uH?^^^Q;(|gJ$)xj$owd4PL z(=dC%%Xg-pCyic*_a-%3niosqZue|^VEJ1%tWG!c?ZQoRKJRgD?R(6df9jki3)r69 z+)r%hxoqOAOx@xx&zAdo@3l31Qo@r(bLTJXJUyx|Z}pkqqU&J;Gpi#Ohe3^LTQA*G zM44PzJRYbP>E!D0;NC-JHy^XAN?%RDhngQ?E?!p+G_Cv6t*6|SzwLw`8Rh)^Hdh$= z-JG61iJ$H=b$c5vyKi0fAZ0tHnLlS!ccZ8m?yW8Uj~Vg*2Rd}OQLfqj^<1QGmNz?n zFAF+cRX5JZS~mPP^&PQnKBq+cq_Q zzN%Sk&x4g*u;;j;i6t|aPbe8nJJ9|e$l4ngn%_45(kH*Hz+*k=_qx6~vPtcb6=73~ z{d)BI-u>L9^1psdM{{@M*VZ-5xZ2*9Me=Y|gg08U?%(UuD_dV>b3oMul#Q8xrmy!N zFYOItmWHoO7~iC>@_%lqyp~VZyh_7zlkQ^H4wbZ*so$n#RmaYTPS(S-0T2$LaA5rt zgK1M{6K0|RxS8ai42Q4eBA}*vYfi&9|L2wi>2pr|?>C+<<+{k`k8W8en|Z`-gxzkz zeB*TXm^f+ANqbJH{#cx!cQHl6TSA8R8;~M23JYLNc*b!c+J66SBuftKYe(9i5vgu7#m%gDYD1 zq-yOGscr4;?geW19*Kpv{5jd`7cTzsGpaRVu7_uAb@#V6gjPSj>H~GvYav;1|A%jt zgzZ6Tf+}%gyZY^t>Of5NWO_obec95s`5k)pSFyR{^p4K?r_P$cY}wLf8y%=O>56pY z;#&2>E7M6Q0M&5ztaY#R$ZPN3e`Kic?INh#jFvBpHu2eyO=?ho8*%e?6MretZ2|cz zPK++RyHH&<0(uSB77nUj9;jXuhHJ~(wPqN*yR8$uMZKD+SaVvXua#wO_|4`Mn?Y&{ z=f9@g>pHiW{q(B#rR3cMUdn zHNHuME(_QjjEKDj`LyOX`$sKakypK!WRq&h2arvQ7YePfYFvAj3j5ke%U+}YhGwVU zX0%t-(6+O)!ONPw+vikO|EuZ^OT;(f+mE`ru*a4SuU)197>! z`&OUT1iuZ1x$3}Jvr?@&tum|d+e4)Ak>S;jkX%0b_hdI1DYJcq^rra+;$j#}-9Ct4 zh*#}QbPJ!Mo{Pb~gu%@f0qGUJN7A&*2)Q4W8NX<+{q~L8PG7*UbL`oa6Psg5ZmcJ? z7NV0j(+d>TGn5Bw|m~o*SZS#+|)|! zwRTk7t`f(GFRN^DEm&3jo=(Eg^ixTDoIFoYM4viuk5rf+KWblUKSEP;q36>15KUW@ zHuk)gbC#VvX-_@VoQJnmOv@_&D01M&!ib?|->^A#k^Kga{YDMZa(-uryLY4uVjS9- zO3Ce7DK;?D|A{rz21m^1vXi%LM7P;sgKkVk^e{3vUd?|D+joYx?u;IL!X7>Mq`W7j zy`+Z@kv;C->9&tIvc2b@y1Y}r57c|-*j(+ix$OK)wR2W|8Bx=&-I^{R!acOu#=M)h z`Rg$ah_7{U&*!r4)WZL?UrGG;Ew6sBwLbDcoLbs-_o-1`tRH19l`_(ozIe`FQxPr1 z<)m;x+?Y&#JAXPZiTQhZycXmIGhAF_8vCPh$npF+eokRol+0OJ*Iuq9r=0`moHemn zYvPMyV_q7+GgkgFzuW2m=H_lPb4ffSN&3{Cwz`t^*&2G-F#Q=-cUoLYM(qxLL=%6S zT8iz1iW5gvl9ri$mqo=$d{QZsD}s_Lb9tffqdo0AC> z`*cOc(gZx5_%_bpc6@ez{OnjiIA2UE2S#;tiYt-UbE#;76-IF&?jVj5k1u5m5JhvTKbw3>I^R4TcP$5r4OWKR=^t}m{ zsJ>50x>2D+J+1Ty~!t#8pjtCdR=QIE~98B*WXP@Fs>`DlDQ z!!Wr$zFVXF?)Z_qx~{dWlb_c8xoE@}`+T^+h|(&o4ix2G$qlD*gN7+jRC& zd}#r6ZQ*{QKNQZd13gi9t@H5OyrDExRpPT%Kt}`Ka2V2bP+?+e8RR^cUb z>bE6-w%m;!_U@TXvKaYdAg|L|E+}=-Z|=|O z%^*&Fv6MoonhC3=!Q{Qw7F`#wzM*tSJn^PG;&Bx>dSBXSYINm*KDeW}?nZ|{b1fG~ zg<{c0>j3gNqLDuzjvpZWCEw?tnRk^|Tx->}P11EI6WumLsj;CW>bjmgCmFGm@#KhP zcA}`*b;fG8fjzY20T6?c1KT^;Drx(n(-x7Ob&^yT_5gVLeYj9#W`)m!W`^(`2Q z+wIPuKgBl{KsOb>SE%b+N8hgdO2YYb$=`%t<{xvCI(R)3D}nfw1ExkJf;op-XKSW7;ImLkI>R+~V*Cmv~tm=>AW7Z)KP#60Ook3yzXYsEM|2aOt zp!1jNKcPMx6}?i5Q(c5m{tQt`_*#azlpaiOvyOjT@ry;Be^I!$OOwEIp(OVYF0T9B z88Xbci_-$p>crix4yH}b<2cSzl+{){(v^1H$-2@`2dgVdb*$CJQ09)IyA?WCNBoj~ zwbsGv=>__lnsG{T-Gj=u^hr*l^h7=s=s5_bZEX{J37e&D>z1+B+ja`{i6^@C5q%rM zR?FAcgWH))+r0_*nwyHKxDxd>xBBjgM<_i>LPQ)Z6iSlWvAAy9S*o3am8us# zTS94^re;;e(KeJ}o55C|!Bn>yDSplJCCnxRhdAF|HsqLh_2OvyX%dZNK%Dk21(_ey ztw2x5PlJNdA)7i$-Y%a@u8xf-j57xNI5QxwCP# zTRJc%u3nA5rSIeC_Jytntz|_=b;MAu&J}8-V)?41@v20Ejhv4yu6t&sa?Q^_S93mi zRhVvuo$jO{9G7;b4ky{#0ZVp5FZZOaYVwow&CgWhbNNZ3Yfz?==3_!xK3Vk`QCxe{ z6e`Wa`PDJ8&RxKE6l%a2n z@oi@ah8b#24QXaA$%~=Zl}a~3vUpG-wwg61+On`*73+@TgXZmCbeR(_Q^#4WrBQQg zsX0mtrcQ&5I8Pe>9CH?^)RSdDi3X@A4;V>L9=WsiEMqM5 z<1sU`3mzPI4u39=uMFMr%e=Wg;tyGSqHjitzR;o_52-nCMY*cC^@xhLw(`}%%4Ndsbq|_NcmHvFM+3ri;eJ7DV z>FTt_ua57h#ZxOFg^G0gOm&76Xoio%pHY*jhe-#aeNao?a>8ND9OyXtNW5XP`Rh3Lf_j=wV|#fsU!`9X@SAR3SH%7*a&ej zUy{HG#dkZ3PQE}X3ni7YG{UTw%xvSN?K=fKE6vtGHZnE7 zVU*gNMAnn0(FW6Gl+iqMF`UI~)n1&f)lg_mu2h@1(t6kH?E3g7o!u0FR%f4$zofG- z#b49e*W%yn?Dz3YI(sSpj@tJ-1yEyA9wt!&KarzZhwjBu>z+zWUEPPK*k>k1p1A;O z!BRTpQZ|OlIQgC!&U@r!87FVh*$r~CjFVhz&fr=TC%N>Czp1lt%E=a-Jg>mnd4&hG zI(tA)mYuINGGEyY(xR-+2Z0`a4IOO8RI}=G26btUu7I=RbjLaU3T1o+8(QvsZO;zj zNlP!DGThW7)f!k8x zZFj0`Kg;@NG-nFyeG5?(x2V&E=t-CvXaiv2P8QQ?kfJ3GA)_JN71~$hQ^_e4RFl#w zQdzQSfb0i3*_$jBby{t5vNKsI9&AY#fZkN-nyF%X`7y+qF_UF5JBsa0Ch4}q5mY4; z99KK#q;amDlooDiFr>=c;r@0bk*A-J9LLGH3GQUVEKX+05-D@%(sO05y61M{O1N`X zymy>Lw$vuxmR!V;T>3sNdYw64T-!bUBUyTB6(m>5(t3cc(UiO(7q~4YU#iXbKrRZC zNSmOCAD!k!108JKH&Tu_PPPrQLyuHHs4E>tLR45bK{;Iu%>}db?+d2UfSraN>N@;& z*HdicCDHh#V;z@?&4f}_Vm*J-c(U%2?Ma4)WJ+5Ed|1wcli}3Oq8dC~BsVO<)$sZqhd@uGCFUlf0uoy>Cb>G+E&=Zo=^#(6Sc zqbQzE;;Ds|D$7NrWL4oTcTfu{->r{R`B{aoQp)FwDEDM(p=&_O9}x1-WI>to8$$l^ zEIL#Eppbt`p=)T$AF8T&%b6PHT*7$L^$1hpPw{5blW2SDVf+1Qko^y~5+(;91?Q;Q zaAuzzmf55ysmuqToR`?Rd#c3Z`tln04Jxm=zO=?2tI~?=%8DQ5x$?u}*cfshGuGv* z)nAylweQhuOuipp_UoTJ=!#V=TjP!>SH8ROZgx$Jiy4ziv;&M)U2b)0#j`)f=S+M% zE#|gkPbC@g5v@-yE?msQB-QMIv5K1nx^^Lhv&@|B5pgrfcyKQ@t`-q-GdXoEw`FYU z>zHQ?hWHd#d1(ScJn_|p_EeoKoFx6XOxk~WW+mBjpJdq@H}4)n;`nTOD=sqGLut)J zk1Td>*Y~;MmD1%$vVWGI_$9lO+X|ao9a-0vq(Y+bx%9;JEM|#R%!2!goGUWrp6R)D zC6VG5auT(pygY{1u_E#P2A;bT<6ZPTM9bo@u#g9W-_y8fTyV>N>b)+0Q!3=i(RCS6+zE z)iV3s!WDEGDVh((cbFzupDpYqToKo;IJ?5~3PsMN%^Dt!bY~W-mw=P1r2%W*k%QKyQ_{9z99OsfGJ%X#pG~>eKj&g$3v;~WNO5%(8?ErVm9)LqR5NE;K2=G~ z?wSorYO$6qcrD$?+J2<8j<@2enNx#xD3FBK@mUurHItXxY*~swWjHgcWR~FE@a%|o zt|Z&<7^>?>^Y`m7I!ts63{+?giR*R{w2ofYE!H^OnL1tI zD%3RzWu(Sc+L3MiWaGfhTNaad(2TSZ12j{?FQ>#pB}(==ivE7oTSUI)B89_?7~wj* zG-hC17c*%W4UZx>g1;6qrD@QtvUAcNl#m2Nyrhd1qfulM%GjQkJs&e>SQ)lUx{|As zWc1z+AJp#f=@-OC^dKIk;=&RaHgO0iuD=|`V=M>Vh1hjJ{v5(yf70AZi=Tb5W~GaD znH>bNRudmgr{7^u{=8AQ|2tOG{kbZZvyt;CKU0QvX6>Y z8BQabF^lWoAu*Sdo=}NIv|61yl_)BTO+=$p4%?YONAv6q5gZFylEU1uo%Q$VlN9VM zwVzj1BP%sZjy{@(u2!wGs$JT?nN{k744be?g;-K=CTsLUM{#qG{KteR@g$=u3d6}u zcv2Fcb{%gyHu}1d=g2JN&9~Z7$Q!2M)qH~Gq#TMqiRXb7yhzHTlS@*_8#Y2(GtqLr zG}ThbBMGgUS%)btBri4UxhcNOaAs7=LC71ny$^ZKZ>2s0!Uf^UmxB`(A}YSq ztPWPlJ8*gy@=|Vb-3oOkQc}uv0=+>LVbEX(z=4ND9X?%!v7>m6+3h9dxx_4H(HP={ zA+I-e3wbr_wEXp`ry0m zkrwhK;X|I$F63owt-&P{hP-oOB+*8Pyi8mnP7zXg!y)f%%VDEK-bE(fbI4QfdB{u8 z(vW9o#dS~qDh+w*`48;eLf+-lW^_DmI1PEmEUvpiVlE{;aUri(r;gSq@;)F%-w|#LPktYqxX^UB zS*;CuDYv+8l{%A!Jfre};Uszwc@LP~UP7Kr3`3qcVaV%E-9lcCI=%gSsHY*%krwjY z=&+EN4HR|y^%jn|BuH<$mEV>siOEx$EV2qlE41(|O~%$(Of~E3PAgRstzEqYMbUMV zge_`$8g_la_Ozmw%r%Trlh!yQrgubi>PW^mN1SH0BjTlwn4SuQBSt$%GB%EQwt3>* zdCux(Bi6lfDc;dJ7S}t{DlVn9(D398Jy&4DlJK-@D`0zCPWtt$bO`2(J)`&5--Fuq zm!&AEn;2{C(cCCSh(E|^?IlZot(sb+#Sxp495jPJGuoM|PvQrU`c86Dg|s$YXzlC>jAE&N;3_oq1u?mbx%Kwi!LQSaiO|ar%s(EDvIr| zw}T~Ubt)CWQnFP`$yU2>n=4i=K-0BpYE!GTYyn!66dJ5as)@y0%Rv{59ckCwjHI=sfM#itmKW0 z#3Q8W+j*bxkH(KUB#~t%jv5&Z8w2M0#o4DiI7IzMGHC4LU za2j`vSzNdBdBq(|Nl#qdsntm%i`c!#oiw$lxZ{(;Fp)+OpVUL#@ku?z9iJ2$q$G#P zK^J!%X>rGq7I(Y=!Nv<@q{W?PETnPAky+e1)C%8Y-0?|0#2uH^W8CpcJ;a^qS*r8h0FNamRIji#v{lt7l@P=vTIm2u^JO&85__moLiw zO`_46mznV%irHikOcSByk)M6IZvFT zXm-5Jh|x|}kFBtWX>4VlN{E{s=D%)hwj|peMvzR(S5V**_iwJ%Er)C48+B^psVGuW zQWl#`T}FDBDL+!V{i%#&^a9#4mQIZ)yGq4T3A>v-YZN-sO_v7JEz%WH(lD+L zrDWVx-KsgJ(M}qd>15f3Jibbj?uzLA(zq*@Mpyh1orf-?93{tyt)*MmT>Xo6-#%OK z5NW$LrK{3$JM}fx(yos*wC_{JCllk>w1zKTS}%KIb&8&jS#UakPCwICiWf?8DqF7t z)sM7tj@(bBoWg^@6#8)8s!A4|X(wl{t|>2)Q8ERtvz8j$i}pO|jI^mz9@h_1GWS$T zvS)1KqS-ac=qelA;_~r4&6CWX7xiMYSPtJSpKx=xlKiG*H zt^0h0T4_omCAX18#?E^G7J*{_+%&K4pl&w$SmD#oZ$-+xDpzaDrY>OXp2!OBiDV_u zEe#07j7~efjX+-9lPROqoa^d|3Zul%b4g23*VmGYy8V~3^puiM4KfNPQ+Fj9daiuw z%4_yitiO!DopAT{^0?4h;$_e4b?ziWky0u$AQdq$W#M|p5>c!nDt(Hxy2477>q_r} z)&uf%4NuZDJXtCkxr5y97a6^U6`^ECA{!r`Mut_Cj2l0r;n$}!uF5}v$kqXA7L$_L zTrpdm%V>g|vj~6721o01Dk|NH`1nHC2|3L>6gi(#6->rVs-B9!MI(vyP{>Yun2nrA zwlK|+x{~BnC#Li}Q`(yGu;UxDh*osmzFaT%-MY{jDQ!k5KUfBL9A^fVwUbYLG}>`o zRV+$VeI6EZQl26ac6=Q2+{`+2f_SdpB6FQ5HpsFxd_2n-=Ri)=vBmctJEM^w2|wuA zb}DtcuF=&UTdcHWXOeW?TFI1^cI-^js>)BPbZ9#E41%ah;yx$9y3&LnSpiDT@IoxA;nZK{68<{g!s^fNszNvC&Nru|VTNi>RrPAgkEvl5PrEXCqw>q>Xmc85?QOR-L+|xb|8-*Ip|ur2YFu4xxPWV`{zx^vFaT5#Izl=8;YbabZ8;?JzvYA=5j zuQF|W8eD6mW3}LY`zbC<<`^k!UzQ;7amYR)X{#B>WpQp6i#p{44qJCb?a_$IM~&Y3 zv`Bx)Rgyygfy=Z?spj?{vQ5tA;UXtYW0pQ|Im@t-!?lV}=~5rQw$QHC4sJcB99>Lw zBo{&1QEV`On7@)YoW!GJC(Us+JLfDoXPq6?>?{+snsrZXQQJEhFRR(6rD4tbRH8`} zuOV3cLC0mN*Iugfpeki8t;#n*rq^(ew2?BE&BB zSswA=maB+17`!2_I&q}0h~k=S)F|8H)3(zT{M_@ZR!PM>EG;WH^P!{%xOQF(+0R}? zEL{hw2YvBECQmo-h|5meV?d(YFF-AHc5Q>UAm*Mv4G-r5aX1LE_yNoT?CiEFH zq$)ulYOt}ZrS!enBgE460-EhcfUKfn%g;PKP?!n(@fAh%ho;&Ze_e|upTzIrYX~OBH&^FpS?E^v$D9> z#rIHM{WaY{Gc@x&&onavDuN6$gl?M28F0WMDuyT~F%b<>aD;%w0YV>#I2;F#QDRIy zjxomE7&B-*iScMcjQ41c2BYG1@_XO4R@MIYX1DR4-@VWM=Wd>dUbWV$RaL82t(xmw zh5uHqE*J~cm6zDE#={$TMV=Q{!^qZly92a&nu6j66^w3>!6G+!e$;-elpBoLR$a@x z!A#N*l5lQ>RWQObff@)PDnP--R5!sScPaDv#eyeV5wx}oso1#ok_X_9v0jV z1Gesks|2#{C3H0o<89*ZBGJ6?!jYfXXjt;&_Gl#x+N)fwo@SC(k+-SYs*%arWZ=yYf`GYD0(2++(29h z5g7|{RH9cnOmQ6J)tH+Ml>!WIESnMuJ?kVJjyrmn1#B^R=F=Y*N*RP zz-ciByMi~*K&YEwD>?>o(xP*sFo0+Nl2*uHF%l0F$QU4-Fn6+?;v$GCL%>R2YPV68 zbi0RWCW+RcSE5X3>f{#A5Sru=+{khhWxhnd0+(}j6U6dRmO99V8%&1duNfZ9aC9LA zvy+f-erTwfp@xgi@Hr`}3`F|Fj{2VyGMW4vD1}Qc|5Nxd5_IjS%YF+ornu=CP0VQw zwP-k&W6m<#tNx4^dULI&OA;V!Qh8Plqv1u7B>&AqadOGKz*^yQ)C9x0;0gQV7|*pI z4x_{v8C_|b%sdW99@9AHr@buDFh9N-$+*m5*w0`qFjeFq5cEu_e;%$bVak`nEp_vj z!vKkk*cv`{RU=9{jB8UxM47$J)UwXAOHjTNWo0U8XvwcqWz8htM+hhFRs0VmBQ<_~ z<~$a($N0+iR!~XZ$jE08TnmsW$dh6{^WVgZy9d&^CW9_h)0W;TfFkjgtEdoh zlyiawnB0t4;uPv|%2Xse^>BiRQ%^JJXdNg22?0E<5h7*$pGD+2vX0~Bh4He8JsARY zX(E;63{8?1WNeNjy?l{Gi+=s4QRbE^3{YH^b*!a6x#_cu+t2x1T>r& zk}`Rt@s+|(hokT_8UdCNkxC~u8%Ax=rJKA#ai}-YtNlrY+admd2x;mk?zm^m_pI z5o=6-1kldh-pMS8!%4`{**9+Uq+5BslYP`0sN~R*|`6Gg8rkC8A#5v=Vt3^|AxT* z$p{wGlQjE?g8HLo`+p8b`nlt^*vFra!0Clz4+on#U*>yk(;$dy+7me7a1B|^+aTGqTM{6)rdgjlBlpV zkZ?xa1LB+{xe$fnRsd!72_5rI8qdb{4=w2K@9Lv=QkN>yh#L@zE^igTfaz z3qPOv7MW$}I1(m3QU^}%kl6^#zDQ$=Yw013U7)0%C#6LAp@Qe|u$DKiht;FT=Pg44 z%)w~9b~36Q#Qz5klijjl{@xgnUb~)Jtv#_F!KCdQZn#JD$rp(gzXNn#*s zVBjvh=eR4pJo1bp0xzx-3v(YRv(L;5^tU)xunlJw5WX#YSC&rAGJdl#N`<*$XTv>g z;{zTUT&-O8QO~U8aV(lmUZ;0G__CC#l1n2Q811!F9k)XpXcBeu|~X8_8l1S z0&-qSVV0o6qI1P-dRK$RUSHe>5N6JZ3L*(i(12y{nqx^Az?pWBRaz>)%_Qgx_CWL` z$#jZKUY5ZQ-dqYC0WIsL@?;c18Bt{nWJ!|iC2`J;41`HnBo|5IvauCFtP=$gv-Ep~ z0l6!Hu=IdM_9q}Un=8x|kWB?8xg3F5bzQa8#I>=NeT8W}x#W%*F}VvMtp#|6Sv$Gp zyT$=skfT!f8xuuxt;cRp8t6xOPE6zH}^woDA(f~GBZA7J$;T$afv&JUw!{{xYl z`23l&PP*t!gMuWZBNF!XFh{}5Ex7U_R7-`cG{>ZK0&8I`8%93?&}>sdX$=bU#z^>i zqKX!~zYrI@Tem+q?)gP*>rNej#Xf;-1xEDfX=TyV4(piW#%Mh3No12}V`iBb|D5Eb zD|FRw68@WnUM}P@5c!r!Yb*|)?D`D{IDAZUZiYFL-HCz-bR4c97Xa`}o`+cW8vJ<% zP~C`|bby#hCog)uz$>GcQrqY>%owdk_Ysr-x*eg;7dew@3M^Z85j zm$O52Kg|DF{{D~rOGIyXx4F>I`FfP>EZY_#Rl~#q8}jxj*HKFqV{GE8M&_^7GsaI7;MR;4|UznIN(m z5B8N@yB@i%N4g&UxTmFpf1dj#XEVP0s8Ay%uIFf6Nu=vXlk zzr^sO)Q=&fPGt*d`Zah7`^Uf%K(Z8IkunT9gx{0hZG%JA_#tB4=(<+8{diQ7fA7dW z#=nwZ{m-~C$N3gx+h#78#k*{p>OT`ypc;~pO=hul@_GU%@d+x1R(E$%1LbQ1n zq^$hCpuk?esX#6~DT~z5*B~xboWQ{+F~C7R77sgycyy65LVyuL+E>{KsES`gwY4JE zKuLEe#P`*@63`TGu++(|V3D2MOd_DM7%X)XSdf>aa#E6xK7Xi;+4kY(c7w&_ zywTCnNs>H4Z~rCzK9_x7ulO71C)OwEcz~1DgZh5dBW2l0?qPuV`~a;{K^YDcWXFvr zuApEaXBM$Vz>OG=pBd)(IsE+ek69bC5RS)HoA9{mJ#5DJWOv$|TE^)=FO2=rD*7GD z;lw3bJl(t4-K}5z_<8ovny-^7>GG(0O3J?ke2WW0_eKAOm*gkVUfxk7P&t2 z!eH`>V=r;$m(_niiMTjfD+l5Q))q^UFRenC1hKb#T!g`4XmUWW!=Tr8_yEBQUHFtR zp3WobcZh7KdK8q&d;ygl-5Fqc=bXm0sr~hS{}up3q{WjPeY!Jz{#f+ z56q3P6J2ztZdJ?P-sZN};6K-GhF`YLEeCYeDF(4NC^qAppFW1!$E>s{%*6dLNf<9> z*0|C0!?4y55-c8fOx(Cd>bk(&OR&TBousMD?U^J>QOan2CxjHf))CgXK1<>JSdopF z(rVn`nK2&`n+TRYA5t?c8r|R-(rN@N8V8hCu zKSVNuqtb)L;r5wkkS1+ZB;5yJ8`E@goI>LuEnpkn)M;94r~s-L6>#dYtbjuJXbIzL zoY3JKaJnRbxWif$%MyW!BqgJghxMlD?q`< zOigP6qoRK*nQ2MUMlDfvz?LW)oeoohigp}NMHj-~(Qr1|tMt7k;h#zvDldwUijlBZ zOaLjEKmT^kXQ>F~Dqj(uT2n%~icm^vMHu#=iU|0YD}o$W5eiC05R4VkT{6>BMHscD zA_Df{iV)Ghx$jD=2n&zVa5nKw+BY9j5?&@@R76pHR7A)sT1Wu38X#q*Kehu>bXL))Kc{rwWN9iwzPV(D%v+6SS{5P!^ueu`=pqj^)V}Olgw+#6|2Bc zZ$m4VQy}uWiST^=7iI95ECgBSkK_jbYT=hX71_GPS+3*UL>_BMk@>vn#KqE8$0#GT z%bB=1)#a!#Q1~bwmsxvCib>?c5Os#KgrB zmefoXN02BTD>o(Ha>ci3jju#>2FA$3aX=Wsrc9ecgdv@Hyik@xEmOL{iPT!4WLmco znQ>%xu2x0pg9}z{KpQ~2V4_+VrUgdR+&k*XLrqhKGC@$D0h7jXC{<`S8vL6+gvW+pF5*-WI+ zW=IJ(lafCS$qpN(z1rj^1e$E;UwGbIrP-2PU9&_jw2mLu7dxL1?FS<&CL+ zehU;1nJ6>(0{@{XC3>iV_)w(`p0rFxMVV3`V+e6jh@znb%!ri)vpVZ^Gb;8GPHuz*0Qnu?I3d+)tf`ttdPXxC|)`prn zFK&azk5zYzq!g>Jc(e;O7#)?z@h(QTg)N3i zEA3=V(Y{$m#eBT7#{x_N7lbQn`0y!paW}|??!iAU++54c71_TLikqA=55nv}Ho3@$ zkJv7dl?!A)@ZmfSvcMKVOqEW`6qMBr1-V5RBXwwZE>{BRSwbwzD5_=2}gE^2fi@j;0`fXqDP(`jVJ@8?@0~hnFjY?Iv#_21cE= z)Um*5`uzDfM3fwy!;)(lqzEnJKNMp7_U8xdidT8?M!#M134Knux_Ml{_t-# zYG;K=b5@rVwfdwEI39Np^GR!3lEdjZ3sDVcn`0p=iVb$!ir{NVEzn`B)0X4EgSBkVgMjh_d{=g(@HLvx_ghQl@+&k9|V z;pjISu|Z`6mB86V&eVEY$Pdn557#li8_2Tlsg$L9n_^nkYE6m-#6$~B@r z4{3(cf{heLjOu{%(&ioF4ypUx8D*H+Y?w$s4Agpv+-TuP93SdHYQU&y@kbmVOXUL= z9sF@9%W--ZP&6j7){6bf?75`{5Pya63_#~QYF_Ak18x~{wj&jAONlFNGg|yUbY>X9 zXWXcx03J23;L@NojoSxV>@z@h4=#MYd!FhZsvrlKMk6Rat75fhl>(WdGM>55kTRYb znJL41)VwmR^f;6ro%nXqORSIL{ugC3Itt4k7}NAZi6gC~ABOMv8l+;tg2E)50kQ{0 z@7z!q5>A!@Y?YHoCXfh2INAsK6|M9vnliv>V42Dr?#h?)1_tm#tEA@Pv?7T4K`uGk z5|*~i06NIZbM3|r=7|8$m5UD1rg#*PY^_m$tz~RSj1Q_~D@P;LiDbSyFbJRJ#No809Wd+z(8C50SHJ}H&4bU+GhRi)c(Oc*k4PGb zCC?rNBUcPh(^&XAZ!$)ili48>mV5zLi^&@(E`V4bO@vAnl)iQ*u%Y=fBYq1`Yq^YE zjuK_)abVZ9##*c~=rsm>j*O8q{!WQC0i`}8WSZ3S>EXwoL1ybrl z%n`5_M2$A1^7yG+m6zg#`v6XFn8cL1I?s&6^{{|=d2h3x?BAM#b26azl?iO*5Z(&mwT529=fhoCL{3YHuwGT~aJVjwvJ zR%IaRKT3w=_(!XvR1;FLDMCB{Ilw&6F5$Xa2=ihfH2h1DSUMa6DB=oXkRX6uTvgUv zvpHcEo#c`iOn?+rOS=;0VC`Z$)G-}Pyq|ZAz5?(o7pk8VrJN;fI4|_7Y##73yFez% z8y(H7>1_OW_Bo-@68j{H-3o+OJll6XKWce_e$S4LgpuuH!6pGw+H9gA%q@V_D6~jC zN5pc}gMHY#Feb}Yv|sD6*D4)cz#>X=FQOpz0w|S3EDpV}o)nZD9}iHxoFmaKEQTd> zED0<*Vd`?>6|LP(IW#CKc?gu=r~+(kkcloCPBMVFZ7HB{p8B;sC1sOe30G>CIK7&( zM?+1cr>J|vF@j-z&3Uq+wP&3vy@8 z*1V$z7%TK4B4$Gsvm%$Nr=$H%pQZVkwThOANhJ2G5O@ zVU8Uo^_ZHdswiA|cEe_eOa)vMahjy0%cS?TqPnnr4(<}3v4^$mA6zVXnAv(WYd z8;NFdcuveMmhWDq(Wo}3Xd57E3KKbG6>ghZDjIhfY7{L~%SVtK4EqZ(dQkrS4Q?o*hx9pu?NTLcH9o*bsIHKZfY0j2VqL-n$|)>;0;)|FXjk) zf2cC#;(19dn()Y@f(hHW-RKxTz@8Rk7mOqHbWG|778DEMeikG zg8LAdBUnRAzW^zxNM5@`wRmQRY92fz!gL=RPpin7qne9n_E8wux3O%BGq~8t4EhXl zp~0d($w==berycrW3+d1hps?ig=<7JT%@VE|U+q0m@%}nj*4@yUR|A=+64a{k8Do?NVN%_ugtRMHKvUf5ea-Gmu=RAE6qP>@CG;VYSUS+=HCR{!FZ)BGXj z>O#se)I@ThU|%}sN6c5tRD_KqmNYixy$EMzY~40tuEc}_jGiTe%Q9^XsrF3xMKWWn_89>b7{pMQmM%8r&l1jR^iYod$TDc2b!*|UpI3Y}G+8|b(MXf^7vgbd4H-xRh*XCG%T$3SC{KZ65>42v zW|Mlr`GS`HB!uy>3r8rGeUYb$b99)J%m$&ojHQyZ04A(0^hut0SP3#Scr^2pN4mt} zq--WRj{xit$iRtZE;o8C`k5kJ6LD7d1tKx>vG#qyMZTm7T)M@jpp|DS(0R?KfQJ5> zaC1ku2y)KDtH zx^N*+@iGq&EU+|!wZdWnTWNVP9hCt&myP#t0aA~sNP^)i7-3E~pz=M!A!{a)163_B zI1rH>TrZIqZII0s2#41y73Me~g~wQsc-jIg%V0I<6PX%S3x2}+_(r;@t-gY)l%=+n zFpQO_LQ$vgjmE9yQxTuos-^6#9sc9!jWqbB?bqia34W<4OyTLDKS~n9YfWwvR(PFT zxEA2r3kY6-@4+s1SMa%TgtlgPGPqN&>DrJ%BXecgE#&Rp!dRk^{bP`Q&AE)fG)k-R zhVNF03(ty@j+`3@(ke+Z9iOd>akXg`O5~d)Wx3yu<2%mHJQadYJ)7X!7qb8tXD?%U zG%e)@Bc^9Ws~{7?)n8ykqdHb3kH!#T>P4YrP#ip-JC)~G&^Z#rH8gaN0mMnw0EUeE z&x^2*$WKR{Hg)c#(*T~vY-+}o-WfZ7C!HO3{6d@tcM>+0lqU8IWEGdTwWIaB*|;pq}uIFSbb9inHl067R$1H|zjg z&O&eLp3Od=EtfS`2FonE&LuEG^INDw2H=uHtqf^Ivd_+$!C8dBI!|9uT_sijCqs*^6Yz20sJPB#qRV(*>FDle>K}GfDY%xFN9nNp^M##=oL`B zwX6c)F!WRVP9>M`J4r*|`N2(j2twak6sGX>&z~*{{WtqgjeNwxeP=5B zC4HwxiOr%+-)S6Z_vQLdqqf+0u9Nb7*1l7@59&J&O;a!QonH~j#eJvZ(tRf}X6XTh zr3Wym-d`!gTJAfQUfg$vIO)D~tH>$pJBc!*CK&t96l>@^i8AvJtgzmGHMfkr2T)h??lD5@dIi)$D?D=64Q ziNye2o|?jto?&V@{QPr+sW-V)b}~wRvbR@qZT)c!R}F z{jy98Ay#qeUWyoNy8(nD1W>YDJ4BU_KI){94aIdvHcrHY-CC@`hi+$$b`N!kY26ON z_QIJcR=SsoU$pGztxy<>3=p||Ke*o>u}ey{u*2}t}b#CqV3eD zBpwTi2MN1NgiV0ApMMtqI}e|UU+gwv?@+$1n~xW3cn}HIsK_{; zygGYBG{-a@QcYAEOLJt5V2&)IzhAP%E@b8@`0uO@%+iMJC6*=8f-&J88#nXPI7HHz zGUo!)Z10C6PWp|n1@llGZSRzI;DhHO#%wQuu)P3Eni>By5yf6(HLS|5IbD^cIZ`6K zjMZm_(NBob;8ve0=9>HxBFvr$T1TN+Y3qRjwnxyqhrj^a8x4gH7 zWPs$s3!H&yW7!hs1{CTbW+ILG1S_=E?x+0cH*{d5orG>|(t23bdJI``Z8dunED+aE zZ_nn}U$7fjkMGozvhL38Gh}!sy8$;>-GS8VdGU37?h!IPg4Y6s z;j!G0jp4_+pOEqsyre*iHTB{w`kj)iUhs;&M)6AXsPXbl>#^&BxjOqN_-ps4EIzo0 z=j&d}zMieP8SlC!?)B^~xCQTS$^A2)E6_)%|CtXRgp1sohzYMj8>o>-`i?!Da<1m} z>cx<;U&Q_`dmy+D)Xk!f)RNr68ILwHenK887UkKG7nX|r`FJFuLT*pv0}{u%<5t40 ztz1QL?M?7)#Sg|=jx?@3TFN)U5vLJx0IlU@2`f-nX+2z(-DdT$EsGgt6Wr!aLJ1C2 z1$C!qI&KyJXPPz*4B7qcIW3HqO5*5IcpGDr9UvXns)a6tWOIg^aP`$=09{wc@6ea{%H2AK8W= zoX{(ypC#I_!%=VfiW|}+1}oz*vr2qVPcBdgesr)!{8Hjleq*A1oKV0to>`MO+E24M^GI1PoQ3@wZDO9D>{~IurlBl>H+c$RE+(#K`}W z{kYIVP&j3u3Udd01K3|@k1kxgRu_5B#867e%at4t9PW`6dDM8$N%-$i*}oN1@Jbv9 znIJYO(G~%fbP~i$6do<)&!UvdD7Rc^PK%F)BN%%c8v1Exh#Ng4e9wiWQ+G)gYgCQyn(TE5 zS!|1lYc&~He+b{~CKtz4{P}l8Y)|N~=b+qLeJw*tAoddV=RwT#ApYA)dehiu)$(u$Z0lVQgi`U7o>m}bv}49 z{+rADeGUBwC z@BwFW#U29A;uhg7E-LjLq-w8!C@7=t(ZJSdt&am3`~+e16M`=Ii9|`VC>^+<-6Adv zCn!h+#jvJAtk>4BpkR++!fLw;sl+(Cyf* zbe_dtMStG#Fq_VO@LwM}32e2eqVSyr*EcPX-VF(9%vPwUR;_XR-F4>c0Pt4C(|q7W z9|u^ai7Bkb5Oj(I*uV@dbV3G>1tTcfAF~KN|E`bgquA1+v|)YJjAL zd@5l8N-;q1I5Ly981=!6V_b*No}}O|fOC1A7$HFd$Pq3HPrQ+%MDQbSgt5dHVfo+* zL%0yo2FuL0)ZA}3PM%a$ibQ<lrIwyT~O(W3ltsKhA>fKG9 z^FvGgd4^o3m893II;5veILmJ1ED5(_3u!41+NB5%aV*R@bWCN_!CjSKGhdo2j3pI9 zhnEU5s}S3BwR^+gq1&wJmaXOv=106i$I(C0w%7lI4kZq z#ztR8!l0HoYf#FL8x5}C1g?hWP_S;Qg=D5_1GtPQ5}L-7!*1wUeR#NlMU4)fVD7~C z6wVIFsv9d`O;y`4d|M3d+G2*60TG&p?0mu)ELyUNDQX!5I=f7u(5~O)4lh**kE+NC>BFQi5uE13^jIqy&{RM5KyM3TQSt z4Cr8!3ad>L4mPQ<+T93{kU($YBKLi6@S^CM6Vu4{k% zx9~W4IIi_1k%Wgc<+aqV{R6b{M1x8=;SC{Vxm(C9F2zEML`L*Z>OY^QTfr-^dMlSeO6FJu>YY18JGqRWt0 zi7`4Vumhso#)pF9+O>_a7c4Xv%OAAxN?+#iGkKK1g4H~VfaXyYEgmIsz>7qV0Be61 z(eNmN8y~MbQ3MG?c@@>K6bq_3Pz9OC>wM0G9D$6%6JqdmGvlrRK}xJN|iPyeeLh@@;ACE zl0TbAsb<7r4g=GHRjGhB?oq(NHcLE;Vc|z;QtD9%#h+J>mOaX3k=uetQDSrns0?D# z9;Kz|;!#SX!vtm`x_J}@#iM8&5swm^3rgVE_GFo5tlU|re-J^Wo?*=L)ThL-dp9^83E{AS0cjaKLN8fk-?u2Uwj+M8lZ~3^bmJ_$pKJ&F(cS7Sn;EFeDU( zaj&N+%$o4c{mT@D$WV}509!!_77D^pX+eZT3nKBXAOdSaA{qq=XcXjbrsA91zitI7 z3Zo!JVHBh&%!2UeS7QEWtGjalK1`=qp*zOj_PHR_;YAP{4_LYO6c~_zf*7O(5T9ob zAV+3V7)FNV#dk6=&JmC=9K#yc0V~IHvdOnCVMP0?fv9zYybK#b8PQw>tjG2&MF`9R zNG|z?#lxh9Aiti0F@(a(v8lj8kee-FP*5^-Ij~`dA~5m^4uWBVBCuwEE70~m^_v0W z1#9MrU@uOB@$(GWk?vmcnuk!f^#0U}_$QF9A{3O0P*5r&FrXp=7TOQk2uei+EGmMa zRRlq+h?@agMLcT>qayA$5ZWhb6``P1#J#|ViV#@U{D8%S<_Lz05Lh`LEN~FCicnB0 z;vrx|MF^}FK`>N=z*-TH0c{oWD}YuJ1Y<=oP_`maNn6C<;ISIF_{$i#eObTy=PtUO zbEwO+ayA({5H>oMOmZV)U{l$OtRt83`RtFA4U{(fJGh+fAA@|S~6E@wkD37BFd!6`HGAHHw7*nO@MNs}W|@oWco)rxTV zq}}H*SAuT73mFx@`48{pMW%*9;_w1VFinn!mb)rFtP1Ja!63Rbgc^u5+n7+6jlhTQ zV91P6hX@8Tg0Md*@;R26gRgTI<1ie@mn=E4z!&j^kE4e&3qonaI>AVb1(G+dzW;X`#x2i#bhk{$N<&d^I)W<}?{3S(L0RM>kYeH!i);5sPeM zM&##T)GU{uKPWNX+Y^)S?OTd2y?se^)Z-r!-FkZksSq<6=rw>LcT$2!rNjG&ElJq4 zCH)jJLQ8rQu(c!wr6rLgv?PJGB}Ft^Qb3!c@W($dIr#@I=@-J(VoUm&kUzC0z0AzP zI=T!{>xeChgqB-Upr%_=z!h53A0Y!R>DU9X7yJ?l7g`e2EYp&Rww6RN)sjjhSW6<> zT2hF>#Pxq2-yl5YsJ*?CF-&Qgoe(7e`0EbpR&J#08X=L|w~@EN0>Y7PX|6vKGxf z^6qk$JvekGv!B~Qq&z?$EP zMt%dDIq`Razf68_13H~wzema?FS3l$y`wSHpz3Ld=GWo$p@>oz?DXOpvqNk-=TpZ%8IDZCMD2_507l$}24w*x71lHn2G>Q|@u{as& z=cb@Srsxw}ZuTk!R;{*aWHw2_!Q5a}Mi9BFiLg!=1Pu;MjD(pS0R|dVtB4LT&}c^e zArI&L2(|)<54LH(d>4dhTlstC;{K?41_?P((QV_QOl`>lM-v()Ph+AnQcBp9VN$jy zqafmCB?Hiyrpo_)y?DV-)5m0Wt<(X*pbvpn9}0>-gxT~Vu<9eCp^t!u5}F{-^f3is zK_7DwYFQsfEz*bKiu6HT&ve=$)|OF=v}L#=Z4no= z#iUGI3W~M_EYenk)YCZF*0}N7GmKw^z@i58J#3H4Gn{FSZwRpsJD6Pqv1VJ!+n=^Y zEM|=OqPf(ZcrSwDOVM%#*4CNx}qQrq_517GO*R zgN`Ka4N|wCu3_aV)v#hqHLTcT4PPd;EgB{mG%T=cSV7USFq?)2Rt-lqG#t=UfE%O$ z2WfaS&;<=|6Q-6lY}6tR8?H#h#03pA*{ER&sD=ehYZyjQD?3>KcpnFTtS|S%P~xP< zz=i_Ym}wQT@-dab3maAtD|0@A`2vUy*1&*o3k0xjMnG=uz%m9&!g!n5MbPQCUdEG# z_42SY(ra{pCZ8D~?Ee~=DUF7;1?&^!+ZH@i4n8ax2n$k`3N-0x)-CTn`;x3+ouKUA z^KeyPa)JD%Q$cwI>6>@f!3ikE0vLBgHKlR#$Q5>qh{k*_6tLWOP%$S;SJ+@KA*FY3 zY^TWNqa=k5<`Pm`UIe#!>(R7MPSzBC=!nhMbV zGX4aSTDl!%Sl@gN?MAkP1d=$Zcr9-SohEWy*bY)+dRj|NdRp63beYzcL`Ma#Lv)+g zDku(L8-gql#WqnW!F1UT{Y;LjQTJf!jT98e6tHki0mN6H0tm;Xpg5)g!Z8I9tuKIZ zOaX*rB500jnItTZDS*+#5b@t|Ocw1QIi|q&nH*DKZox4ftLjT`m%rwi1nHaicc)_# ziUrg$mBuljLiA^IOvYKxF$GfEkC=-Iq%w{vkjglwKuQZlsa7(x>X;N1$E2V*roaHl z6c{2X3)o+T1anLZM#prrD59)m3ZycQNl9fLQy`UbOly!99n;13_hI=P9TUl)%`u(H zh@sBEkq$hT3P=<6SBunA$7ERF{3qItI3|G#&00BHc1+ia+!h>@64Q=}n6zVRDY`hO zlISpjn-Sd{lY-)yv>}LN3T*<*G;iB74TiG>YdDaSWg3R!-mP8X5)O_Iy~ZPRfPscb z5phHZ7-)$8n8LUd5MTjSW&}A^4#{c2Vw%!Nwo1qV!(*T*cZfzDFCO9> zg@HFIfRxKf%te67oCsQS5n!Mb1rY0S0n4rd3^6ZviUd3c>h8)uCWkI1H(v2wkdwRcRcHM9KFGOsnpLBAMGhqv zFV`jCg(Uj~I6-^7La}nSEik|#2L=QAY5;$JSr;m@HIi#xr->y*)dl)XlG|Qb-*PuX zHC*QkKd&^oS_Xy$40zCFF>bPxkDIyt8JAp#?1j%4$;m>Bk{!n650H=R$12q`1UC#J z4oDSYNZea?ox7L-uFS=l;!{;1dGCrO71+$h0Gd2oz{W|s&`%T7?g_*I4# z&LglINLESdOpz)d?x;!SAtAm-`|3#o!cpU6D*(fdNWyj_QqZXzk;Vo?)+l5{!bNN$ zOhYl4Y)E7#1beX=0|k2&lh(2-NNoD&Ydf*RN1z>#kUL!Ah4Fd7%;RZmw*&7YAaEyN zePfQGs-Y5zn~?)<=4@1de!QTmmaYTv-+&4Et@mFfG=Gkea5CTJx~qbSY0u`1JEZ{G zI#HqkqC{T;HmHrTsZG!+wJ}_YB0^5!f}A2Q3zN%0Q`*IdYZpls6s29pgjHz@7L}TB z%6@e#G=i%@2^Aq-hmRnZAOaTsor2;lrb$L+^roPcogmyIv#%hskV_61xuOw*4jWeX z3{7&mL@?)Z6^WUysECn=7wSQ=*xPa=aV5`9oSZw)YDg&w%*TzKY~JRZkkL^hCj`xj z5rp=|8VTFCYytDuGev8CGHr*f`-*An`!9g5{ zSZ>TkkfjqWPfkTpuy=r$=g+y=N=sx|)|sh_y(DIOVhG_5nZ8t5`Zv3=(RJ zLq7M&v+{==iTXWqR;*wDw8+ip*Wq?nI7kjy1Q^kV(>$eehAS0> zQ3X)6@SHRed=kqgrxjM;p}>rEx)pBvya9Mtg%5gnA1KuoX|1)1bRVekvdE6bYR$^% zK9H5c;zs;I($aB?rHPs|{?T_>x#jM1;tnflIW2ksp{K`zWtpL;p8zb}&}4`=n|Nn7 zeTS7ysT-PPi#IgO#et?paEN2!ctf*X9G1p6O9n6)b~PPL)!F1`Af<{hqhiW(^*p>< zLJUfeYq+k0XLiJP6p1=_RjpJE_Q8tc=9yY)+!Qh$mpLo^{L1&4;-|Smtn@az4Ou*B ztm6)iY!T~Vm9B08jAg)Ff^*LUc;3bO3PuhKM_++_I<$x7FB`X%iD-2-Gw8{d9E0%{ zNj?yo+zh;bM;yu#vG``m3^;eNi$A*rQgXhz@ksM$5(WwSVS0Q&%Ru(=5!-;IBZGl_ zUnXKj_(n)Df2E*!CW7X#6cp@cVAKAJ;pne+kf{FZ@cGeS8P+#nHi7=?@c9PCy79^p z{ng9_t!*usJ9NZbV(@dtp9z)3 zK(+Qi20o7t0$yR9xIbjqKzdJ@<8% zOahdK?ONxC@Pr6xT3jizQgHwzaRcgMuVeUB&s2O5%ce3Hi)381OptpC!~!JP9mQMawC&JzvolRtF)HNtJIdu z`&ha1DzcDa$%7&b8J1F%Mo%FN(NoAmbQJQ{LU|R85%VJo!50VdWrz=yWuSCjm1LW}+)DIZ~~G*FfPFZI<$~0U&y7sW$^d8}{`g zxV$2jR$h_QBwkrXD(PTFD!#lT4-;`MD^lqPD^l?XD{>~}nIZ`m6vKxFsfIG3<BP+m<+J6KImKxkAG0|%)|k%bb&azZ50NNJ=LvJeSsdKJP= zO$xGMqi!-X;7Jk;1H_rQM9;NLC1w08cPIZ^T8!YMxDzI|!Uuct zu@HpE#PJ8M+RF)WSe!z?w$kTSvkmRUUYym8EzKA3ZW&l;}Z#cwmBsBUp>nP_=gh zjNdr|9KLe|kOqVbj~oF88WHz^gEOb_U1+lD%qdv`Fn;n#VBPAAcueRB(@;3MQK#cC)=wUBYLcOR7%65Lc$&??dVBB}izNXB!-j1(1#uC?HqVwD4V#Z3_Qe7g z#=ikc)aX)(!fO3QR}qaY2}~vClFgPOU}=2@@u ztk^18fBAR7uN0=w_H?)MmOS09$d;e(Hag5T{dBis*@_Q(x_i51X(VFIJO%%if4WNmF5;0U@HXe>F&UQhSk=w1<86nLG9&|C&7zT63D25;&p!vtdvTz zI1oVtBQLL>0we=lnDtD_HxRak$IAh#|FY8W$U-s@!SLRwe&q>$rB zL9Wl<8sBg?0mcFKU7x*$yMVWVhr@MoEh@ejP2z5BZfYB0OrJ`)7ZN7b5>>%qc~%k^ zr-*r%bF<}Xb$rs@xpOu%sm=2Gs?7|P8;lt@JM}25p^*fzp;#}7c!|*1zx?-1sHiQ@FLnARC*9WnCtmK=Kz{@ zDJa%e0jyaUv1VNgigl48WnIh|a{hLfb|fcPPJsqbITPhNGk*I*SSqA&(?M8<0vCVE z0@?Wl65^*Ul(*$iSr{E+(x0+0EUm5RQx<_c{V5CLQlGNuESVbxfk&>!e`mx`Stx;b z{EsYr$|4|}1Zi!hkBE>@S$xTcjb3rIsa3K=ghL(RGMfq@Y$|}Fs4*glnxV@hdYZ z`&+_{S2*2}q4J@akyHVSKq(mgQzAzC!j=AJ3^D9Hq2Bp1qIt$WEDOX!!VQ4pPydIrc(McDBDm439>30)=e>H z0WypLupd{3gUHCSp_UwSf3SzHy)sp=Xsn&pxX#^aE7@ctI5WO^_9=OC#Bh^@aU5Of z)SinV_Lz%fQFKO@`W9e@uwZ#u?WIKDRtSX$h`SuB2@}u!Ld%^2VtycwPGI#+3KlrT zfM}P%WK&;w!j5PzXX3W$!F!KZiPB<}DdCD`1 z{m0A`WB;MpanPP%t*=ommN*l^+VZnvvA9_ySRT4bdLd<74pJDkgDN2_+9g!0KTke< zp1A$GO!)kv3*R{$II>;Do)0vX%CUBzOI1Zm_XRrDm;_-`uk`45FhR(knm zU{hYi7JX+tVA0or7lZupGb#PyzWYNIPCU#7I2ZCzP-9Bx#xBklTDKMUow|p2~j-4Z55Qh0Z;y zphITM*SDpvQzUoP$>2NrlmegeOrW72bxPE=#vDUKC6JQk1)i0ub z^Np)b{T9Am!ccS(9n}%Cg6asMX&(=EaitCGa*eJ{12opK6m4kft~mF&OvoHi9)|g> zjAIxB{HklEbI5q=TAhXv!%hR^m;jGi zlIh5az-oMp%jw98>#R2f?=F$ZZ$~89ygaQiEg>PyDF}yYNx3*-dP2T1JqdBp5xt)h zMcAe%-vwyX69r|=xffXK0u7T`o1Q2rSTe-v2|Aei?Ygdlg_l2YgINk}FjNkXhz@Y5 zi49mTa+&d{$nhx;=dTuY8|b7>M|@a;ohCW80+Vk8gfD_tlLr9WO#TMO5xK(9**Eu{ zBBrKw&PXm(9o~nimQNgYt~@`3Rc~8eCZpegMIt*jIayoItK|7uzZY#TlN#=9k)Z-&7wjP z5l1Od#N=jx8O;p{3|0B&UXxgRA)MeNF6eVpHHEbIT+PDB+bOegdVBU#tuP!cUg}nz zTwFY3Zp*=3+eIkR(i8CC30RDwf$oQ-3>Sw`D*uLvtwe@(uQ``IV`MZ5f~_jg%Xm3P zXNbN~e*g=5@~_}vgv$(rvWFd`Sv%%ju~1Q6>OcPexBI4j=05%oUqneeBz9 zuFp^ehYpuxbi& zqfl*!!0kw)7KP^57A;JWsP8SzARwZB(n+LQ*8fOs^RP9(2TMjVw)ku9cdlh$S**C0pT%=J@c8!ERemws!+FL|$ z5thW3yUQSeq09O9HImB7zl^_062j?F*JnKbI~2vznmp25`&8DItc$QIsuIp`M@wI z#HLkt#gG&+SK)u9M%h#@sZjVLD7ZLkkyN@GJZx?GhQ5(t6J&BoKvGL0OX8(7ifrCP zHHb+oh@3F@iWVmrIAC!Ck|V&5b+xVsZZT$hmQ7FlJ#ZO*x=-C&p zTA&rj859J4p8|qCy^s#HqsU-fQi^{UsU5l2ICV~#|9QjWyEiZ9&=RK3F-S_DiYFVY z9nnsw&PHKo&tYNY=U*4OEu8UFBAh9Xw;~EEgP8Ogzm}p)|639rwe}98+tz@BRH`)? z8E?h*X8D5_-hThT;c7I}|C+1Gi7HxfH6J4v1y^Gsb2TX%Tuq7w*CHX`eEtqL$M6xue74p|yjUavV6|7dJSU_D3$#gX_4ur$iR7nXw-PJ^%mR*gp6gdUtgRaI% zEx4LUE$3>=Ni~-dNM&42d66aYN?c7FszF_ifaYoxEv_bTz@j5ZfYsIXgA8*u3PxAc zUX)zc)dW%*SEHn|t|pMmxSBeoMcWu_f6tP?(bbUr*<4LmMhx~eF&#KJ6_7^f4;QJW zuEwyw`H5e{7R1#EBysqk#cSEs%oVvUxEdvC$#euU4l5$#Hv^3^M`<&aYKl~hy3n&PXV0!Mxq%sXu zNo5;oAeCvL*CH*}*?so+FY-4wP?A4e1HGORLp|?J2mYE0h@JXJL~3aRHLPzw^B2&) zG*E#gj?}zzwA?_S7P&1nP$i}tC^6{<+ER3Bpe4~^Horo2YoH2B164zo1{!P{(_&mG z*MYDW#y>ZVYhH4U09T0Iz(G0#l9W=kc4A>{5yQ!^nOD{_LNl+ivdRlh(W20L;r|Ch zw|q)YQ?w}bQQ`jwLNm{PN=^&3D70R1X`$VrspFW=eB-cxO{_f90BAJanUzf0_5b}^srOm8Rl)Ntt)X`N=`3K&TU;`$@o`RwOphW zEf%SEwMdhpsn%#PjSEPSeX%JpjVbz4KF6+q1qC}$To(>7jY?q|5gXW)*?ePKJ;{O@ zM~JENav7RC<^lZqg-0BLq~L_y3|y3SOP0ZHo(QcpxJR;2@bHQIS@u_)-2N*2JSMm5 zpu|QkCcYTyPCNq(GzESz;xm#trj+y5lE94I5xd=W*?-FN?_1f6bNI_8rxb^89`)}i zi*N;)oCY)7X?{5~KZA2Y5sSYfmNPQ4W&9zMFjhw08Caclk7a+#YxEV_ggF|@=?5N( z$Xfnferp3>tQ(qI&GCCiQ8n!lw;fM!y8E*aW>HPxdocS1uQ!PTm8%=p$htjI0rKKt zEJDVACTBjXc|J~eEOQU2oJPv|3Ga>lBzr9uW!<&;Tk{CrnuqXZnY?HMTm*G;~i-OIwG&h!5HdKRl+J{h{(owNgk z{h>TfPZ#-oB*%6 zHv~Y`Vt$AuH~x?pf5@px?1e;}o?vM*{s#qor`|Nga=5EjD69BK||0qBS6XcKuf5@QXa!~CUfZ^x+3}IpGP+N8TnfLwK z_srbh%kJ>TXCl-|g_{Nw=W_%e7jQ{zi#{dLOdeZOlD|iUII~`yHx#2rtjFx&sq5MHc)a zgX;F5ho)-z*CK3)*!!jV$520N@c1s6QV^ARM1{p4Gwg^Amdas$$tRG~O0Z}g*8-0% zeW~SDJ7I}^tkoC+LV#8o@0kqxA!KwS$Ol^Qqq+AXEHq!EAS&^ilZOy>62OCh{_S4Ol{{uL5^+Y3N9B#5p#E*b z2XJrhgNje+(BSVrsW`x^&Iek5%-hXCeBAmrUKag7@w1HKrWiixiPRSFb`$0yFz3ZRE3((UXowf#5`cKk zZBmzwzqerX)ZJ3?upu6o*FnVicbp@wE9`A;LS4LC}`}&s}tEY zNIO1MF$V!tdNXpHs`E4X`!~rTpiNH(9?-zRGYS+l3X4KZAF>4hEjc3&0#q1JNenpy zslnTQ8R9tzu+$!q)T$}-Uo`;?IS_b61B1>iP(o@Ng-vnjQvA2{%$S-|IOG_L?|m}0 z_li>++b5Ro>2%qCk}jK4LTVbNT-lV8F54F%K2^5+EH#Xv-iWCo@McUcQbKAPrCe%C zNvF2oQbVQXeGjSf5mM!^R$p5asytGl6ymkYKS7mat4gh9u0%!ug#pedtsbZjQ8V5s zh)TRh{Sl(#vk{hIv6%BkfQ&QNUnz5nE3-FbS#kTdq&H;mkl;HSygR!;MGZyI^<&+z z=mQ$?U&E=fT9v}04>%PmqgoFGFBP5R7(e5mk_=#=H)yweqt)B6cL4WR{~1LY#BMyz z1Sw>}A2Mi}&Kn%d#1`;X%?S(euI5;6@;wcxO)4d1UZa$=Nu{K1@?S0Uh|AP+{i99( zT@%pumf0+gPurVPLTVbNoRuggZ6z}xUR33h&jaK^5h!p6z_We68fkFArD2dTED};~ zoZKcVVhc2|$wCJ+PX^p&;t(@wPlZt;<_+!pGEk#|p=TE;p$OlWi0oiXYg;K@Q?>nD z@TQtow*jg!G@iDa02GEmtp=d5NC~NFlyVAFN?KvZKzu5-8!R;x=jZ9_c}@dbJxU3w zX_RuQDJ7lSZ;Ml_8z_x{C3sa6&>7etG@vsurG(TpO1T-BQqnW9#SqW3$prrjNeit8 zgYQSOpJ2=@gKyNTQBVcMgC7Iud1&{Cg{Y56RCF*HrM{ort7C2oMP#MP`G=7h3}7@# z4iz#H4ejtC6Au}#hpHGJEc2DO&LDXTi z*8&AmiPxxqu&B&l`sb$)rx+ga>ar2MZexBEhnUFnru@xB+?>D75Vz%DBI2d|D~5O_ z|3;j&1v$9w@_T^+o zwI%2Fu$W^(88;RG9rils zYOiOX&E>cL@FLc29T+b3`Byj68-y@)hn6j*+}Pa_4s3x2Hknk?8;}`u4tj&u-K)-n z4MQTlLHA({{6PZ~FDy_(4*N+&wwRGeo zZSl?--l(w0)rg-ol37XEkoIZ1NoNNBq=DWi7bqbU8ilihe)4g;lM9(p68BL0os0s* zVV(>5%!I1h-zdqo_2R zziPg&7X$BTVEEbsC1hrXL}X?LH{rjg(+inV5;HRx7h+fq7h7f+*{_fm&^^E2dH4O? zFLDHsndDaB+3)?oUpWop7 z>VBVv6KQ}GxtVJjH|OrjA#_jfV}?G?ZO$XKIsX^s&yb$T$Og7-ysM}EWW)(wK`x)9_ z^?ECWUT<}PUpzn1>S7G%+{M+Ksu9{$y_s`xxbn@_yNK9@sT#=JYi_`c%kGAn?OgHL z-uh0iklfjNXB&iew%LuR1KjR5TWS&7QoDo4({|Ku!h*ir)b47o6kpx$uUHsye{KIh zPl&$X{>=^uz1iU{ob`2Yb-1byp{we)aglFZ-GdB0Sob7DPu4xd&@*+cLQtJ#?9SdhUe_a(jE;&f|%<_qwMSLihB#r8h#i z^u7(xF1g!!-_sYNd-^`m7oi9G?(M5;+uQdMA|C1c7Rhh*eUG8{`o3@E_xpZG#D{%1 z^#gfRziav-bWOi4{WSKLemjWR(Qi|KlKWrXAEB%JZybQo#sOCiKgUEXyDs}5PEyidpt+>-k>)JBlPCr{XCw!fAH%#cIaLo@}ENx`p+Tz zIMmoT^hz4=mBY3UM`-Ktox>5@Is6@l-WmRPhW|KD+-UZ)V zpz8kKg5U79kKZhOWg+mdEIdG8{r`UDH4q)%VmFMQ4XbeQY>VmHH1zu{me&_!dHrTv zfxJ2QJ+4505B^O#KF(dk707Gg;uP^#ej67Yx52?FVpGLVc40f==oE3Ef0XNskHXg} zVxNDHi1*;`3{m+e=RC-%8%BGDOt}TyXpVeoqnN`WD0WiL*mNHdo)l zQPdr&1;_7j!SOrrcN%4T>zzFOy%R1^5j)%5$_2+;;q?@;rFK^>5WC>`6tSt@yJ)KR-HtjScEAZL;=#H{iFg!#P!Z46 z{f3C&z!fUu=}ymg0^)giLq$B=`Iq=Qockplq9T6S+c?zD<5Z#}`-A?xuoTDLnJjNHTAA^5X#GalHq9;q0>p>#iHg`a^rN9bd^B|Ha7Bn`MD4>fD&n2t9}Oo5oTDOM9`O+`M|=eTsE942 z?i>Zgop6zgxMK9K(Ln5imsG^Y`W^K^?0};*#F(voqF^h0r6M+r{pMI8z6p1!h>yo^ z9tXr`cuYkc7`JIW5S!pM6|s5Zu8BbGg5Olc-ihBQ;`?x&inxE$vy*^$cG9CqD&o;2 zpFNU@Bd?#Oi0fy4dlnGihDTMz%d=mZ4a6&Os)`W5x)^@-C-W8Ylli}z4~}2W{|$#h zsLJ0gd}$#NFD-n{5U(wKpNRJtzQ0I0-d}WG0}$6W{9=hBezD{QE`z?X2Hry#BY!Lh|eZ}blidC6>;GBjVA!H@q_~_1)-ixCl}?t*#B*8HZ_U;znz!= z4e7^D0e3&fV~#a`2I>Lp_Y0d4Xks^k0J@1r82~TG0Qfa-?Z3tW@Nx`*AHoSY_Yeob z%P|1{dLE&#=f8vd|L!~ar`Sm#`coVcFUN@Z9g^SShccfJz1nv<3zXVlHs9Bh6h3%8vt?E z42S~*AkLZraa6#Q7|xojF>A(X#sk=vv*v2dn(x86q`^I%ZtMc+Mx8FB z{P%TvwF~lJ?Xrpan{;SEz6=djZfHP;3=L>B&WzD$92cr&TmW=-_w%^@|Ge(Yy8~LT zV*_~3-ub+pna??LHRi||7^-Ao03@RVAdCutWJrMNIY)-+IUYbc=g9DyUg!4)bUx?E z)jCJ6(m8T9=E&dl0qz^lk*hIBK9g^SpSkOwcLnt4U1ca>+527I5BZmKwp@+bGR6Va zgtKLoor6G?3<88W0#wNe07$xjJY?f+8R5acze@UkK>r!^IA14xeDGF$qu}iM!Pebn z1b{Xf0U)0<=W5KHU)ck6uW0uVv~>Tl^^gzuQg{4tuj___@VcRo4AqQBhF&xb85a#( zrEk6mtM+~ar`H8l+$;9_3BIEsu7uvVlE}XOx?}G&!C*Q*H2;y#; z^7a&D$gos}Vd=uDfG(W6nxhlYtEX;Y#)he{O@;i|roM6{pjVDO>!^IqMe~ERj(Yki zz)v5wnqwEqr@b@{881!SfQ2LwY?$`8#k@TYcP4nTr(j^So$n|v93HkJ%gc)FdsrL$ z;S6-Nj|^qTBSYWfXNun%dd+?Wui0Gny4!Ry|bEErtuxMzzzm}NQa zDk<_+C^FV(-^<>VXYNhx?I)nOzfQ`39m_u5SNDQF6G@;S3@dqhagP6;bg+Eg&o`5}_=g$wmu2{%boQ2JwX(8~Mp?@DLiM9Lv7k&VWhpHYP zD~Z2Ue_kz#KTW=MG7}KYCk*x{F6?BZ_Fq?A#YUh&Tpp@gSB1-ls%2wwSvL0OvAN&R z4sITM_gI6Kd9!!>;O?;x6Gh?j)IOa5&4>&S1*2(Np~zT}lEr27AP_-@HyjIkU5?qj z=04wyw%tu0+J4>gmR8Y2TZ_SR0P{sk`1p?c@Pvgo@3kQ-&O{2@U^z&f1qXdG?@xR% zu(a0=y=ALb_z^OT&5UPrrdzpG+dMC1tLf%9^jgy!CC5{vt;oz+Yn$(c0?(oMUJ*Rl z>x*7YWay6$gK{xn=BG*jT=bol{68Hin2C zbDU6ef$8hqf3VVtT&a@gb8fN&M^-^vmS@H5c;xxwDc4L97A;fZUo-tn+IKJTFB!6Q z2rgHSyk;c$t{HjHNI*Y~JZ}^(=Z(4uJr?@IKaE>64)B_Be>+0ppQ|63D2Z<;eGNYa z#e%6lsV_-FD=`#45Mb|HRd9FkDz?}7f|#=e!!@!#9Nzokh40{!;D*4L+Kdni zzMR);cOY-$ek<&?O$cUi536KvbvMxTWd2MjtnG+xhb1#)g)5MSB?rY5;L#B1R4{$i zcKxtD^Ujb;JjaE6#=W$-#lZZ`hxy&l{3twJbnH4XKWE;GVBoKt&bl{e2DBg4eb${h zoEd;!M-Su*@(@fkw`tyi8iyjt_U1O$YjW75rw7ebfkp3)`tQ9zT4;X;_cghdnDdK% zGfdbyz2vUWc-y{TOu-`&S0lf~fQFIg)n4!Lp8TC&-}OS6*^y9271JanaSOI#3j|lt zTh8V=GCv3JM<2PCQMans3%!8$J&|L9{1)>dbyct1DEu~%S>fhV=_&eyx&N^IoE*&( zu0UQN5a5Rb;ENMCZle>H@yXmp=gKoXJa-0gu>w7&$1t}aeD}f5yl5L`Wf=8_p9fQ> zi?t})qPS$;d%6bv2hhV^vAJy6z4gcpmS8~_{w6b$?=+AHUl|7wWKKeP7xvyNT?}*o zAh~#0d>Upey*Kq{LS4dQpoIC9oe8gpY(6X&pSe|7!EySE;K^R!qDwm6vRVvSnXjzV zEvpnp{+LgGX5;J#>+X2EnDCso*X|&RWxXElC5e}ZT(Bn-p3D3sOvhnR{-VvLZE-oP z*G-&--#=vg5IaOW8k4^i&AbAH+uPW*KFqcg?kJ-6vS+E3|beLjm)$#Xamzt4geuM z7brX&6jaP*Rse+$HbF(VG59m)*OAL8icdhg{aWR|4PrGb++aZ~a(0(t?=MZaHI0Tn zivc6^m37@tc1}P)aP?dE6Rp_;5wp1We=*VpKlT0uu@KzechRo6Y#g#-Ph8#@`UReq zlgII5#5dOnFTN`mT-^I}M(E#$d_4r0*M@$^VgIwCUkok66u4VOuyNSNVaVAy>>tB& zbIMhSljP;lI2ZT6tT(ThQD8L${u}NQ{2Oxfr<5B={(?6(8;5Pdtqe*N{@fBRzX3zC(w0RO&q9wH=>^^zF|=Li&@Cf>1_zvsptx zw@2*M9eL7GYF@|^hgiUrikWp{6%6{=N%B?GRn4NEBo+g!FdtSya1KRJjpr+H<#0O~ zL+PkA$+t#C4H0;HjG`6e@t@{>CwaOxdU4aWu)W*pZ86Zoe6@Y4)dGdZ*b3bu_j_6) zY=(3xDEKqy2GqirTb2*}1p6a2_X5fN4O;zA13$zKE7_QbkavM_nUEZb#=dOeI|I?! zv6-O=f$&#kTyM#iYIza+?hPZZ9*N7x`)}Q!nQIRF`Y?ds9KL)EF1J*k%|Yetsu!x* zNe5e|Tric>D;D$LB1xO~+{(u)qvo|3RGj(JP~m?u8{!5%VeKycy0+Pt(JK#=Hj87x z%6x6JOEEKKx5=N`<7>uAYZkTjLny!ImP;-ls9tr*4Tp&HVfbh(xqJxPMnB~eGRJN9VdqbVOyIUGEZKMk=FT>Q1EQgwrBXeA!eQ-O2QkE z)Kf)KQUaV%PY9aL@%KQ?oFj!pnb-uDitX8~gTL1aI`ob1f%?z!`K~5+i)^-c_bU9U z`c2ddisC&`cl(0Pmmv0C<&H9Gh3PTu-PmGd3mNt#xGV;Y%tsj!Bf}Bv3`+R=HtYw$ zgLnIkD}50~FBh zfr@d}Ru=Ai?>iBHCjK_6wxak@y6)tBtb1gXBz;AAO$P*C;Sh=xZdYLuiuB z;Xvj`PZGmJXsoa`$4E-V=-IkEfx{H&J2S$#g8xGp`4)iRz2Z6zMe!lM+r83tyYt#` zERuMp1~E2i%B(t$+v{J8LKf^X9UeU z64+gV-oJ}5PMxywnWEpS)wK^gWZCKI~E|9Pkb>HX)AXWFR0=ltQF;1Pb zP@UcE9o0@zROfbkKc7@*zVd!|c--&C#Qjb&PMxx(`kkWUes>7uTfbX`B>e6jRD^TO zP++x}By+pVe%b^X{LYbizhg$i?kR6xz57^hBI=ybKrq9{6@Gs|$SV8p!Om~UCfCUmWLR6~>Y1m0Dk`w0=o zsZ*BJ+9@htyXzsJ>ZGrGQIs{y%`6X^wR4@CW^(qEzb*?(>GD4j%AL@Q?-W}BW3F8R z3%^7fW1JMq5a7$m6M~j@gh1#rlOqHLO4C{@_9HF3_|84((m(3-_dLVryXxltL)q-~ zdydDS@h3%2uP9mgI!P3T`+?ZDF8IwH;pG$kD~CPIBVivN_UbUx2TgBS$@)p*Nyc*E1)~K730(?OX`ZFqT(x#+mq`0 zeaG6#t=1>1L2tD_RX}gG6yww>OKcN-)R>Bj?}9%O@?*8TNz}=p`l@QsJ@>CEpo6Mn zoH}Jm?c5X<@7z95s_XGRYbWZSimQ7%u1+ydowB5=Q&e2tiI5+!U8L^jxVk^b)hWiQ zyGdA5)hQ~j?(?L&E1VzOIVG`uC zcG8VrF3R{O+j)E3fG2iN;#HDgitg;JJr;2f+@d{}?~$KbF7GVMC?xmR(kNHOdxvH5 z-a#===8wXX+9-;OH_C7<$i!@Ls;tjQqgZv?C{~>|N>ZJ&q&AA8;*Ii9Qr+KWRYlbO zB5s2N70_^1jH{ipP+hG#u%f8W&4GJl?NW!1J4XYwCf`RVt6IC^3TW*Vpts#I6E7+8V%2mstieTC(0y^q3xx7o2`UF5Uw%W)Uw z-mtM4urgm+54LyTqP3N*FksOVZ`fSc;h7H6jl0EwmHEng6CQim8+V4%=|yZG38h`) z{Yy^;@D>qw)u5p?RRIkp z#W;1!lIm=ViaXmtJRyiR<_Yq^Ktkz7?HjaqFDan4Q;bumEUC3qRJ?X~cy(d>l9BG7 zQ`+!PCl}(XiQ1bm?=eRifz)d6JCy!$}|?HN6@OlsE|_j)8MCU!!Sn8%?}{ zKr{vA;%{ayN?ZHg9%AJra}n27Xl31KzF#+D=6r}oMSCOZ*Nq6+b)&g{-H4f7Hm5kb zg|Jk-g=p5%-zo$hca3f#2F&&O&wn5kJgPW28_%X`f#RgE8JXs1;&$2ekeL&xd#>)RPY~3@+~r#c4Q6) znZE}nvAYLu#h!{1aSz<88-Za8>~eC1ks71qKL}$9`mkD0E)>PrCESyXJ(@&y2JbY0 zu!Y+zQSbs6u{UN>NHOvmLMwNQ=S6!Zn2TeA#mwg-?e7!`*gHk*6L17((kHx`EtT9U zcJ<~Ax((r54hJ%CD-t+c$$R^h2wS!5Me`h@z<@af6yplsLl{#B07bGhE@;Tos0!>WG=H<7NQYasr@IhQE1&E zw1uI?To+pRA?-tpK&{YXW+JpK)&Ce;&x!2R&{9-9w93#8vdZzF88MWlqlEJ1d@*i$ z?s~pIQi;Q^a^ErIyWCGUC?&%a7bYz8Y}|s) z7G{KpFk`!-Dn!OlxvQ`hCb%lUmPh6wV{Pyr&s=#gxPtGeAma-2Ah#kvXkM}zFPVQa z<6lM!fOnarpP4FEtw#Ai$bHXZ-T;BP{HN#|&JynAer7Iir~k}x!p_an`NQ#`E;#%P zoJBV=_#yjPj@LJH+jGp`p1T8|$ekEm9o!!fzCZY~i13$1KNk`HxoEW^yxQDv1aCGG z_DanOqKA7Kr~VdI*_gYJTd@CG^e%Q=Ygb%ITSBiX*@EX^!GE(gd?kBh?o96MTZ&Q; zcQv-V02CQIe^L?V52EW`ZmIe_`_~*Uf5kag^5!=78m-Hn&vUUZ4_-3%xue%C2~#EP z+-ZpRZ)jMJtpypyy;g}04j`0lA2 zDc*^+S$61L`w*9__}*%V6A)P^oQ(bmedfvUGYH?${yhuK-?RVV%X*cr6Y@;xFyFVY z@x2ck+v#BIM%#xemGN=%T>M#>J&&7qY1*7QNN~eYu!F{`xud)Z%(FK}lZB3tAxeAZ zX4yTFF0&GuC36;Ivt(epRiHZIQ6T3Y3Ee|t2y(Y>WzdqZ;dbthM+tDU#mFwT8hj(* zNcsCn&E2ZaN2A`Oxl0_aaM&WY!lLX&TK(W6oVkgN>$2CQSuDHf9UC;i&NhY+xE|QF zdw|0En&~h2QMce=9N(v-kLf6=;pi3*z;;mW6)nA-#tBmW=m9LHVn#tsBmmicL9gcBWJmh+_o7H<|nHrIlyS1gCn2pm|_dr@p*d;Ln^bnS2(q1E1gUW)V4D_lW;Y z<}ubt#@ZPu&y3mHT(ei9V!^8HEw;IC$=<|M_mV%$%(oBQ^u@5ym&|zeYxZKk;d?=A(l1F~@Q1rKtHM!qN)ZZoA{pm}>l~{$+k9wq{G8pn|&yRgbb+q1m%t|9;`m z?N$UmMuPOK?BDoK(wF(|9O!?_pTj+$wp3s>2MS}6$!9J?#}pLtCGwZEYdF9>#~!dU zcr(8V7w!F&dMA^ATBu*nZpzy0gfrf@g;lbX0!^v;h8izOESXk4I4|Y z^xES=j|B$Ax@X2SFGqlVQ~QIUIbE9sr;GFfDAjU}p+s(#=3-xJoEB3#(u%h0!H*4L zs!fG)GlV68wi?lBkABxAHA%NX#`EV4> z+AlXlax>;7$rg97$kj~Cn`4%RC zK}Xu)Fb@kgW4K)pm`eNxZD6I8VGnB1VmJOBG)Vp)=>k>@h?1}U8%y2_5?U=_5H5)I zSsR(LG5eN{%D1xjaM*M|bM~ub#ez`KqBZ!J;xsW_u4bDjrdZn}6^Da(b@ndO-Ie__ z=V{wzo<Wx1z9oAOH(sh3n~w@JJ6_FWghN_r2L=z$SpAX}_%i$N zZ0`5k8s?X;u`L*md4AuduAixVgLK^0-|R%_I`Ow^(civM1n7mL4SX*h7T!>F6HnK; zsrYtouDiYX4&F>4|BmAOn15gKqs)J__%WORSn+MV9c|3d93@2<3jU*hjX%FW4V4HU z&OXmNJ)eDvbqdx6U(%^wFz?e7-!~r^srh-uS5ohl#mkFHwW1iMtVAjA5O8D3rV?hq zU;1GwuOF6vRw`^8%3kHja8da!T>X5m=|*lV$KFNx&z$_GHc3^`>=!_PZoV?K&hz00 zZtP)5XU(2M!_PKd0o}HyW{l((<@rstqB7|>!_$z5_l?=zX;Q*}6>^)xE;x6Zx!gpI z5WXDA=H6Onr8EpnTE;!}Uzo-GiXWV*={qA}GM!+uiOpkgvB(uHW(D`HZ8twjnSU}1 z(I8?4^UT|%VLzQ~XLXpDCC~K-N|a057m6rY(Z&*h2b0AF!yN5D?AtT!_vQT7wmt^abk)dI+>aa+k63mgmq-;Emg0dw|QC z=4!ri`w$P9!7kj=FS(kuv}`5cnZ2v*AzmIYdjXeP(oJg^n;WJpag_Qd`uZkJJbA+U zx4|OjE-Jc|Z}=`Qx`NQv;ffHK%Sx8w2pb4v&uW^Ah;p{ULudnD|5p4>F|M`ModTcH ziEO~P`d-XG%kuwNbQS~ZEQ8y%>fjD@521U^%TeiIdC9wMVM|=olf_{*&$f zOv#I+Kd<=7%zRzD5p9-4kLcrH%SI9&FXN=#6 z2{6v2{S*rm-VSDt&`F1kH;sY^c_8+L;BB2Nc``QAD51oxHE7pUx~tWgN&>ni`*>F1 z53(N;{xJK6!0cLfdtYDuiVK3M%qEsz;ycm1pMi>;ah4rM&&uM>tZ^6yZ`F*X3@3!= zP;@&C4SLulq$W*AYB~oCOmKgD8D_4*Wy+6(?m24mXIhE+Ci$8vIN7Zl)t$umGk&`i zZ?sHN7sVY`HzC5>T+p&D{C%I1bfH{$7_xCn51&EzZsAFY?p>m<2NQ z@qnf#Jy5S6J(23klPxM&1ihvqXWG#U9F2{j!Ea{)JlcybxQVdeWk!0&QG_>1pq6#s-Gd&!KYqxINM3P!vq$ zngK$^GYby+rQB%4Gmexz%%iXoKR3qt0o30qy_ppGX0FxWoVzWj1-&h|ATe+#B@Z)d zJsQeKW0{^a8xXnC$_nF&2m|&8-QEiVw*=>EY#tDOJesM={*bc&)mZtS60E|BBD|iT zza)>`wfX;G0ep&Ms&zH5iWI(Q*6R?^A5w)>)gxW#t0sP!GaZCP~fVmxth_z)ZcRq z{{1Dmkpkj+td-Z6!xGagP9*-h3Cj)nRV>U+#H;Q zpq5{ryE(_qH*=q`TA$>;$SLhb`K$6oT$jIDt`Fol;F=9K3$Aw zEaLU~qK$IhSoAioz!#lkn17DB5ZC#^8uJ%{|6(2zc$4`^;E!b+mq|Qa1h*u-B6pnx#C5s51%4;DD$o2? z`PU>eUdyAg0Ix1NvneCx%%q;f_ymMuZjTY}gaY9XN${N$uy&;^!E2 z2+tsYFevTlXlrg}2)49n{N=&ru( zJHBimwC@zo>TERKsZ;Tc`I3a6hh)O6fO4|t6lp7&Wp$;RY{(qW2Vsb%NMawN)o8jt zO>Nv55UekGuLPGHOJ6Ppo87MR&uQivBdJN6Y%>-*pUgDkN6{Rb@xlOr<=yOf1yx!wO)yHz zk1w^bXO!-MJv(%F`I$REpeX72F@GNyT#~EUdmtAwEjC4tl&KNsnR#$toUxq4OsaI-YMJ01(3YZ$sb3&Kc)rvqTWZGI-gZ` zSsB51%C@lg-BR`?*3pA)=_0N$;ua&9%kzVai6fklgKF+4tZhi% zrVS@IZO+c-2IB4_d%sMwp1_S$ekPs+Jk7h0s$gsOUy^?XzV$`AM@yfV>+_|rl>+@5 zA5lQohxo<}(c4PD7WnqECu2o62Z~mnA-*bm4;S6mmu`l~p@=*?Lw>GkSb{)dKH;rD zb>l+SxI79~xKOeT6ENZeh}|E3a$ahy$COniCs_`UrO7lD^gu?er7~5Q7Ggw`0lw=1_!(E zQFH?qS_cPvAe2=2LNBB(PtVhzxmi^1j_BQ&`>HO;VqsQ0e}}>Rf!RQYQ z5BLA{JrsZDaEUr9$~wXF(R7y+@aKe+ax=<x(ikCg@YIF;(~;~3e#~Q-i?edbKLtrj zMJ@@tfXyePI@q?^b}yTqdrEdXlSV%?8$G2!GmQ_f%r3RoUz)uEjeubhD^%k-B|~%= zmx!{Ny_%mY}TYg#gYYxfxu|t{=Y|3xtW~;6F zZPd6pxSd<7Zx3GP2LYumbVQ0Gs9n|f5?Nt%ff3zwBr5YW4!z$0xeg;Oap-z#n8tx< z+KG6hA~=y-bA#DuU^_Exc`erL*}I}FM+hZ%yPt5(c2c zXg3P8?REl^Y&UePBA*jRly%Kqj%hbNUiVTS5|a6cJe=##z}cp=5(k z4PiE+9zkX;*Jy6xXM3?139FLQ@KOoZBPZo$aOSbQ6$eXaug&5-vfw-(*NFqT^LOz9 zJj!$~2zP{RY3^ylwJ)3dzT6X>KRDOzB$$!V^|^d0Iarim;#8WUs!X3rqT_%GPy`hQ zGl(p8zf(ZTx)%P-+KsG}JafZ7?qK#pJCH5RKEZlE!4DW$;%m2fjxr9WZ4nOTv7XIl%ipmgn*)a^9Wrfo)|X=cpEpM}|**lIUrF%(n=H)lT} z^a0PON8iT>7}a=yfo(qA^712Z5}`h0UY1Jm9o3_cli3^_)jH7Yg6l({nf|D_&ibq_ zE#IAcF2|sFF83vunv=y7$b2izxS0ti9*;lAW4HOV;8Hin!xI7iHH#g9m9hhnARj{j zyd(EAE^6K5UuPS4$j!_K_h%o;;)=3`t&q!=WS^A1_Td|a_wcS+_t*_|_NAbmtNR~kRYt_}cS;6PA<-)7MXVK+h!A7lskmK&QsleshoiH8HA9}XT1bZ#Bj zlQD;jA_)=hyLumAPzCk&>@6I1YUtjT!IJz79Cbbj&ce1Wv?A84l&zeGtN|8&!~PD( zv3KP5up>0HZjYPTbOe|lkbt*X z=t+c@+FaU6cQDAXe!c}9J1_=ZQdb*H{&Nl%S=|3~8S$Xw^UGUt%}& zQGgwD=O*D5Lde}K%kXFmm$lf0h|A~ZLhi{c{F#@9p59!_a~U_o?{V1> zyg_Td5&VNMIV~%Ch_4YnV4gI9o;0uHrK8ajN@k9*%dPbd`3J-Ra_?vJQ9x$1zp+1a zs&K^a@m8>$h-=&mMR#3VjSLFDB#)_*28~89D*1@W=$SA188@=n1}lkW!MlMZ-VJW$ z_PVFc^G4w3&8K_^Ny_!Uv@j=+*D)rwT;{)$8yoJ?7Z2Ei#XcGOY*OwVG*xUbVpBA{AUwe4Lc(8=9Bv<1NZRC|rQ5++iUSAMuU`b2eOy5*yxNn2Q!&@BUo+_* zS4i5)fl~=Ag9m0DyNlP$tzc(HNH%0nX9&d5Hy+7uNFsMMs(U2W;Af7Px`(hpxUV`$ z*36SUhI7ts)D~j<$1J#qe#%D&B{D$F)!t+-c7I_Q%&xKH#Twr6jKjjxb2j6-EZ*-@ zy(#kef_O&YXFZN$R%sYF)?lp+8S5Y|KeGf~G=(K++mTRP#BP|Lb~^=L zbP7b42Xk>ZiZ69!Z|8_~yGpL2!ScUD5P{a-={0Q~NVkp~i zEt1ycuOW%=M|tID@x9Xfps@S6{`g1$M^2MwDx{Ou)he`8)e$V?5v0Q2wCHE$;k51` z#H%{NSkP4jM@&I-3W=+@oE1I-rFM&o%iD_aA@8i>LKQbyTDI2(JkN=64$I=ymYJJlSHK(TAFKES{AC zAKvT32@gngo|VDTO5kY<#t{?WNfGS!U7WqtRt=7OJji{!5U}ln zWf=1EXEgg9@}7ei^2BXKsx*sbl4j`~&XTW2;JrunjN4M?qpDgA-F{@MW{vvxL z=jrjEXT_eiQ!yiu9g}eN)3$O-zExQP3oGa0?q}{3oifcBnxBJ-|+KtoV68g=i{36W*Sahw#_NaCNs79 zW}e69J7~h6rK2EKYEh3Pv$NSY-(@-iWjtL_6;8 z#sz1(J;;jrvtanyt@5UF2u_Inkhy%DLYS50H1M8whL#dl6bgickf3Sr7dgC%w1>_5 zK0q;;+W50(zX5IUSO>2%O#gvwqCL%1- z+s8LZOWrTn64_$7(l}9LMO3vDg;o?%)lL*LL=--%r=sF5>x5JVdx%~%tq@l^Vrkv* zk0|!=e9g1-Vr4L=4q{z6F%P&HxTvTGkLZJ%qGf!I<+kG2br~((VF=sV_5HRT?w58L z70kqTmEe*5U4f<^GA|fSy=%@Z*3`d?7lxXu39r*stQ7Snjn%@n=21UnbF<5X*YK4f zf?rZ)&9-?axGTWcIA9(!&lqB!VG#uLf_Yak@A6m!U^cNxf;o@d=D;IGlbnTNO~@Q6 zqU2l`J|a1r!cXM-Wq5ZfDef-CdlGZYgJorJlmXW6H)EC#W@En1yL=Ssxq#OPi@z<# z)sjRtwZx->n%Cy72u4+*)vM;^Yu3&S=DnTM%)4+{gQo7s%RV4@0y2e!LIvZ+nk}OH zD|QfH;UN*Izs;V@JKc}W4ZKT}Tb0L!s4vTPL2w<*rvmJ)o>6=|Robo>g!Jkw3NHvQ zwMDs9Uw2ssc4B;m%u^y;R(N&}YBs|v=LCyb>P5j7;6(=KgBe>;-iB?489fl%Yw~t-sqjzT$k3x`*8jap#G~OG={UGlmmB_p(1a@(Awy2EC__lZ~ zx|eF4(XoZ^`D`)U@itul=5JZ9{elA;ObTp ze9RBs+6j~5e}&S1T>M`Y+Lz67s?dXf1qtL+@Smi`lc-!s{=t%oro{f5e$ofXD-XL^ zeHrYmVK#3fWyaEe54L-M&MPjl4|A;3h<2m+Hma&kS7`3qUn+S?b_vdVV#6%SE@w+E z2Yb?UI*V*R*l*EMJ?FwKUL(h6fbbHl^_)!j6sXWQVU`mPL~pb#$0LcPYy|CFv*+Nu zH+Rm9XV=i!HCVOE*W5;gWky6`9fq8^!9*I4Vq$V`K@lM*mTlz_0XZ=Q%)SK2ei`1V zYFm6O<>|<|K*v7$n*H4b#Ow$+$6Igghl)z_HI*hPX~FIzmkav<#a(iN2}dHyjR;BK z<SL%ABGdnR$p_FxUnK=LZ6+yi8qU-u_TbWZWTO~ zebmk(AI-kZjF++BTu0dr+12s&Ac(|E*TOyu~|>~pKOG1cE2Ld zER|C2z%Y8Ai=4Q=pSv=Tt5WDE($)x73vjoX4oS=Lav3h~^8x1soI-TI6&NR;&V#y0 z$SWy%B`KR2$`iC`Jduenrc)+XbtzL;pbpz>r0nhDUgv@+ySPUg#@oV<&xO^?Wa92$9gjHvmQsMl|JEWu79IXxzhfhy(;efTw~ z_mr@a;`l#iJ&u*Jj~?W`9ez$3Q?r5g6_q>eLiQcl364JJ?%X{#%rYct{g6 z(|pBJ$m7mkA!b)W`lXsM@`v`zuzAwc;&wfR`8)Pg6pw`j}# z4sF}x&c6yv0PXkXCI>6>UqaRl9bmKOC4!eDk(y&Sgix5C!`U>ii_^T5{Yw!oYdyI0A^=4i_c+bR+}AA;sPOUWug^hMStU(J7%x5*!ai;Fbr znZe#)$~77*uCHdlh%45BkLEe5R2SFO{nR&nVYg_WmZo|CereX=P8SDWDc>W4#;3n0m~RY%1!e1pw>!Q(cF=Uvrv7#EAI)5thJ zVl?0RI3g(h8EfzpkCv;ptHp5MI`L@ETEzo3cMQ%{nZ_qC6OXnjU_;{CIyfwVb3r%< zc<#S&Nq*!6)~wijKOAVO0?`&pxVQk83Sy)=WfY2yZ?OdxSiKE)?xCSARf^%b?Vmrh zR_M9$v9wG{B_AuG^$3dLyr9e+DozRtD+ceE>C4lGFs^n$ns;ri2$DRBhAky7f`Smu zBSSFn!n$ZCXxl@EX0l=#fH+QM`*CG;=qMevE5R~Yr3=}#n26#U?EaaCSx8&#O<-dZ zN%b!2)YEuSQ8%yPNwQu_QO3fR@tf1_dl)F`HVrpSNBDWK`G+s-ZUa!(Jx6F+_x-~t zRv?471(=jq1n@DdD3?ji^$Hgs%_fy6Ne{B?doVWX_z)Rkclb@}u9^pg6MG7RKh|JB z=L}5IvRBBasS#+BE3hU7)HQfZUU1jr`7Gc^a3L&Wi3D0 zvFGrxW{R1U;TIZ*@6X5i2mYFWe|-wEr!1Gfg3GgaW(nSjM-f1(4nFc{&l0kx9jryd zUZ@pLHHy5$qE}`=#ojWDRshXYFE@gOqFXy@EI(?nL23XU&q}Noar4Z)3%Gd=-cf!G z7+_EM=_DlEX|fBF6_J$(0K~$S(P9Mq?PpV3FAM1UFy7*}#I|byv8F7st*OByIS`h| z$|{?lwan39vp~ejMoE4(rG5MStcn#u``)c*RkRp!X!ovrwrRynpPt!Fo0eGh->vnG zOd4Xhp*vvi(Jhr}=nVMojI*+xgLGzANfdF0|r&AXDzhxw*N>bJ*Gu3wS^JlX{9ZBvPI z*QP8%!h2%mD_{H!9;D=&4wYO1@unELwHK?FDjnX%g0zY(7M2}53R_iWIg`mEuFb-c zn9k>B$!8T=Gn_>v`BF>f^A~;uOb25Nw!75B7EFRf(bjboZC$5GdA;j&fiyRmLHp+e z_sf*!XW{VxX07W0WT^h87!lQ*&PUUyWuo8KjvBd;nSAyy6nFkAg@T!$V)Hw-DDojQ zNrAV9T@u}3=G_=yMIY_`ag!10W+wS2LAk3An(3fH`(a~&U!XVypgs(%;DYu}*k;Z! zo`h^JW8_#h0(cV5d)*L^kJ%1~BP)}e(LXaJDg7fTg+sHx*u*NuDrJ{nT2_=_i|zuy z@HgvzUu*$3L{S_talp2aYpBH#W{uPh7U;GM%(Y8TwN%f8kaLhM=<&=(tXHeq zoCx#3F@vo*Q*5pijS1_u9h9`*Dj`wpwdyR^>)adG>y5>$xb++z&DN@$Sg%_TXT2W1 z)p{iI)>FV*FT%ij5eC*{8NKx)0M;X!w_XZhtruZnJq6Tyu;1+>0$})>OTm(`Wf~%1 z47(}_lUZ}HbznywrMCa zJVt*JoG^T0*bWwwhQrp;)f=`X@`hKy8a~3n@DT=vXBoZWBLIdcnKyh2U=1H(V0Z=8 z@ZmlpfB;M#0WhxuHf$pRW{d!59&5xI5cYo#+y9MOtXFK#6pab%6^8BELeg;9I=Xtp zmPFoq3Rvq!7+5dDzd$EWB7~bnr8n$T&30p-l zY?Z@@Z5l$tHVt7dzU}Yzhiztq_lUZ}HbznywrMCaJiZt&f)j=>4BJ*h(s0;1x_ZNw zMBeZUSi?sc7(T+l@GPS@d<4MoB=d$(0j%L83=FS;8b0hG0tg^%BLHEmfDPLSK-flr z8qfVTl@RuS4%`2YS*%xVekB?c)+-F#V}+#Quyu6xhAoM_^%Styi!iWWgn{)~MsK|c zfb~e`t(O8=>qQt?PXVkr$N zA9#WxhjdFv`*ts7xr-3SBgvW(uk5diCw z%v(1Fu-1(*u&x4X-SANnKmf5B0fpM6hL>{q@Jd5Sc%>mCpc;Rd&HwX(9{;iN-LM!l^ur2 z1!CAVQVQX$MLYwyE<1F|^U|ePF_ux~&a+p4+`Cj@D>qbPv-)fWBFscAt zb9d?d4BU9)*4`srS`fC3tn@6YbUuH|T--g&GV_j-#%UqQvSmfeRm;({i1{*K#4@ap zkR%9y#X@E)!;5gW3%53tEvnhlhPeQDyrj+)Ao2kmD-D4g;o|UE;b1$829^>ohEPsJ z*ivWA2w8xsfAt|E@f~YU1jM;L3K&^^5UxbX7xuYF2uZ_zuA{5B&n1x$c?E39M;L^B zgn>s?fyak@1i)A%^C6!CFtA~a2;%`_5b#q)00H#55r95d0o&(B01OoY&OCZGiy^G> zeQx3E!~euA*2C(9FeR*4*kP{{l7>5MM^|r$O(JhS1+4WV46GMnU_F-6TQ34&J(79r zr2y7?5eC*%K&=P+-7X>khOfDlcGzhMU43v$Er;*0m4p4HiXuW+A5u81#VdfSclF_I z?-6y)hdM_jJ~nOGrlG{}SbY$#gy9RrcCe5%9JY?G-moQ+H@pJY@DT=vk1#Mi%jgXs z0Wdttyx~&-YxoEQ!z-YM5BCuP1i1R(0j@rH(O6K50EBG>sPWuiGXpID=dk_Xn8kWn zeGrWa>lKFW*+SBA*gCp;!7q;f)j=>4BOd4(s0;1x_ZNwMBeZUSi?sc7(T+l@GPS@d<4MoB=d$(0j%L83=FS; z8a_N-1Q0;jMgYQA0X1q2K-fkY7qHfdcS6|zIc)zoX0cwec|tTMtXCMePYX%IVe9DX z4OnUKZ7hzz%2m|Y}jNWV0Kzr`5Vi`~u#EtO zZ3L+C++R}(VgKi_{ok0ydRR0RjS1@&hV8LJ(s0;1x_ZNwMBaJ|SnEX?STDlBdMu;2 zUIf5;B=gow0j%{R46LVsS`T46T|@v3m$;OMZ5l$tRuK$axSEE-lRo<_mu^&cweb&9FCFrfEK%FOpS0S>|PkPON6B1sC9JpMlFfF z-4(EQk1()%gn`{zMsN2BfZa*v?VbWyyGIx_p#p06@LCZ-08twOh*||~)J6cJHUgXt zoDCtY@lh)VC^jDmQ^Ej+f%l=1G#q%2uHL{SkvD(>)&LO(28b{)0L$nN5CJd%$-Dtl z0Be8<0|O|a20-9#6%hc#R#-UK)i!xHo`#UXQv?G~Ieg%yAtdn95RvgrXB2@S=}TKq zyfa!(Bw4|7;_kv(&vK%$yX8bu`{l$4@GFEWEp0hb#jwq45p$8Q?&U;^^vj8R1Mtg< z0@&q5i_qmnkHB(bgoriQIH`1<%ZXan*m9zyuX8zZBnye<#FKIL%ZZXHtA>&tEhiG8 z%ZU*}mJ`zuvYfcTaL~n+!!IYMA$B}IWnyE~-~s>iaK zWu<_mdYmKCNcB0@P6^*i{iSF)v*9-@f~tvfISSvn_{|EfJ5w3QV>xzkMXs9YQb!$S zQ^^)9WR#BrQ478eL@g(KEhlqRmixs^h90t>k~tpBQR2$eV9EG?v;G>d%<=rs%JAA5 z+Zyjph^Iksn3+5((@YxI0kTEU<)b+;OCS-t7Fxgqz@WR0FcCnWd`PbZ4;&4Lw~JP+ z?_+nOOQLgb7Kx1m7!x`IQf;ejG2XSetw_X4$#|OR zd?GmRIOiR2))P<49*d`m@DRk-amVpu$XahaDZh`W2GtkDQ$juCsd4Iaz5&eK!gv}z zPMmkrBwj+PyIRxoSPmagqsKY_oir)6#hfz7D1k&Rh$m`6JXtNtc#4%w{EcXgt|`jVA&=o-Cm86k!lg5eD%@xA5^K zS~Z?r67h6tBsLCYgK#-9E^Y|$+~09Q+0Mzh`DKIS(7pA=jj+e!COHm~wf?vfejhh! z<4{6(jYz0-91`UPaU&c)Zqj=DM3J2`GglcUV3OmI)lv{QQOVNA zp{Qh0+z5wv$lriH!pohdL7D#vuZ!<51by zMBJne1Si)MH_9H1o8&k|)_UVc`F-3psJ66$M@Lv^XoMdMIgsedePlJ`SW_hj5C zhmV`I-agS{PMNWcDdUjUl8l>J$%8m|m-LnZOJ z=?vJ%jQ|=qHech0fR7ssXxu~?#7%@j+|Vt2+=y0<8<#}f>=ucQ0~m*f1LMXapT;mE|UKt#hO5%=N0oXgP0P46lUmcf# zcU%jo<3<=bZiK-C7~R4|>aR5E>eL`gKqzNQ?VrR@n6Nsqy3CX*M*ZqV<*{$Q&enLXlG{^N%NR;0X1Zj5! z3H60D7%6=$Zjv`7b*axq1Hn>}5R04S9f2q>h#TSXag#RhP88WGGpb7Oq?0RCR!c$L zL?u&KuB&8G+z5wvp9RKv$+jtBo7x+qm(}pkLzw3a07u)V<31&m~A`}NDKrnp2`H_<0)-Q z{y;tPr0lVHO5PEWwcdDAejiT_sxOGAg!k zn|CK#%qg>~(pILdmSjA|N~ZBtSIK-lDTjCQ2218*BiRh~D|0-yHjP(?cw+hD@zfcx zk0${%o@~Cx69FGj7SMQ#Fo>rJ!#ix{(RdQA8c#0CJM2ho9KbjR0A?Y;78^jB$hVCE^Bf z6gLEH+-Say8#1|ZsIvk#Zaju@<1vgI1#H|9uyJFPj2k8427oxgl__A{IONk@nG$9@ z4iQKlhZY@?h^MrHU`9Rhr0lVHN{&Nhtv8;O-^Wvf>I>p2p}zJwRF`_^;;`;gsede< zlD)muJsD5R;o~W-w@o>l_(@g#tq*J-}S6Z3sMSwQ0{!f;-vWaPoTP60cwBVgxsHp%-TCDC|_ z0Ip04k&PPyspHT|Qxb8LHV}-iCvKEI7B|Uph^+O-jq>}rX;6JZ+$7Z39*62u?_3#H zoGbN@#Z7V?lDa43Mmc=kr1kcR7IVt1s|GE{V9g zG!h#JFb*vT#*IThjd5r-Io!OCKx~=b z_i>Xp4kgqV#7#nd?Qy6s^|>f+mP-9&ag!W}M0ql9l*7kOT5q2yvQuU(qXZ1KAa3l= zWve9_H?fkX4GmGreB3C9cjX34=3)TO+-PNv$8t1Y8Ru_k>v-I(1nlER06Txve2p9C z`?#@y#!ZCb{7uQogZY~RcK$}d&fjd3^EV~2^EVH0T@HX7hkTmra>DG^oF`x2@Da7Ej4>NR%hz zNjZExrS-Sjp1Hp{Qg&o|MD8c!MQ#v5{f7YJxPNdb^VJna^VjRRbl6M7pr z1QO$rd$9SZN+P`Drah^Dq#$nMPwJK3#tj`e`J|q#X>pT_27=X6fSBVZpNEU`q~j`w zcign+;fW$UWyUhf2#|bIZ?z;HH&!zBrMgPy9alNLFEv;)=Y;U4Mk{kXmZR~?;J8#0 zcicMxd&d<(9oOco;}YC8wh+F z1Hmiga1$#6iGjd5bRR)@hfaG^e^osWt?V&}PClt8YXc5FL<$gd=;ZToQJ!>Y72219g6JFM6Wsb*kG+r4Tno8mh zJp!?!O9eU;G;FZ~4eTwbTdnEN=`Y`i_z6jq0DJlx*W@cr&@_TMY z&*-COd=!`aFYZN>FSg=cxwS~*`yoClEm|zu8K&`qIY}h# zD{&{z00=T;@VZ?vW^8VD7>xZR(&02zwjJNWL-W2a#{}S>gY)AE$QQ)`kymWCh_qG` z&8^zzXX6toc;%d|kV7QQq;etvZ^TCcjwVS1PU2Z$F-!yigLCxoi*%oa^V^{t4oBUV zz@oe9x$eD9&B;6)k;m>+U#T3(?*YEHULMDIfEf5y$BS5%Q)Wq%L;$K{0i3Idszd+^ z90B}>4%)Xx{uGemrAh*j1^_V|0YMl8OgexP6vr_U01V!}{Jn|>0AGoKoN)k@q7$+h zmO2hd!)DBa*XSd1$oo!+hMhWUk901wo71s!Z2lM#zJ)EZWLEx-j5~lP*r_Ke8DTCL zJ;hEv(FNg?2BZsBlBSUj_hPnqt4kw0h-JGpvQgEWNiFj5oks$AfmFgWUxY7SinT#? zm!(2;_#{4Ih}}kB=;{*vwNm_JBQoA;Q4H6|inR zokepUX9U2F1<*pnk7E!VIR;4^!J<;0S`Km(vLgqH5z#>`>x@@fl|E?SKJtNxL+u9y zc&=)RnI~9&w7j*9Ed2N%4o_vamK%qsMu0!SK-u)PgVr+M1l{C=9eYS+Ytixe0MPN$ z&3E2GAAYd|=cZDcKj>f~0DsVd0QR5*i_n7(JOZ|h5Vp#Hl1ky7eDqL(d~m3(6srKu z(gfwj?iAPZmM9H>=6vDjhYWl7l}L=`RWWZIIu*DY=@1a%-EzfU6c0u%%*1Gs4=*GI z%Mjk{Qt0c^+ovJ4nEKbOmpDU11p_DG(^V5Di}`}d`1<&S;QTB;-CGr0j?csL1CqJ$ zEe2n{<|yfnBEU&BABeQ3qzIaJK?S>vkn|x7@kv&2@n?xf;Nw!rcAp4*PdN9-*m^j= z*UisNxu2n)Akzy4>2(kaHFiG!%)gKYyD+Za<;Rhgfz~M+8K2Cx>Bo$8J5H1r6ONnc|Zk4X>M482+ z1l=nAN5N1Cmp?Y>HVpUY!$#$5MhBxR@mVWr6^9;Aw(-e4E6TY;J))!pO{9GM{$$5} zoNKwfYUa5QF&mdVHt5KYZ0)fR%A_9PFjj^*jmxt#)Z@}+U}ky+aoO6l|^Do!JnH={$P(2=KkOvNhbhJG%ONcT)M@ z{Z#+Id%6#iuI?(*WjJM-AP=QxJL0i<^? z%#_~!ZBk0_9>m6b^zLa0TZ;-A(Yv6N?9vkv-Lsb+mSI!VQg9uC>)3^!mkZl?xtLZ( z06c3TF#1(7o5aj8FG-deWgr2QaHYXs3i2a>B{Kcrpd+<~&bD1#QNlsUG&-$}(ufJ4 zkD~1bn#3Isy%L{X2{KZ-eNef5M(Ut75)+WH5))>*%d>r}d0mJ*V9@BZEB@>{5DJw_ zHKU1Hz?jTIkeQH$Mxhj$oZ_a*fA9tK*9gET^z6^7Y)O*^Eq6qnckCePJ_E&yQbeY3 zzpTFo3Ryr_#-opdvJO1=2$LLMv_f(a5{&jXN*FS{{m*YA>@Z%g!Q! zowTLWu_(V~E<@|J?}$Ggd9R;nLaV3oT5u2SwD{3mi&&QylxrKxm6vvNfZoSwK9BlB zmq$Q59}f_NPA|fEfEYOLzaySF;9Cz9V;5uJtIF_c#I6<22uT90Bif3RsVeFz~nt1CM(( z;)w$>k6W<5Zjb9<=y6vHae*;~D&cW4ncm}^EO;EHSdWvW^SB6bZUK)|m34ZYh)sH& za@18wC)x^5^Ej1hJ??50w!q_Vlvb$IKlSP|fOjB?ORcHRYlcHwujm5z4ESvo^) z0oK_$5;p51BVn)pG7?Hr-AH%~$O^pVFTz>dOWMd7ohVXB+Ju)VGrgqE4*0V}heYX| znGqh1)&ehaS{%D&u1gENWG%|&y+i=@63w?>Lcn{80@h0+47?=5z)PNrc;bMw4(Ca4 zdoQUq_o^uDmtGg*f{+&~8&r1g70LAdl9L6`q7*mxVp1H2b1x6L&I9FBm9;(2&b>se z2yi@>qpm_0kfrrYDwAys)4YvB6?oi7$dU(kTra9U_lk-HcG4z1PMHh(C1J5m=pv%g zS~&NzTD-^AuLb4W1`h9W0@%5i=o6 z*5e*R2@5>#uhI&&`#3w>kBS7#k~ZOS%3R=a!cyRIjn=}sm(}7uu6`{j*LrYxj}ySo zy(Hgy9P_=$DPTP=!f@^-WY*(ejd(Ek@<7bvHp@qG)9)|0*+YNzwh`w4Mu-cHDO3rM zi^=pJ=VZa-D8+i5B%Q}afO8A4vQCc^u}P1szmQI}txKB6sZ8r}-=VMt9#vGJ?=^&F7P;^N_bpMruR4}3m!))*5f4UJT3y9TfpN~Wt|=; zVv`=H9Ca1aiME2%JWgd=kGmR$E%3M-r4{P*xTr|5ENK%Sr_2Q&CoBaX*Jv&9IH$#X zT>V;5t~*gK?{NaC$7#OxI0D||6tEr_Vc>BQhO_;MCl16sZpO>r<7&})??q>!`;FHvTCNo=<7OXtjt@MyFac!|^E*e!EiTHqxsQ7-Q#0;rd0zV#9U z-b)m)UJ_y8B@qT*azn%u2VmZ5ybq92uxa<~@U`$Jsm0* z1MtBvV9K3tJas3`O+(J@Hj79({J#o!#8pSwmFsNyF=euSGB(Zj(MR6@7ACzjZPS_M z3px*#`%ygjCQ_}0ME%MqI@#6 zFAB{^-<0Pcj(i8eKO7OjJ{++KeK_I~csLRvv`I`$e0|g3%G7@J?a=ygBvzj2;rGwd zJb0iO^yw#V4C~uGX{$c{q^;xuIP>*5|K9S|PjzVcK^j6HmE`=_L3ed2eGs08fIEy} z1Xw?pwDa>rfT-KgEmjH~`8jjrelD;&Xb=*J`?gSU@ z9V!+B@TnYN;(ksz?&oVoWSXC^qfG1Pl8*fRRbi^b&x!PY9s%BemAPR*cXSQ;IqAHg zzYW0qxd7JBEkga=BjD!|!ut8YrE+%IsO{$tU5}q{5(!B^w|TTByg%}D=BuBVzQUCE z^E8C``QL?uOK44mgHLW`!$%szc4u-iiR=FY=GXubk(~y1I zJpYg!4(rIr20dqha_kBcjU|!W0Td&uQX+hA8AMeevi+qkfVok0?}4s#k3EYaY;Feo zC-)p0B8fsEJ#=zRtSh#8SlG%@w(>3*i@S8=R=c2^?e+#EfAA3G4;g{fhy(cCD;M4X zo(!L1xuk5ibh!u+O>$d9Nck|7w$EdttVHYDWt3bK7_?KDQMQSUrN({(3PdM!@q$bzF$G$a83prV|BlRRH+gR&jI$eRs{x6 zn}aUhZA+tczZ6ul9f5=5rZ8aBR&GFMBZ0{BOVAj3fGiI_1qpQLy2baZS3LInZ980c z`D1rqER8y5u*(*^|E-FQc@cC0Hs>+iOLsyccj}a@IUeZnDJKEanBJ9KkmmCttpd_y zbEL{M`^kxwQLW1$u&l4EwIv!OM731vL+x}Cu^yg6(uw*zJ$BP=YGJ%2)G&jB4A!;? zL!_~rz|PAJL5@V|u7Z3qYEj%%x-MIViu5YztzQarD9nB zP$gOa*^K7LTN;)rD3<2-HMFIvpGf!PnEHvvZB6+&(49|Gd2cv>?=k2&#*C95F&K9y zx0Xrim0}!PSaKP8sMDjuH#Aoh2EUk%zlq$SCb&F6zFZ418H>SHdxct(qz|yUNl8ge zT$1!xwIs!Jlai8{xFo6FD^fe|OBsB$?d7Bz_+#D^obT-2rnCvc0b}4{V~#-AlQ$vD zlF|A{5bKQX&w?{6zrC8R7Qx&9A8&60u2)r^kAK6-xhM0Ska->;0%3{?36O+9m?HOP z0t8Gzh5!K)AOWpFWKhx4CKYEfSDfpFibJ(j)K+cLpQu%=L#3##cCa|qR_pM8-*>IG z&pF@yZlcfge|mZNvi4eQuf6u#Ywf+yKKtygG(4ImM0YQBo>GxRF|4KSX_sVc`!IT_ z9!};C`+0rbQeVe5gvCJPRmcYy$LLMuO~{AJS8;R#7J(_i;e|={A4qkM7uefoBXaII z3Y&>tZ7!)1cvLg(c)P@Wq(h4QV1N{2p?>hzq`<0kKZDO+wB^o0ZA|+S^cy9`3IjEU z5cDzRrvQiK?RD?K-B}P{C|w;xivI>j%R<0lj_M5uFW@61IWS2r5{%fwBs!r3_K;IG zw*T$n0@FA;1M_<2>kLfC)`LLhBuX_1WZ(gks@S@uI;AQ}t~fwa6QV-#r#vu~%KJZsLtGV@p8iXv(WLhyZ!IwQtH?nE)5#rynXnN{tTX@e z!Nn;EgIo>F0m4#X2KT^DLuI{6s@DV4aRUM~cxxf0HV=x2cNJGkAr`d@-kKCx^()ZC z1Jgi-&+CBoz%)>SNzeoHA%NAuRJslwpGprDXhw#a4<%6T(to9ZUjBtUJkGtZc5j}?N7lG;U?I^%|L}4!3a0O7H$cRa0|3q)PD145T<`fxHbQd z{9VJ%NQVeF&zqcCRv#!Zh1;P7R`Vu-@}PkNlM@|EU^Q7PZJ=_92 zFx-Mt4Y$D6!!58i88Fqg(89ybK!w|JzYPcy~3%Aq25#c7-!p%U1 z8^H)S!4_@_jc^NeE!>_$nEoN*_7m}U4L2hlBHTQ0a%P3hK!GXT4kfUfHwje83=~K- z|MEi#tmaJumFst^a`$kX_}4Vw;lk~g>5sYvXY~hyB2)97fVDXplN0|O0 z;r3?ncMUfq9U|O3Z*pc?eW1V;ZifRmS14YRsUzA?; za0^^L+yYw*6*XQ^s^J#6dbkC)CIhA#_IL_60~KyxhHf5i1}fYLdboWPU^U#7u7%ro z!4csm*uu>~g&V;LH^CNe35{?IGz^BN*!;)G@?08z_|_W3hl3+G;I~Qwwjr#R$jQzx z%kbVkK%7%TkjG(QStmf06d=CFe})Vc42}eYCBZm#A;CCwVF0Wb={RN~5ds#0OA|Rs z7-IDLeGzV-!OJyUfvwQ^E@06zy%Jb4QR=*<)TrIY_4HYL985fJ5@Dm3WGdAjp0pW0POr0zUqb=^h)*CF z1z|qIFeO$SD=@Z&{FZo$$9H^X0xRvOKn*((AQK$9i5CpxCm6;b081(io(KV3ZCb^1 zC`k!)8f60KT_{0qaok0MvAmmLGe*8$rg|Bc0kZ66&HI`>6Xia9$S!9TPlcs$mJ!av zW-ch)kIY>SCwLp{CAD2VP)R4Ae=%omY4#krxZN;uxy8YDGVo+p(OA zcTaCY+CCVLgj51;B0rM!r*LW0?wv{Ia`2mwgAxre}$~!Y=pzv5{#}b!Em+#a5!5cz}W!$O! z!3noL-`+z$|7LT>#UK~OZtPFW^10D3F>}6N88xVDo9K%6tr%lgtWrO<>O4GQL8D$U zY4+E2kY`vaJ1P9^8#~xm;b+xpt-bID3O35r_TCW(vlC9|KQ%lSdQUhV?S+=v0vQ+cdca_DaJ*O|VN&jflrfQ23Bz9te2ZE^B4JLfkdxq0Evyzd1FX)bl*X|P zyUJ}2`BN`rJ#~N%x5@OG4fFZ;5uKst#TeB975@*hj?UZXz83Givh}!)QV=!3U(oTI zZvEx>x%~Nz7kgr;7Bk&iaI+Vu38#t9(8^hlX@M9bk~?@2Ljj_yzXrAk*aT{3DXix- zZHU2KYwXR9n;O$spF4l&6S zR^EvNf%>wSHs9K;sCCrKsclk=ne*=`Yl^IGe^hH|r?U6^BYBweJgGbrQNWe^Sj@iW zi@g}slv%v333^)xsQmw~{3FA;cD}4xE7Zy8%|MaSp{FDHx(Zmf9ZX3i9)kSto05N(=s61}quav#He4@} zP|YHPwR@}?4OBAn7eV72|B4{?7`zdfT{zn#sP6K>%hea$U)p%D0^{FktN7XF)HsJst&gqO7s z6W9wFy?#E?di~cEZN6-vx6f?#J!+p*EA8`~vP(X1Do(f!1Z^z3Md){};cGqxovwGA&5;MX^qY zi>Wl$~h6bWM^Gr-cpbooq)6>tiy4jUV`xqekt&aWh@wyiL9{zk{2wN zWT#U`;@#B9dX&v}Wa9)tX0rsQ(@HSI(BTF{cmn$pNDe-7c$p0H-4@P!Q;-iIhrXo) z+ZaBwEMnwngY))k+N%+1G+2NvXLMOku2qd zlR08F>24SI3d9pr38Dgx{IPxXjtTIN38z)!$Iv|FH(PWXEMNW0pHv<$d}clEo9{fB z^^5^LW;*7u(`UAKH4ozWpXd}nEndavM3awL6cSPqU;*Mu`@g{2z^1%^()=&dH#IPc z_PO%@JE<&3;)yp#XI4A}EPMa|Jj$qFGzDr8`;~JmUWG)njpA2TEB!ihM9c{-_Q zX|0Cg37bmk(HM_?35MS#nCj%K?_zyq?G;gN*E5Lf_$DrZZ?WfUWQ+A#zzRk`|6ByP zvTWi>>gBOIydH9Ks(EoS{%yFE@T5%QQL!ps$EkI}qlLDSJMVwdKf5nly5ftVHeSpc z@B!e6X_zujbC-m9hJwPCY*TZJ_%Kb##-66(0eKB~8l3dZjr0lp1&%d6b8F;I_!f$2 zS%`vc6=Q2RGtVf7AtGc`ry2u-A}d%Hh{Xx`*DW%Hy+aqg^q4Pwb2PW6PUDyK>}_C7 zk05k1sxy8`RL5~teY_T)B*m4U^KlZOtD8elQFh{$k-p3+6K9EKvEE>gkcp}s3#h5tlK(oi}kbm}p6 zLpd33JoT7puidtXr=^9n^fA zavVd_F(=sY-^e!$$?f^siKn`le4~)+l~FEX#b zXm>J0MO}dTBjOzac_T(^L>fH-@PtYE-dogZPnw0~ESv#^v1!fV zklkFhr$e$#Gz9&Tpg*?;h{*mL8PMSPenlOj(rR2Igm(bI##im2V|UOm|zr@ zV5?Q$&_FZ^?mKA;`uizWub3p7zJfU}HM}7;ga8?~$=l+^nZnulNsu#XU6`7kifB2| z`Dj>ym8X<81_VR`L4Fzq=MNB-p8@Rb@GBXvBel6q=OR}5ocdqF_+e1k{z|6&yDjzwaL!q=(H88Zu_uoOQ&O?*Uv!xAkzXnL1T#iN}JdEt{ zn*^&`Z&g-|FdR~>Yk@9-MW?w1@5;Aa7*+_vR`#Z`xZ>;@m80jp(2Nfod=({>HmIav zgGx#^_=2>d4Q3u`Huw-QQ(y!3m8_N0W&;D068rBRtc!R9DA7gat6xI4V_~af)9`{C zKTl{Ly)~n+tk`wJX7KkTaI}54d|lYV*r%Y?!R{lm;WUBjv)c0;AeWpYdp@?c=axom zNI_0bmr4+)P6bx&5+!fR#;jBKPzWQ{9AvQuVkIu-Sm!}>43vappiD5OL#zFF4{9w? zlC}EpAzMd}^cEnaM@ld}E5TLzlmTcLIA(%ho)#!cA2b(b9gUyGUz`OYTzf8L3v5R-2Eey5u&t)zKKgdzEECK zVzQKgVDD3?gk|km+al5*LjpvIOa|81whUC~D$oSBs@217bJCh`CNM_v`M-QKF_Oy= zo!F6+CZXTwqGBgy($rYw!m49k)Um4u%d~3spqW;$J;F;0dDT@j)*_!T<)@%A=B~ug zN*uke+Bx9}_{7{(F4iQ-5IFi#NZ3s%CC1A|F$I7p7bx{Na+W4bw>KtoHv zZ@roRriaPX(AwGh&201d%Z)q_u{;llIAq7*yJWCL5Bs<>pN~%Zf-6!dZF%z_iKZ#e zNvQZq%k?ey@)dfYxMB^2tvQnp-YlL0CwBswqrnVB;C%*);@hHZ%2Ytd<0(QMPMwNE zfwT8G3Acr~_$DF$FUc8-+(UKu58ole|A?Mwv1cH*uu18z8DPrDkU)JZG4~;i=Xw9% z{MM(*O54yd45Tquf`R;!wjk&Sz)u8NebcBk-ZWxn5g%0NV?IJFXo@}F18qn_BxY8p zHMxBNPvf;TE?=poQP&CJA6>vZ4~(!!Kf_oX3(oB0O6MJx9nd#iklsy!ma;&B-%0`O zrCR(&Drmf(FS24PJ+@i=5S%Ds zV_Q2WQu=D8u{h!M<2%x8m2MYChZ@*?AXb3bh*Ha?qM!M2SB(r^)98P|35~v!xkjG; zsnXEM(~owfzo;}c65TWk5E|8TNuwvaXjBl13B?GS=I>3B2Xa@$({EL}nHwDiVP+>1 zKx}BJ=VD11LsXRB3F@#vG1i~was1pE~zm;4ng1cvhqM4N4wrotc4pEHn_oZQ_{3>HOuEf%Fpa$aP(i>(0Py zN~|{4-VE}ojB+?lz$0sb@Yn#QdH!)0mF4X}*UV-1Du<*9YUXsb-E3VvvMMZ5p<$Z1 z64qO}sy_$XBw2}vVyY0f5Gn)5o&gU>vbSW_(n>K&5Z~rxi`PusCDZ5~1||{J7aa$)HJhj7?I}&yosP1b zhvs;D^DE6+H*P-**>_3%nE@m%ZYkn^tqZ~UO*@U$P#f0rOtR~d|gZy|PhNyxd7LZC%?^1&SJ!LQ? zP!j(7WA?HY5)ABR zPq5*Q3YRdthToH0dp47c|Bwy;#`TIWrM0IphQb+&Bq)i}OE@mMvAj*-!&<;5tOYz# zSqsQ_sqxTA+2wesM|&W<<5>FTJ6U!eTL|mp%O2%F0{Jh!I`TV?`7gaX>=dDJ};AmS~5L! zDALQP=krE#W949|lnXP!p%`z+MSV~|rmOX@YtivqT@X9D9{3j<1c595cL7f9wS{TR{ET7>oe%SWd~`CJJrPPRs1w_-32-xjFpql22*HjC51jThM9b{P9r zd=o-(CTMM5%BjNO2feB;ZjH-6)%*s#-fuL&jm1gMh4~kBj1ge?2lTdMvVS1QEt)MW z_aP@>CZ-~%a5;s`u_<*~68!X2&9AdJ{yNI>MI(@RO3^vc@NLb%q@sV>e5|Ud)2ZOw znvY7+N68^YRh7h1I7g8gM^a(8%9sw}{mqZEjE^=yQ7yyiETg~qF_rN#a(EeeAB_%mq{y2X=ArhG2pWQmhLFs5)IIA+zwETsH3vel1tQVqZ%(Z=ElW*6_HH zc$O6jdSABg3@cJyx=DnUUZ6+Cd1p9e9lldTvX2mf#S6QtJSl^Puy?ScD^Spi4VboX z@Ctg~iJ}fG(8Kcy4F?CF2s_Dqt||&Y7dto6OR1WDJ!e z(WhI*`Q$QefUqpV9(@*u-i;cRf>Qc86Kusl@pjf>KI$;Patb(T#dkni!UBdAWb&Rg zKn(u^^Zt4Bq-U%6mAG_rOn}gcplf7i!*9OyeJu4vlzQTG5P#3HjZE35=K=G)ZPsYy z&ew|Z6j*l+OiU9nD}4u|6POjtfkjpSXTEePa~_Re3ORjtYSNCTQ?1#MoGP$Oh4ruU zykuS&sFJA-{~WJfV@E^vHRnO)^EQNQCx%gZ`+oV^nhg#?%9;^`|x#O`GUdNxPJ%4tw!W%$G_Z(XfROu z%e>_`dWqvG)ZwUgoVJ1uzbe8US%N~+Y*cFYI+zhU2Phm%8b4&j&q#OBOS1 z3-)MDrzIc~llb_{f1$!gK~TIF+Jcd%Yz?FH#n8f&@N*K@L~TmrIr$oC;WFT4Uz#~6&Vt!HJ9lh_vAmn(pEuX`8YKny+W-_09d5D`)%L?{336-rasryX<4#nM}%F z+V`&J_i;2pBl}V7$NKkYt^d)#ziGXvUA26)K>X{PKt=``oPK86W6d8>fgd)pmerfR zy7e&s`EKiJ{_}L}`>h@>!f~_Ek6Qmu+`psDg!@fvA3vMj*S@QraQ8s@XuwX@3s=2x z)r-tjFEUeIPYA7t*EXImgVkls1(sWLHf9T-gP+Ye;OB;$xgFub<_DTce4_bj{3GuC zHZiY<-&~wlJ`BgzkSha+wlVAxsKk{!@U!FEsE6AuF<|Ek-ke;*%vw^v9YtVi1Z)LC zoIq|xGm#;=F&lpbH%Y*`g4IE?DhNASDIouj^3$sAAr)N;;(Mx7st3iWUEgzi@S;#h zbuU|ij4M_~+EjXjIOij@mSaCw6*m)V0_RqHNPPShbn=Xfgo1cn0D_DH`N@v-@5+x# z2ET*;iO*LdWtd4Z5T!PYUm-TMa@s6rfFUiS9w}XBLFZRD`|VMLisy!BtzR9>_it!c z>{MadXj#=-$3vVyYY?>7Dh$+H_h5j|!H_^V&nKnQz?LCCE+xq~i)k+O-g9Tz+Hf4( zfa^2+2W}&AQt=|>bSo3IFQy6urD8BZuV6@^B>b%uVF87KuK4xpeb^*EeK4d|CpFmw5sOwh;V0M%G`so*pfcp6hmh<8eUr{wE-AJ9~L7EDgiORr1eP^H<@DQ9UEeD z$3lsD$A%Jt!-+Y^mcyuFH40DW=l~&U6wW^-;TRsXIjqo$*v4-Ulh8kCIOcvC2GwPt z`S=?Y9EyLE^>v?x9N!^fpoU%pHD?V5ct|iL&}aEiyDnR@iRdC(R6*1PA7t|}8s9ti z%8dsSPuDy%yGSr5w+U8LOi|XJ)-Jps_ARkQO*L~C23wI1GaGDR8MW!xH}4BQ8}nuE zXu($Y(KaIE35Q5L%Y0;+rrudSoei}#0v(I0Vg-n=wLI6`l}m-DpM1ZHS&m|sZ--B8 zze;6gSKWrhZMIu0y8|ozeb_4Z^2%g8B;@avfD_PqCt#yeb}Ba0WM@AQKhL`i$;+-! zUINA6F5WW{?!8yw=ZYP$YPRE+u>KoG?$v&h?74T?z7l(6w&JSVUIGPwe=XlH(Z@lp z<5oefRi^-2e+hmr*@on{>#ABBFBkUKUyPrNw^2*5xDPp*!Lt6k6fB0F2L}gdOix{F zqv@`9?vz-65q>VRN7-!KwJ`0q*I5ghiv# zvg#A^`70oA1)9Zp8o4oX?md4wewO3Sy!Q%0*~%q}uyX#SgbtXM6YcxA4CF&D|GH*C za7Ts&YU1$=h&dwfe|Uw@%9$RI!m;>4-=`VT%?F6Z4}p3A1{5#^U)@I>F$eGq9=n z>KsD^L9J$%Aj)XupHXXKA?Pu!RQz-Er+DZVOmd>b`AL$x73@Y}e-cj|6?~uJ`?8-P zQ?!2ZWt4>rN0?>pb~1je zct*Ln@&m1y;2h?H?6!MZg&K0JkUE=Ad_&ZtH6C_n$jJ_=mKEa?U;>ZVwi6RbIn7Dv%Co+FKk_(>|-? ztX<9lW^QV?3jJB2Lm$#@-i=L|On7%5AXd}+gvEn%2_mwI?Xd}aySR`nECtoq=PT^5WGmS9LD+*2}U#g1Uax?_Sda3>fiP62GFe6?|yge!k3{T4U|2ai>j%z?-T-$MW zjBC}jRPvv^U)eSH+=HQOk8T)y2}iM)G!Jmfd7$}cDbhbD=CcqTn{i5&RqeyVjmg`S zbil&y+a0P=5!SnJkG{ckupiicJNp6q%N>t0cfSZfFS;G^g!m+yZ}!nd1TnJGX#zw) zNv-HI2(m8#j7PZQDRHBdY86k5#ri9jmj3_<&g``)iLd-{_D;5JO+3;Wm6IRfe9CD! zZfpmRqZI%0f0Z1c_H4{1Oq7U%XrJ~F(stJZ;A{PFO;Yd`6XG{CL1*=#5=G)&%JFP`?tgXHZKeX@o3s56y&SvowfN5=Lk60&!!#&h|AI5DtpJe4uN8^zc&F5G;9nlrH3;sS3-piW2 zm)YccB)RJmbk_?IicxKMz5M`3TI(B#mp_jfp9R*vS73NA z6Ulp@K%(lsmhR%c`D3!(nP|~7(S>cz{;c^LPSRh)_f}i+-YU6mOw-&KE#Fam>wXlv zz)hB86LQdD{U!W=Nw~fco?~Cb6+Z@wE&>Ath|miV-oiZQEoj+aNkE#wMawpeNr>!* zxydwvc+6=R0jfb~0-s?Dy(wF9cFe*8cL8zUXBm#m+rY{2$0Mg7n`fXV*#vQ%61&)7 zNFXPT!jb`vbOCtXB@7gHC9r(V1aE-gJq6fNHfRZq24x~O=z1io4QlCfuG`4JBvVa_ zh<|PKk$S{C9T87bRQ_@0V#oeQ>~?`c(JtiVN+BYJAkB;cJwRyu17L?(MGcgF45aVJ zU%ph*^(^>&w8QhSfswDl1vPl=<106x8lNsMdshHGsNn!cD4*{TBUb{~$Ct;Bn}FHL z`t#LViBEmOCbP%&$mwf;1V>xD8mNuQ!2ml4LjvU_k02Yrafh7=;`?NRw*&OPAV6U6 z1lF&-6d10hnbqAF$IPmlMlNRTS4QoyIUl}p{uZm~`++{0MRxF52p1m)8H=<0vVxp!Z!}_n zTrhGh9D=;5C;2!M>B8Z5rH=m(1X>nO^Mo?+sZb!!i8$>N)xgu0QK$HZX9I75XpnCL zJK9EOfzcpLqz3su64ejnEM4oI^Iq`yD^y-&w)k1m{T3I4G9|)fv)HuuI@?BLlH(0) zzE9+8<3Qb~?y^9_{4hWao&jQM<7qHpdzsFq;8KUunmVfGa1QI+sNB&A^VnSLC0-EV$-Eo zkg-D7kTp0nR3TGLd%ciV(m`L*+lqEJ=XA(F9mf~#2@X9Z9hPSnsz2grl4ftT_Ze(cgD3is57{VAu}Ag?78=k6|BF*4PN`HoBQnZ$mER zeC^2ROMogCcrYKS95{V-Cvx+zI}MA0l*PJYMLxiuhQJ|Zv`E4eQibmUrmV%!THG!u zYZ33(3J}%`5ETj#QkwbKC8fh!(C<6K!(!Pfr$L=2{_Dg^i|>k0PqsK_CcTj&jeq&l zhiI^qAm=1Iog`a-BN8{h0NQ3R!2G!nXI$U!t54{H$&Uwe`Y%EE-vCXh1h0``Jd|eR z=HqAn(dL=UwC@Wq3SbK?C4#BL*)}Pkc174%q1k-xyTUw2?=D(KU+Q?b0)>eLs)6bg#0x}*Z-Aou1!x8^4suhK(GGRm$|)1T1$rhLWXQ85jhxb|W1yea)uXEBFd-6LA>-NUIveVc-K49^aS;9_FBe?wkQCIQ|%T7(xe4 z9)WZAaotC9POFqT=d`(M;<*dLjTRg!H!3J#n7-UWeJw#3gr}C2l&Co8TUD@i#6818 z>M%ai$T^)J&e=1p(>V{vfL1v~8FJ3oO9wjV6dZJiW`}bIZWD3toNol5jtnh69FRF@ zH-g;f;eMJ`?;%E5r$==B=08$~vy&!5Z`Z^@r4e8S{Ua7Tnr2 zbKwv@Rc9-=Acfbj+DAhzvCEEgYl7_H;gSJXMD*nCC0f$t+h0Mhm>0q0l_0biZ;q*X zHD?spf$ew)3|}lhgc)y`Drbu8G`-oxDM@4?aqOlYPRy89K6hx;Id~$YoHLMRM)Xuf zHk2_E=r?yzwJEY{-E|&Ktcw2}7bMc*)B#Oj}EqFk<^< zz-xJ)bG4i)JhBYEseyxF<{rdHsO=%`jSz+?B#mPOqwR=bAH*V+Fq9g&m`*5)4x>r+wLkYAU7%Ybw&% zROHOBR^Z{y7hVVL)X>re2}_bMESX?fl5o|M#Y=(U&MVZIAYW8tj0zA2B*Nn@i@Q+2<{Uf#Ik`H}d{}z0=nUYH4Q8_dm{z)t6kR-yaLGSY1@#>xc~ znxU2;^nJ6i(jY+CjbM6N_D-^}qKNARV{SsY_Ok2)!HDW47}5yWUY30<7}3HBMyw) zREscnEwT@4EXRj|o^H-Tj^pgJ3$|X#e;lJPE6D1P1p%U-0m3;#R)Cb1VDzgBD>C^i z2tID5(q96G{uv;%C79iD$>Jav(9jmlI3n*q_9ecc!?dlfvCjDuGN&HSI@Vjh1xi|P z`FpWd*IP(V>n%$~UI4o-u=NV+LnQlWC=np~mE(bR0|f{J1<2Y%D<-iMhLM*|pXHC? z*(`QV__Ci=o3N$CE=<^PyHZI>2~zAYKTA?`NzI3b)S)<{66&Hs z|HlD_{RNx-4U~Tq4EqZ<`zJIM2{df}8E}XF4L17|4*MHy_BYtAavacMr(foc<7D)D=^ASc#T+0VQmeKo=sfFrng=P zB|1et;>3CSXWo(?pA%~z04cW2F zJ!!x+6jIUIh*b0lJ3R*~enSkH?Pl3g&x(wJMaUh+>6MzwIblBF*a9#LactP4^;q)F zK;y`AVZo~-?FaIf=nAh2!>fqT4%S$EL5apnFdFMcz(->x7>$)+H5OCd8_Ow&X)JQ3 z#=0Ac)L2S*V>!VZD-qCGB>|1~24t@`7So4pte1(Qv#}goYplRk8;dwK)(0K1HWV5S zAZ#?&KwdRgC$BY@H(Bqes6L!JJN^Q^#J#|dsm?Ce(LeV!AK>!)1I<^Z_t3`Av#zs? zU)3zOJoCzIEB?obR$K;Am||{ukTW;Tuxn{JSS^jHucdiXQcg_Pz-I3vJLewlPN<>_ z#2|JN;`2QaQ$lAfl{p)h6Ajf}U=^KY)CE>qSWl^`*RACTf@}M*%+vx;BIDB?9)(@QbzXMuN^}v$((?PIV}>=r znWuP_6Rv*Qb#T@$s@BvuC@!Oht6z2-BOjyJ;F0yhM8z<1`F{97{``!;4jemLL^M6>Z z8h_VV9Sc#2)%HUktF<)Ls-+RDwX}kgm@cvE=;Upzz-6uL9WJX;5uV9@B>Au z%BM)jdaMSn9;<<^#hKzVDAiaETs>9;Ta$s0Jq_Cf?!M*5lsXk1phk>G%_Z1 zz(8Zg>l@@|M*QYXq}9Llf*%vmXFwR@GnajsGe@z4tyqFltY9lPp;2t0QS8ge9mO)y zwb*_TR4m4cl^s2NnQad1vexf;U54IJ;RlB z9v-f)ukBr#u36zOkyQ$r_%bVE;CT=|H19v<-Rz+vZSJ}bBy9dB)<6XUK@Wrt0IPwZ zGy(xXj4P5MPzetBnZO7IqPbWN7ZS+!3^=tr?9`9&IgE2WDwaW= z!^ndGNy!`F97HGQFrKo7%~SJkS>YU! zRnF0w6|FStZ{-{t-{;Puv^mGmQK~zKfpQLl?i{}XSalAiYtGSv^l%Qr;T%esa}W&Y z5Nyto&~T1G(|zF@tFh3MHKyVDV%n+bH%_&eqM#I;K`Cr<`#gYnd&sB2g0O#5Cp0)< zn#AESIRb4mZbd$*FByV0SuPBeXA^|-S|k%}$|p3G4>VPW^3SM$?52G7H%a+X07H4g zuDsBueByw{!QmioYd}H8BIFC@1)K5)N_m2zykJv4p`m=BrMv&+`%!6s^0P~gtlz#E zHwSOcUWTt5&@!*&1E7Bz^Jeke!`a>C)^SJsZ9LgIcQ?z6d0;3fqoV{R`rCn`&?(@nr zG*p<^TeFK(p~1XfAL&$3;Oq0TUc|B#4>G24z3B04I2T3SVMK}iMd^o&iuo93<7ytb z3y8CA_b^OgYtu3{Nl+@&xWw%;$Tye_`1dd@M)}TY12wh#GIaA!%RqHn1ijPxCctW^ zrF5;+`Yt%4(-Lgmp@9k^)Fa72QQtm7GM$YX*v{qPvKyl9MR4?Zv8K_rTdB+Tj9+Tq$sFQ003YDL5i<1Y6)3sK6l@fg{)gC!rBIfsVk*pTb(RZ~r?Nv-NZB z_{ywzr}dma1bGynkWjN<0Jg(?9mG?SV~ryT{iTFX?D84$#L1Prq2n{+Z1VI;wvLZ? zsX8h(QJ%fAi;#_*x_yh>s_N1#a$B{*j1p?)Okp+HFPzSfIy0`GCbgtvXg%r-{G4$n zXC2j?s3CH>C5A!TG&?`FAUsurKg2M>o6T=(;A#R~NzYqqpjYB|nEVRcZv3$60*FCV z>-b>7Hn}hmo|B0KO+6yPXf8A_IfM>at*9zu8_4Gl+0?HEIhy+IfW4^=R8tG=XzF)K z=>L6Fm%22Ik3a|1+MAlGLp8P2yEL^^YEAudNQoSK@6E=`^I(bU1OrtZd%rv4hl zL{kg4rZ!MbO)#2Tur+l;qp1UJ4Gllsb%?0O_ORPPwu|4fsi{n0OB)m61TO*XPGF#% zKwyUx+^6FH@13C3rCGe1bxKaa)S;Zf>0O+_DOD$cL0@n3v^hAl9kK;+$sLTLGxEFT zgkwZbIYzgfaEuQ_x^FZxP|iS*uguZt0bLct95m^gmiZW1LXt@I zvkq&IKG-^i7C#bLYF;dXH1xoFZzDJ!e3@VmY&$18*lMF%;)jmGFY9*Whx{`kCgxRw ztp_$xmL`bW>AjF(3&4a%Fb0|$^Dlo)ZEv8kTyU)5{xy} zC+&r^k9JHQ%GOTrVr!?=Z2c`r3tI~gTQkwc)`=fF2ET0GjUTrD1;m7{1)Hr6l&uMd ztp%H{6B@P-vAnELDNgMq7v2y2=sUf<_3t!i^*1kQFwx} z(=@@@YB~T`pNfsAi4d>|^k)9$Bx4JOdK2tw!B;2QJT0~_>(0lWjDzfc8P-r?<%SA~ zE;m##5gRIu;2SD}zzr3N;M%L638t{Y-rru=a9%GQ^_)pk>W z5AQgN59(jv<3h$Nvca#TUQQ%+C>{w2!yX#78^P6_E$8j#Aq&mhxMhgJZ?yu)p3N370*2xV4g=jKSu)UE?zlr3z$XS^F+NbP{$zYEpRqC z&@m?thshD>c(rnpHge=BFdu5g6-4QN+h*}{$dx5%&o@bVY$?FuU5}-mmyV@viN?Ru z*|~WNtGKlc{0>O4Bd803#w^%xW)BXinK&Hw+uhHFcH=#xU|R?N1Vq!<(7OjnJ@QAT z^r-fMZ3nX}ZsR{vuSVnOe8mmgtb4=m_yBqL9#{*~D8RnxNC|$?f%$StNeTN(rkDdA zCsfMHiAX2pR6oG?g;1x*=N+{V@X@i8j4>U$V@NC$+Jt9`>8-l|DVwxBrp3oSW?ljGO3KD6@PI-iCv-ow%g>Thl zAKb{AZN+)n(i(ajb^;#WCQKf_hj#$awT-r5>g#0cb*2JLU_3}ks^3U9h6~M^@HK#O zRgsdGsJ+=}Q9~A^Cd6n}d{8kp>Hska&*wn_eE)^=9K`9Ixf$5T5ZM|a_EHh#X+QzG zYjOl6sVCBq^(4~O_a~O#)6i8$W~%(*gRDC?<~OouErn5!JGHc;(Rl4}mMulhf|fQF z{iX78j@rU;twpwgmt>p4jD!nmGGWc%&~k=n@088vAtwv?d4j9)R}wcD;^rNVpQD!+ zxLJe8u=-@q=s3j{-8L?{Niq#TlQL({h0J-V14I^|fjn%U3UFd%$w|Nmqs%a626)kk z!Rw%S)nuK#ko!-_KGHfD1NB{W$J-1C zB@?L=D>8wUhOj1|Mld9|Bvm-rURuD-JbO-?=Ux1kBJpmCDC+|)-S=VmEFf#F~2lX0^_l@p6P4P1+d z)>LbEX0IU2>=k609X1;Kh#mBkz!WI`pp*etudmSttFKW9ukQyWxud>@EESf`4OuFz zT6AWwAj|9(WSJe6{Bl`e15RZy3 zF4cZUeMY!!%`J1Ib?+m8t$bbkNFxpGBMslZkNmB~4caCoily2id)kG%&UQE(z{#NTWq8RN^EzisIn76z%YtJ0z`Qj~^nP8?j zL%5sCz+|SSDz>|sjMmLeMj2?PQzh*XW-^BEW-{79Go22h$xKWPFq0w68pCrUlPuDi zse&vs!AzGyxSPp9j@f9N{x`DF!at3`EuzIxbPM>DYxTW0o}s{p?@A-r2LW=F!?3i} z88C+p5ZKv1L<1Wju+PNcSb`WbcZGx!#E_Y=kPx$gcF}md53ePtr3m6N2aYf0+rza= zfq`|jXFyc~#H^ZNk2CWbbP~BZ&O+Y=W6DikF zNHD6EV65E=h83}N8z2^F0~|AMoP`Jxn4+PFhkDS3=Sb|E z6Y6%0#l)+dH&8Q*R?!=6+bZ_mZFWT!H*yX{j)2+D6?DK7O%3xW?xBJ_ZE%tf61HQO zO!*&)mSet~k8bU~#gJbW5+Ai@<9WRie2W-9=D?Hz!dw3X*xB)dhzVFg7hS(PoeUs@RrbZ>j8Sr^iPwq z4~0G_u{a1O%X->3-w88~0z7I|dsp*dHcBSL;U3v^uAMBz*Tj6d@kzr6m316!H*R8@ zehXqmcP&Ex5t8h$G}^q74ItEXkID>@p&NI2^#%SN9M%Wb?2KbP_O z6FtZ_swQ1Eu-?7_Q*SK{BKC{!gL{b&`h4|luZRm{tz zL5`;)%Cdyd%SR09K!?mBx7{=;{0$6;-bG zllQ-s`rFLzSUBXdCyl%rMGpJj=&94^?VEitJ89*xggBV3Ts!>c#?23I7yTg4mR=9( zFx+wT@vlF_9XFrAQHz_6N#hSqoj0Q_huK8XDmVD)4mO&7NZkJSSOtlN?7o8p#(!2Uj$KbXIcc^A-PfwjhP&Q?YPFHm-honB% z&q`y+&W4xg##gV_!12B8LQ$Tk zcD>3%-2CS(xzTm!^KwXDj{e8kTP1J6?Q#XsILaPU3j@=g&rIS>9*ihM zd4|32WkIt?h6L((|0BVS`Ohb(4wHTb)4b}e{L6bKZyuU$9y_k{`XIFLYCu=-N6f|fYOp)38E7rHhq;#{gHXKGV{=;Bi7<49lK4uBn&A6#5=G6u`Mz{ zXtN%?@f?Gm2z}9WEO+s8m(pyZSL#H9v5^xAZ;7X%RcE9}98<87Kc(Z^bT0gA^^)1@ z>bdaF7JL}pvm?Z8+ZC$Jr~rkrTBtyPcuhmFyx}DZ{vQ>r<9ugY!HY3d&DQt%(b}ZD zi2_6k0iuKeA+VX}IyGOrOn9`UpNu#XSoZd4>HuNT(ZE)Y)?WH{+DHwoQ`&6`%$65{ zJ=!Qm4{+JU?H2gCD*A*h92}j`<#I%`sM;f(9@@q;}198~`Z}e|ee1I8R2W zAr4rFG`CKGunxga>wHV);u^!Om<0g~aUe9Ci)h|$h%q)mgcw1#Cu9W(O`7??NJxiq ziXV$x;sQkLKLhMAUkpGjeE~_EfET|an1;1{-@9oMJ;-z%FZc>j;`~6FVzsX49fL~X z`3+~X*nA^9=PF4ndO^nVq58H$FscAe&e9FOl?Sl=BFULjxj1h`jQ3NH=EZr1U!0fF z$DP;ZW0mtZ@M9I{jqh4$RTi!@%3xN)*kgt@k_xQaTrMpzKhRy;+2VE8%dOGyPDgDQ z>*j@ZscUu$M~cP3)*dY(I`4lkP0CjfOP>onJy+M`UJK}2JV0kRz7T{L{!yB%k(=jS z!Ji1aKLtotA@V~Kxd!7khOP^;OLnB;Es?g8w3Q?urYsLX{=ejEJ@Hi~af*3fAAc{| z!HH)1=K}FsE1R(fN<-=U^O7AgyQxw`pBm2fAuiR7J#MWG z(Y~o#^B%VaM|p+wz-=YYYw9@GW`Xv;Xh086&utN1&3_!!JMJWo(G`BKN#6V_%ckTvYpo_gv$4Pi(zU=wDv+BOry2%EEKkh zB<``oP`GNT-fWz4}oQ0=}))|sC4&K4h=;L?W1 zg`2aoG1E}bY108MJ~q74Wk50Dw6sM`Y$&3X{8kl%4;ZsiyoC@~7GjQkbZLL1^S&$0 zH0>UDp9%&Ab5LF|WPkaKByT9B#1vVRVWRyOLj&oO{Og(ljvE;gC?|gqV#eqFzdqU> zmuWkC#)_B3v+-QWTNrz@Q76H=CoR|hr{ycO9b|=E?M#jhc(<$PN}FjbD-q0EwZ`$d zRLh#gsC>Qv&MJ@xZVPegNo0%U46p*x{$ycbI^(2U22?#VBv6fb7sQOr``>k}TR~}S z-)lkg>$D8i1|fp}-RT~H)%6{v@!cu*P1q46Xp&y60cChS*_X|Ym+=^;fK0a?SYmgf zt*IpiQ-hL%h5YM~r|_qZcD_Smar0p|Y7cdLLo7-Z%gIb=8YQ)H)YMrzA;8***{o!1+nfe32mT!PZk zM5OBtwp`Y6y@Asal@QvSZNDt36_iw5RUT>v{yy+0m)Q>u@EXn3&zTx z%2!@*5InW(4FXwa#5*V=)Aa^QVB!*ZSOxA$?Cf&JlJ9zyTIsSjoYtRh;Dx4rHlNAw z6>SB&krgMmZ*A%fZu0vZmjEF(Ky+2iGVuj_O2A~^lXTL05MDWb71{$Hi4SAgN2EBgex9FqS~KWx^g#L{){4so1*3~ z2rCpsV!fEFNP_8HDDuC7=934o1S7@-M~o!`Vyq+}^RJOZPKp&7EJ>o{aTj6AAFoD+ z2J|s>bqzfT>tN^QXs6|?;F_y$KZUKLdDx^+6O>(~|UiEO-Pc3(u7x zyW?lYh9pCBjE1*rsM3lx`e)5LUrx@}oy8Du6l6-9VJ+dCVM_`MEh%1ui@gREUJMVZ z!@0)a0!!}n*#BA#uiWuNuRSb7$s)}=%Aot^OQi#5d)Z1m-?M_-M4Y_5T^tWS`+(;9 zfY7_azq%2ueklF1_t0~?MNX^u9B2##jIIH~mIM_DXz~QBnVyoYY9M?$B(#f8P^}2< z0w1982n69h5E6_)NH78+!O6ji`F#Sx_y!LI(o-OO3keSdfgT8gBM=e+Rw)T)=KR;v zYLGxMVm%OONe_eoW#OkKsCyt7?J$8rrW6R4@IWXj2!xX2HJGM{Wxr~=OCUIX@IW{m z16=VCWhfAyQRVA_5V&d}{1ki^2uDL}K^6$z2&`Ye|3P}q`5Yk5-&H;|y;taCFf<%< ze0pfhj8qvQSr6ZVM6dS5yvN>zL zIM7N8#EL@k{0j;m6zAZP-MTuLgV7jBj>)YGCoM-T*VYH-*F4|z!EDvL6g&pq|}6 z2kaOrQW%I&_t6~!+rzeP6kh>Yolq%V>}}j!KA=(G{Alf%T!xA*Ti%0}k6W=hFk60d z>24?EO`vL4{mD;Pw!z#@(;qzBW~X8N%g)+Bm0HCjNF{ERYB8 zf^0fYHm&2(=+BNu4?egI^Qw6R=Xq;5&x^LZ3#EFK8>l8fA6Rd41J&dNy~&>ou-fEG zcWLq&Z(?ur2RHc%%Jzpf`DEnrCO1$`9#}MaU{PzzPffl|g>^Q$V{1(wxN4IJuG-{* zt2TMys!hI9CD)rgaMdOcT(!vqS8ejZRhv9;Ws~28QoYFyRFj_utT(xVYI1_!UhWTQvr$;K?%#Dtz7nT!60*DQb^;~fMyjQ}t zxyvrs1+pO0-jy_q%~sH}b1%r#>y$=8N?SnzqM&*%7WD9USqsfl=ETES@gX2J6~u#H zg3%8q_@j7VGX(kKFW-(`r@k5O*&&9+{P`kG<{r$+^V@jJ&K8`=f0Way^U;|tz))(q zr@l>5891{cRZ$T3j7Zu$sn<@n{FNPv4_cJB{K=Pohf?%9mTSdZ;=+cjAonWmK(Ygv zi{-tiHzr#-9Hmgo8f9I`Zt)!4;+}2U%D&Nvi98$2FSEge!`XS!BzZ8{SF*PcoP`@0 zw(=i-Fh!v``s)CN$7NB(V=4nC+-p=O@bPY$!085iz&1h)oe6B^0vo`>o5(;A9{>jk zk9h&GJ*_<#LNCEMY?lx3Lg#xf%;(wihSIRVlgNeEu5m?LPe@4?G<&fZj5kpMLY)A? zKm(6%@9EVy_+_GvI|o5&i-O5@nZS^?5)@pzi#$;LG$f)DgbNX%s|b~9C~eg!`Ji}> zFVa?#k`J1$Po<(VWdhYH6Hut*FCQbXR0!P!SG(ypc~f>9?grVE-PhdD6Jqx_5BN98 z2Y6)cCL9^-mq8b^QK~zjNp^ueJQlM^@Zn$MqL0BKGf^Pkq22xZ(;G67(l+%x0i=c& zy4rueP@EN}lmU9viCV(S)s-!RS7D6t?1bTReNCO0ANjvpW# zpP)N_fN=Z(VWPcY=xObhxd^-C3yuAj;rL3M#{?JrqsA3!^OxX)W_P#_@Rb1JDFK3k z4VxUlOu+G(NRD47;P~^B3!)N>kO;>ooE%?-isLJ7)hPL(c#SX8R*{kqnjV`qv=SbF56C73%pUfp`F?URJp8J1t)zq<7f{DbGUW;>rEUMcsw z)`Kd8+66w!AT5;vdO_tI&E8@e22=bC=T68?j^yJ~@ow-<(j>U}JAk?BR{SYI){D_A zIPae`8g;>6@g~qrX@UGi1<#W205)R|6eBq0XsZm6?`Qpr|KhnXA@lzKo(RViAQrK3obp$T?#V6&MM-@I@dNjLyf;`F*J{G9>Z^*-C7M zQKp2$m%Qg#=Xq#Bh=KuvYB(1JDHQY@nVA|*#z$;Bv&;Az!u}Gi4>b4(NPLp#e?>zL z+*eHYe=qX}7d51|DHWg1LFyHd+ChUqn~1yxrm~p&X)J{5g&RQp4V<4F&)eJySU0SeJ+w<^L2%J%F6u)ljfnB zH;k`8x=75!Pg19%Rnv9^PYXQogz6)&Lx|K#K1hcxW;s>4&wj$VW-K@qF zY#cuu$b<6mnv`PL7(+)o*js{qjp2dqYm6vC1es;S>GwSe%t~-b3Fak;&!U-a2pzUn zyj=xDLYBZx8t0_oh9bP;*vq-a{F4GYb+1EsE@AD06J!4Tlkjuuod^IEQXyg^%1Nm4 zsax=~n@B1p}zoK{o10VG4%)?l~{Fi7nVrV&SK|mK>ANtlg zq3W~+__^pt=-WZUrcQhrn_aX6?lgqXkmRGQ1!-$`5qGe5kg5VZNL7KT)gw?gx8B1* zdMzfjf2T?egZxuBvfHZSVA;*eQsL{(PQ|2#9z7s$4d;1lIM0hh@RxsFC1asHn~F!F zo!J%Fsr(wP4>U9%NNI9v*)YCmQ*quTvR#dAa*Gg&%|W0s+tqAf(TYb=8vMO@(*K>~ z?e95Bwt205Z|Y18se-Q9;ZO+r6a|E@e5;yRK#}1%F!}F5^tp_I>hzo7ig~SI>X`oW zrRu_Ofc7`Mg?+$Vn(y=lzjro2#1+5~H6PLJFyfs5Vy#)(xLq!rvIMp{aV>t%eK8*w zU)=l?^b0$)Kf%99zNQJeu$WamaxQ^eBF_ccxnR1$m@r(CNd=@LmOuqC_GRZ@il0lt zy$Re8QL~3A8H4$dg4(ci!5$?8;nM;3vG)lE?9m8N<*+oAm-neULwjzu53RGIWv_62 zMA^#S0qwqnj5~Qa+8uX9=vlkFq-m(r{NwSn@(wz*S1S?GRUD5BtlWT~4R^3X*i}5& zYEgVp|5lNC|Eb?#S0RcgtgGnEV^I$4k$^47q4Ko30bRHwpdB|vHKKFyOwfDUT>M;k zL)mWx31L1L{l46O~~*6cz&7G^tc;KP)65|O(qxPw#`jH+&f{#=?(p!FXp zY>#TjI6eh0lCcMp<)|MC$_3deo1z~HTyJ*DdESoQrXr()@P5Zf_5v3l%Jp zeafBw@8kNH+tVs?IXPEPqGx46&%YYGGUc!4imhTNbB0&lT}^zcl0a38cOmVaih=4> z-VJPYDuSV;CK}%W!6zCcge!;{feyg!@{AY`Gv{ckcl>?k9L6~thUzlsAd%ey<{SoU z&JkG5IReC-BS6eK4Ah(>K+HJ;#GE5Q%sB$YoP(gxIdT=OIY)p#=V0>pn{zlPJCcEO zjv#iQbBwln7d!N?cO*jQ{lEH0b|j*B!a9=9JU(3@`uCf2I4Ap#&N)Yrs#64y{vdUk za|Ed>up?JhAZj%M%KDtcK%a9QrApN29D%FOIRaOma|F)kE9wsdSDkYNu0H3Os*=0U zIfB+@&S9kPbB>^OnRCoQY3v`K?f<@5|E8G?$-m#6V-7QhudJ*l?yV%)J#0hTy9Wc+ zJzNHCbPs~9E7*>y2zEE~T`xg~rWRnC;Mu15+97LWLkX~A;NgyVH5a^iF&7{n^mZ~6 zA7%pvGak^1ZV(+XWjHq^VyJ9D~QDF&A6nEts|lvTOne z<{Sb1?KqQT49ZeYBs}Ns2UE`5xz?icexma5DPMMX^X_JIqw9n|s75!bWD!&qgxcaS zA5>7Ceh5JrshTfX(^!B<>Ed@&anQI_7+f$6UVxtuws;*x5U-C>d1zBSacgQ7X?MJ; zIT1$LfX9O31{t1V4$b>S>jAANolt2wF09Ty#-9I+r5z$~XBw;XI3ocEB@{c8$l`ub z(y5sH#RkFItdO*CZ&I#sm_`a%=MH=YJa#cGH2gU;V6nfdq2a0;sy6^+!$uk~l_A^xoWspt#32^?bd&CQH_83ZOX#0g8!-cBjnLUH$;Yx*gl;Nc?`>CP~xZj=ciC2LtS!H z=K@!UlTmb9IDtV@kHnwD1Dbe&(AeK#}33wP8~?l zHyORu%=?9)56Is^ACMp2#g9?;w2tm#P*l4EQMN6*~9Rm z1DwV!Q6Ff2g`V?d^PBwVHLbUD?5Z@{RsSD(?*V01m9!0?dv2X@J42IWlcUfm5*3>; z3X0Nz1T&(JGCEExifP0~MMV+22`Wfv6%iDjRxzW~7*G)vGb(DE5HpG*sH6Y$)ZXXZ z+ko@F-&)^V|G(DX=si`nt7=#6oX$SV9<|yzNQ|5bCes$U3s5GIm*L-7zv^U~k(z)^ zBNsAFS*FcE~c5Kb%5U;da-d$q{1w)QN~Y$=C_?+S(p^Ks8lwmV zRW!jWGBp~WM3#(}7VFTMph44^G8#0R>~B$nv6~`?9*>{LO)=V?xSH+GY!^=K(ZX20 zY++j9WX3qygNA0D)X*MnVbq>+)*jQ~*=X8h6eF*oz_`7mhQ%)_V~XvgQ9*`;3><-Z zFP5Q?1Bj}e2C-h5rp6$bCc-np+Z=n4wy%z5Q5eofkgaC~d2$JPe3J!{u@Q*ujzE*Q z=GU(tLwj?PI=Q{v%A=*%Je!~M+!yivlcVKDcb4hB!cwhP?AbCjSOvXMb&M!-kfOk? zkj>oG-7<+yj136jHXxI{VVYl@dfT8mjgupSw6l{dEg4HDcPtknXhE` z(>1MYuquW*EE0J)6r&_EWxbZV zu{Q+}!O`lh|C)-oNmib*OxmJM z12*t=v6i%EYK#*am}%oHtj=lV`s0_MO$X}1#Cnf#Q2j_^EteoM#95nokj?2Nt@Y99 zgF;qDM`MrUJ07TtDud#oGUKdF<_N;d=yf=ca%J*S$asjS-AE%e-U@N(6fT5O4cy9q z5`Gvku0dcD{F`JyS&R(Oe7AT5B#Eh{eyw`bnzb7j_4P8zK_YJyLjf|No?}vQ@AUj$ zHRKr$c{sa6F%pYxf+~zg7U@YaYNMGj=FgvWJd+f;DeYfNBr9vC%WH|7c`6x+db790 zSJD!HiLWGoA`%$8i6-2|SGa1Taa^R4PpcJozKxOD>`2E&T9NEGdkcIA2;N&tII7R{ClMKHCgATtCJ`4diL%S9uG0S5Jg9^%y}S;YLarhv;5r zv*bA!Et6(A;llQDC*(1I<8ht3ysgZt78b4jwkOgHwWB>wZ%TVy8N^&W6!gv}-;V>x zeRv$BBzJqi>QS{Q!Xd!b4YkOsQ;YN_(jv8}Nb4j%CI)$0gb9WlMXkK;Go#WI(;91( zpR{z0CTNDGdkPQJWBR4F4dJ)qu!ZR(k>i*2qzd}B?G?Uj_%Bax) z(*Ogi(F&^3m=7)o3yKF4H@p-%(Smg#f~9iXbjBZ#C`>iowOal2+nHs!)^5srIIkO&quBL|;!%+AQhYmv3ZycoG-c@0S3 zP(hwZPrV+IH(&T82omJ$76RCOt6XggXFY3P<}5sIDj&rHp^lU|g!KEDD;q z&{9SL5g7ZJ4~gD+WlpjQ8qKyg!Li~)frE{v#sK5X<3|I*g}hSvDH_yPos`27<#YOY&kzkzdDCGv*m_D+TOqk=ylJ#3_njKHzgzLa(MxVt?~1c!1|Zu3u0f$4}6p652^4XzLnl1F+4j} znX+_ahDBgRLd>j)_V|ye0ldfPw516)QcDx75;#YH0XO_tB{p&x@G@dy&>u3-i-P8P zi+QOX*>uT(D*fkGSx$E4a3BBS-eUAsIlMt@VPbV68$RMcLtUM~00VuPgya9lnvQDY zhW!DyG+hRJ9isLHrl#7u>$i2lcPIk%C9g;XZDKMUjGS^z^F9?I&h?gLq`A$=`!RP} zdl~X?A$oWKUk5)23d|30!`t4VFb@grOBRKbl6X)K4@%)d8N|G24)0ZX?#GBeqwp-$ z!b4RgQx~7M5HWY)4@*v+KN6z<0s7Z#0WCx}74E>U@-W$vxW!FQ!-dtixVLhOcq?XI zivN+klLhBaSkN59A%kLVn)%2VztZv_A}C=Ywj8_M%ut)YDH{bDG; zcr)Ea(#FUd>AILWxtCGFbwu_-!1k6-njH=53l@1>O)%;?t>1;&t*4r z7V>1`cRqekT;nEr0sA%XQp_IZhvY2Qf?0BdB=I6V9xI7IBj51x4O*AvRCgI3Gq|)i z!>hn|S0P=2x&izV?-?(74ie{CZzh|9&A}&JY%CAwpi_}&vtL4Mp~+h(&GA`!weUl& zAzKqL1Z!Z)4O%NUFy;yPnc=aL%%I{4s+cG>^GVfs##!gTr5bUEmgHR+puG9*suOaJ z;I#@2;pAC~Xx19Psn#uAqAUFmHDRk0@@?{R@U!l$g*y9Tbk-fB_A=&1T6Y@Z+%Wmp zBf!=jBcdnuJ_fa~U$x;jj$*LEr#MnVSH`H11dM;_iJLhB?5jOG^V#2SqZ}&@I-tsT z=)#ZuVfUi0uz3ME+#lX>Si|VBUP#oQ8*ZZJHfdpo3WE@!<~mjcQx7+M3JpLk?fOLb zA?=1QryB|*f`&rEMWAwQLFarTyji$ZQmt8@*pjdr!xW6Y<(_~37iy{YDLs{aAxY-6a#I)1&C*_PNrFGv`|4{AAkJE z&!lyO(8PR`*ve&*uiOpnL|>8RoJ6el9>9Z~dkAPtMiB)lqyWVfpdf+0nk;IHV?}jJ zEM%Qq=sxQv&)?`E`WZ>!Gm_PK$qD!?@-1uKx3W_d-zm%J;4%;KFkB6^#fYk7-O2Nx zcc7hW0et0B9{@FwfEow@-tYbQf8Rh1XgXn@m?elZeZCgv9`tu+fL$fIF(GBoqqVz{ zZ}^?F5zzL;Pi&)>y0;^lkO$!q@IS3R8+K;S8tfDY)QEm?4=+qtQK!R*8b)m#5rVl0 z|M(mIZ=gM>8GLEZNFuExlB&xSY0TtH!v^xpbug&+`r+;x9vvAiW5>hq@e9!7jFbh5 z#XN1aJn^QYZzeuSB+o^g`+=_IV#)Sy^m`-aZucQq=?`IB1ueuz_f6S10cydS7zAqU)0{5`8hb5`Ec7^aKxyi9t4D zij1GP4E`3zF2MhgYtYG!#P5xs^4-V^IYwUhcJZ+b-5G;t_;Y*>p5s5nN%}+nTBWb` z*BknJe>3S@{Eztf$p2D*wfuVnp+D-cXS+8-=nve5}g3UxV+@dC~+wne#sB@8@h)`qrGChQ2eW5^t%=1G#VU@mB7K`1r?2 z`7n2Dt}!OJG7t31yhVAWFUnhyr}PzhuaN#q-e#q5&f99}Tk~e-gFZ8V4!&_RQs(5} zn6Lad=C31tUH%58Z^(bk(BI1ciuAAYe^mO9`M(?b@A(TctCq(L-sWRR!F4zZJTg3< z6A1vU3;44I`(SV!d>!vB#8RoUC}?=nZ0PEw@4?B+M=rD6qto1a!(6EKBsy^nL9LnE zkjGK613h>#7Mw8BT%P#Aw9mh~o3Td-%I4%pxLd9wAs;2@n-+T!M$l|f<+^(0Fy?8? z9h>+6D&W7RZNq-BaleCj6~Ivw08Y?@&8K^nBmG`2WQtyMd3J4`|2(?&Ek)$L7E@BtPT6tmK#7xA44F-g7@9 z`6G9mlDDBjanHF#esX^y`4_h$N%a-U#YwAvdGaoHXLlw4r6K=9S8hXINWR99*OEIU z$||{^IdQ*~dzR-m?{0Q>cY7~Jl@6IXY{|Yn z$5O7&so>os6*;vLr95{QcN%8p-kxiD9?yM-lxI+1EoFD^i_yjmkm^S4EmB?S)_(2WQ2#GwJLS7yM6eiB~;+Up^bW(EX2_ya2uaf804d zQt)x|Ypk(i?zEj&E%Wcj1rTz#zX7u$Fm3SP^m!q2JHT)Hm*ZPf0Pat%<+Zf;Wj#VG zKh64@kEgOX;-yDU6sMCJAO_cHSesUXQ-Im;ylnb2J%j8w>OAmxc z!`JW@yxfyo&lsLSOOH802Z2)LRzpJio2cjMoa%nj5NSH>9ezYB!9XcruM`i$ZX3?gP5|hqEQ1@k|P) zF@HhQb;m31D|A{z|6HFm;m2r3NS~e9eN1j4Y0b56jtpl({6alX;{&VB4U4|8A&S6j3LdFI(|qMs<(yA)7V?Xlw!A( z(ktFuYkaLcnfT^F2jf#0GkH5P=4AM*rU5!sOsg6p-RT&VD~uDrO7E3HCybX{N1Ciy z2@EH&)vUZ$=>lQsnbSzUuP!h?4$Gjm3;Lb2_Dy-q7{JAiH9K zBhFBXq~EC``n5LO9D!)~kx0^37s$1kfL>2q$IM*lk3#cC>SGMCsSV{N=E_XF{-~VF zWg=zL`>j-0E3|{HI-)u6*d48dJePViWty&74;OJ%*5=q$mCI-jOuW9KXEp<tw@@+ z(5lg5kWE%psuik1U&(F<|JwD4Tfa=lY`dZ|IplNxyU){;9Nbk2v5k zh5AK()EH&jyHFVVJ`2T(DzZnRF#LNLii?za&qDEm|20yN>2C^!;o7rMC|5?IxJq^H zQ7B&ZKlI~5Vf3(2sI2XW-%~kTC^|;*I=-Q277E?-gjN1l>tjYgOm39LsLe@epOEQT zMn7x*(R;X(DzQsa6AN%H`GaZB|9L=Z_1w>l=Dzhl+zoG-GR85qVgowNcAc*UUOfXg5Sr zJAFgfEBqR0!D|pVosEohVK+RZf=71UdBOrYCbZb~ex&YRB5bhhY^L`{bt+{_n(o_h<1&lUczWPE_Xv3yCcZmJ(YU)Do)=w&D8uKR;bCeP%&fIVz^A?I~ocJ}|(KflR%mPxMR?ww+1VNv|}rS)m+tH9X!ae2ZN`HJso^V z?8D$QVxI-&_>v0h{&#E%z6-HRGhUuay~0)NS5jXQ`zrNAD(&~7hhXqBvDDO=^;&+_pU77y|G-20Y~-QE?< zlS=;hwpmRQEo7(vAJQKVpJZa+ovKOI39d;!$25H| z^=e)EtEtVTznl8V&d2Vo@@zb2WmoVqH+vx;RoS<3dGfaGYGT#d4`$b~_QC8QNdF;w zcU}7K>~d!2%$yr?GWpSnhbxZdnIm1m>VcDLXn;Y*63RE43D{>w*}fj768RO*J!Y`u zXPxaGEmY{{R;R zYXYO?Y3_xMmbctmJh-yr95)yP2mK&ReSoAQPJ$^?CG5}Bd4@_5Uw6`;&7V5K3@%3F zc+=1Pq|5)EzgX{h=)H@T{jT7?Ak%%hFL<2v$Fas;hhD=rVm#W24Rz@of{mna3|_BG ze?54U^f!Yob?IAz4@mz2jZ7W=p9Pd?zW zjAKx4!-~4}if|$63&X0q^r~8rx(y7cPsQPLj`YwFT#!WT$?A>34#zA1c%^moGA zy7b!cW70nkzo<+9BHT{;_VDLAbQX#dlzkp{Mo}S%5g2RAWvmf~O3>V7h0&<%Kf@48 zU|~SVkA4>&_Ukg43Cvt3vy&p%-=K2(!S#0TR1B5fklbB#gcEKD*wa)z1(TH+cA>%v zie{(ia3v}W1NS$40fOv%6a+BQFBok0r87lHD4na{>Q6mDkkE($ves74g)J z0ly8*T;=FvE2BSMXNi$A$-O`l!KHX?e8sTrs}BWc$sTK8ZNE)t|_*YBu7W}V0_(-LTeagCW1 zj!-@NN{@n3894#;_8BjjFz^6VXeR;W4PJ1aV3g6})j;ekuAEpB6`WokElr!NL(N;$ zBrLfhz^+Xj5sf|Sq+k=lK9M1h0cjf*R=j;3@zFW|35}x(%4L&gDedxEE@>GzFHx`T4qFeVkq1&mF)vE$_-Bih?RTB%|G7(E{=rW`OFoA;&5WcVZ?lcpPFI&Nt##VxI0+qY)EHpg~;N-VOkR*j*D z%4?Fq&e#nCSB(C%Fj6{;D)ENK^i`betV;ZwDuMqS#}q-h2Cumq!lUjc5;nOS2RIfb z7h#?fYE))s{=s%>{K*S>h z5AiCG$GMD5jdxs7#$@6g~;#-NgSuo#Dd_(d#Sm_|=weAf(XL5u48Sf7G3`Yh? z{SV&X#FF&onu5$mO~b?H(rkQ)q#vwXCI=iEL5H5kJ}AQ)|3|eYiA#&LrA+F14ZeV0 zD$n5^GuxZVJBckMZApB@w=_|2pF$KI>fu5Uf-FM;zHA9??fm5Si}`w98ZV|9XePpW z2*>T(y%oo~RL6f^~ue|uiAa$@gP1(3;i#1(6XWB{xW9=R`o#Ik+Y6pjVxUjmhaI#!b8_p?o6##U|+H(MJQ|_ zN*jpc2BN$|h%IEKO^lJ;w2%L+HBDF|o6shlHZwK>Fg5`&HUTg;)p?)BKTiF@;ns0- zi}xUpAFub`;bU%UG1oh9O|8Hqj*)=>ca%~Cm2DzrB1;KMsR`=G;6B9b1hSw_0Pqv&2^Mz*fCay=y(M>vD8gt#u}Yt zp>rmesMQ$0`WP;Q?RYPSZxa*LcT}ui{~`5jf0F?0$&|>HNCt6G z01tBGK~^^Pk?wM>KkH1nS(AFkl#)$3TTm-dfPT*TO@X}yj18195Je0`8DouZ_aY|W z#4_2IX9`)6QWm6`ElZIXki1Uqzwa-EfN3x8s%+^ zir97rUrx~$H=?pEf^5r-|D5tpL-tO)m@^mE5XX0*@q|$sh_M-n5gPCIltF1w+wf)w zZ7VglnemJNvBrn5f=k$nP9kCbXH`KnTmG80MdWQesUe*XiulwHKXD!F z`%frT!_nhbVSqRs_u8yhPuIzt`uqv2th6DWhOwBMLOBH}r~oAupeTWT$(kIbuz@IT zAc`A^@(LMio2a$;(#7_2^t-ZKUrve=bhrkd2w%_qCw`vi;KHPKWVmlwbj9FAo{2nj zI;zy=iF?`OKaW8GX$xQw$L4VX^*5;E%#CSon$1hx!l}zGxXReQfQvt-)>!U#u%KO6 zUCrp)9q>G`sWs%XcCbwJq`lTut6;`#W=SKIu|~^T*=3!+5HKvR%5>N_T!*5XA3B`J z;D*m-$1pdsoXz~Y#4E&J;kjV0?8f}d(b803rWy&<4YG+3p>&c%G;-_)wToL3;r{5S z_UDEE14d{UID%KwOt{iCV-F3~C!&WGHf$^0Y+m3&Jl{pa7Kj5ygK zEhZy^$rl1zz^hls!5+*LM{6naTWhD$$5?xZ|D?HEz_?<=w1sC70n=F85L+b}W}9Sv z7aq-%YRzFIkb@N_AxG5wcF{0q`Yrw%dv?X~`zw_d_&RPj+2-(IrRF0&uJ)_2FKqqu zON@Tx%9Z|g+;F%Kmm;`RLu0oMb*JVam~flDCoAM(E_vdd5y%Pv7$Uh){rA%=@sL59f&+!4m-Jvd6w=WEG#nU{ayl{lbj z@i$c*-)@oH+>I_C3;3Su1bG|#u-XWO9cSVgZ*r=B6e4^DNP|7sPZoig9{u6MvkHy` zD_p$2hH;7e9I@xPAd?;$a<2%vv|1(Uue5V3N6Gou!1z&eE812*uW_%36Ql6uD+rIn zEaF$95DlM$+4v%kYN0d!x9Uf+wkxyT6HwnN*FCbae&O#W762xQ6+gX2g|#hN<-b{4bT>vQI`_lQ+WS;j%IL8Eg1w z$>+2Ke@=ej#{3WRv!XxatzMvfwU?DpRkITA>o3+lS|-oseEddtBij&-VYJ4;=7JH7 z)(C*9{?X>u;ju=&`v0d@+_*cL^>OlCt>Sapd86#&Eha*XI}RY}Roa zL7~r*KNI~q`3Jl&QEN!19enCL%zswL{ckm`(>0tUX*4modk5{xXuT0lE&icM*C!bPsI#qEPyTu?z;myKL8IhN+&ISPkBOOdmaBHA3WcMg z7@dNuppX7PK)@oGmgx`E00!*2I{-o(lpl(pyZ4=AsrsNj0UXGq(E32L{`Fz$aufNNex_~ag zbs2opFiL&}%Yb7D6(zdyEK~bmum(L+j;7v`(7OqGM~YF1cUo29$UPK}M0)J~m#MVd zOb%dYnsw}DiFbMO<6ZYtc0ixHPw@cAQ_u`7vQ*P>yiF4GIf*@EsH6Wgm^)m)NYudG z;Yfye_4zK|aiiZ0lFQ)ta9OVAV@hPxgRy{aq5-f+6#i?P)w+Uw0n>49;&n~#*YPed zQhyt+JRtdYeOGrF#tpv{hn8>&Br%o*Xi{2h=yj?NUo;+ywbGB6A|EBLfW%O_!~K^& z=VD|>{PAQBpAZgTfDo2oV$=K|RZDx6yhVxo*sRWAzmC?G*O=BRZiZ7UW_xNSKc5uf zlM;+2Kz+2S$zv}QvC?0chI{*uHSN$EMjl(^Pr`z!y(a(-EllAB!M7($IgjO^Wxz3A zX^a9p4h2>j%$0j-1{{o)_Lp$4vAgg z%4Prl>Gn|Tj(?G{EP3u_c!#GW>RQKMI(_SP0^k!SC8vTuX|naie>knKFf|p+?YRHG z9UEIjRdo@4Y!3_CKZ4}5*WVdxJvfHT=Q0e7xZ%&kbogN`x+6u*tFR12PEf6x#QOKC z@ih=UOSV8#%;pqxtlXF2;vZwwKg*y+rv#__?G!Q$14EF!8)>fcw_SIi8&3m6OWCa+o|k*6W`N zl$U;vk<+e1B83-f^O~{!Y8X@_9V6FR%SFe+tC3uIL4e>KfOye5ve-WT(n}eIPR_c( zk}d~mQI-Qxw8x`pUxTB@({SSoI(ZZDHg`9z<1BTi>30?=#*NwDfSP57QOfp=enlVPO|_VK3bO8$r_DNGcpmGi27vp2`m@^hM=jrf z7}~>OREe#qiF(KYR{$thk-+NM7@3P^5@JRImnC zBo=U7uz-ePeI~Jj*a{j}3d7LCj+TdL7_R_+f!GT)42RYdzYzN+VQ(*nVWq~t(bhhk zbKGl8n6@#~u5r*ej>(3T62?BZs?#nql#6f!I$o*9N7@Zuv2QzI0FEXyfzk$~qr4CTj8f#lbR>iW2|RvNd7jtA5t zv`E`4wxK>zyo?Oy0{bRv{1)R@4QhxO8a6Y>141K=UP;2E{>iQg?YbKl02~ylbbX?A zRoXZBT)&Y9@jkYu{oKk)bTi^_hpw+3-v`|D&!411IAOhIy%E|V$9T%7eZ zm&yWPo2VtB7Nb4G@KNGB5Nz*Ht^U=!(EFSwb z8R3!bNYt<*(=^SP#cG~@-Wj*3V4LeK#C{eAp*GT+HGBk;a>QAYPq6fECF>~jWNYck zlVc$h+6O{?j_|%i-Jd=C}b1o~J@$i=_C*IPN_QlC*c-d^govhS%CZ0(sdK+JU z8jm$ZJCS`p>7F0T^PJG8N5vTm74+{@t-5m24z`_fE_^=sYF5yzF<=C;Byk;A=x*Sr z0eJiP1H>MPR&B9DJr=J3aR(s0N{7PH=v~KN>s321uq6*=($IOzQf0YK}u2#7}@iN_33myL^rSpS(9FXJjHiyr;*v90*P{(+U zq0i~SQ4t(GG?gq)Uvvn}fId;t@w0#lPP>hlUX~c5<;k`=udpNe(@K~6L@1N&5&`code+*0GcK+CTQaTT-_MHMil{o-=l|;mn zlCUzg)Wc7Vs3%T|S*J{kh|@0dM;lF-%t!ucKF?p1DAAfqaC{Q8}Jr!Xw)*}y4oRKMhi_RTt{oL=qmY4=7wzx$)G z#i&jYz6xzbEX?l|{2vHo8lTP_dcZ%Ljq+Q9ADE4qIR$Ak?RPlLYMf=B!H00xcxt@t5*GdMTr~L|iPEqCy{O4v`-|%ey$hUC zotDY?DQEx}av_4tiC4KD|5uh6Lm)yM{+A+X2TZDIFHQIlrqWf2)FxaV6aW8;iOC85uJZXsYk{e7qlqPr;z;L^b1o=)-cG3`Ma&U$Q z1QjO^aW*G{GQ(C4Oq_G29E*z>C#{MD-qL{na_sbob&FD($k7w!)Klee7e@3pN*4(_ zIo>G>=i+PdPEdQ`P^UU4xDXN5cf5vuOfooaq)QLSo6(nOWdcWKuts;M`;sf~;4~)e z)&LQ|rL=D2c=Hu?Wh@TLpX+${SX4~th77c$a$(4kUxT_RFy zNUfyoJh=>q=FpPZkibDk9uUli`&9`zf~Pnappm&5*e!~McoW?*85T@BVTdy>uz8q~ zVRiB=r~%hAi8@JJH=a{7i%R*)L!5d+_ro*;YEYC|4)JQHSJo|tO>kgX$x{$iK`bXA zPeD+D--base*K_E;cCK8|BQINZ77UX-5p7EC~`e2*0m^i!-HCc9v)PHeppb9--%Ao z4B?;{Ri;l+0wcRR!8joGB1CB>+$qTr@k%GN(Bk7L^&IcAiwW10CMa>`pl1gR?HE*F zGQ|07P>s-XHz>v9SZ8#mj^tv>d6GKN@tP?dN_K(cU7Uu4NpLk0l!B5BO7QCiC7?78 z9KeHuN&I!DW+)A+rlD@R!C7zyc^*6m^reJX29#CN`-hyj7@1Ep=Dku-D9u|s-YXW( zE|iAPCW24F%`8d_U61*{W0l${oC`CfEk?FokqBlVjvRB$Bgh#()Y&gMNPo}L-^Kd7 zQGb8K?@__X5&T`OzhCR`K~Qm2VD&9lJSG-zwEpr z&dsj#%Yo^3$!q_s$t@RE(7>*EDYQ|IO{wv6rFnB{*}?H%*kL%6*?$gK{D(X(rFgg; zew2(pS|*<9cng*2${~lKYAKwOgAbNNhRUHMk$lo10#z8U-UCAbY<8u$Gb$~lnfac!L9`G{Ys_79`GC3 z#8svALOF1-f4fV>_NzpfY>n*HP+OkW+Zk>*DmIreXk*IeO3Tr1^xLlri@8QA#t zSp!o~Xpi5Ja6{R@uM9ZI@%kx>@dT2oxxz_liwtO`uqy(~A~*nC+TN%_W0VC?$0`~~ zDmMd0Y8JJs!`4nw!xqD2Yg3m^QOg#=VB6lT4%-ez4OxjJ3 z3ZvgbRWY!sX5*FKP}=sC0cXm2;29 z$zg{@sK{YQpi5Gnes&_+RD3L_Z47})qy(K7AJ9SZO5%e|I|z8H89U$$9>v@d&8 z9#J0Si-C5Jyve~lHmro)Xz8Ki}GQYJci@9hFZc*5j#TAy`wX5Sj zsIVh_;mhj^HK2L3$mOWEpBRkE~DLYePBYV5TM)o7E8>S9?rLd9xKBLYU*x0#K z>2>PBua=c{U~f3C15R67Y3hI|9M=JZ#&sajP)E{rz)<2kkey~=9Vk}R)Pa6Bh-p1E zf|1q+Ha^^^b;J1lxWdNgbs2TWz=nUl((CyAqGhGed&9BMo0QG?{D#7@&jyWse%mTc z`)nw&&+nxf=(E#;scC!;6-Il-x)Q;xD+(JQ5=EwruuIQX7+HaKKZeoPH?lk|FRd*P zyFCLZwW}{tdX^Mn%yPKp>DVQLlhUP&?2j@1k(RAvPjr?M8c1iL`#avzRDDbm zlejg^@m{rMmUg~x%Pj4TVc4_P^3cxjED!B8u(7j1`#EE0Gus8yP6NkwwzO>4PJ_mF zwzq=TPJHlYNO$Pr98T@|+ckD#{Ig*D-R_Bg{UF--uURQ-3 z$wfaM!AzeRMmh{oo>tNaP46Hp8-_@EIS_eKq7GT)WYaJF zhq4;M9AfXh$qcJWk6_YEe>a0%A4Abhc+-M3JrnM8OIl9^Q%}K-Y5q*Ow!X2)^(3bd z$CoNFs7cf6!p#azp0K^{q;M!*2Fr-i7zZdS(gA5UP+?RxWQ&2#sIuJB5fz7m5lZ-S z4Z;u+HDJDlIrv_wa2fW6Tz3Zsq4mm;hmlsh&FP^1j(N(yl4Jd>2HW{ze9iaX$v2nJ6@!~=L?XX*(h2e0CA zx)I}fQn(LNbGbEBl{(LKNqsSL}uiEH7F(h2FTH9OAU&`>_wD2l)+38-`ARWq>LIXr>ul2pDA7+ zTZL7?epU?isK1Q3JjT_~b1sU4fxUo5NOpbxV$#+%u^H3ZY^PF3c9hI`Ily( zNHP;-lI(nyF-bOC;f8YR-{h>bF~?EV18PwC2i467sX6cR1^)( z6vg=}VvC|d;-VO%FxSAw+#6NKn0t@HaZxOgbWwatgW{rS(9EJZQyENA9IS$vyrCl) zuCOcF==8@b9AX9eX{6_I7Rx$JMjR<8EKA^=&2yRb26YIgrTK>nnR0v`mlOxGKtU* z=SyKr+zI*!On5?RX65B&g$HuW*YOOZww}v67~`+hM;9aX~^kE)>|m})pynQb*R zNL&qL6p3hHlZfL~#$@O8>Z00Y?us;=+H2A_L(9W;Sa!)gG{;u1tcQrfJ%eyfXc!;po(A= zmH`T5Ky@evR0=aK;sKRXm?H6j%2ISdl>yIF*bJyJhpSN(11c1{m6i>C5Qj{6E9#1y zlI(^$po%DD!1!vSGT1Sd!e&hM*95&~C6VlWITl4bO~HUcLrr61V5AWW<^tR8b7YkX zFR}ChX28f5ielhUEJIKd?^m>;^cg5a|AJY*qMqa;M_;m>u)kyHGz#O125N>`U(AGi zS@RlVMIjR&p{tuo$wzC@POio#vg4&`j(4_(qsleF*_Ee|!7%~88Q7GUGOLJ{?ka_Q z%44{M%kdT~))ZgWS_SMu#W*WO6M)mIb3yyJ(lB1Dha;78&V_O@+r?*;iv2~bYs2b2 z&|+PrMuUwZ^E=9!k`pIIuvQ16!*n2=l$-+TgFZe+F&eB2nV$}Wnly8~t96Kq4n9{J zwM?Up8e!2~gG7q3GI?czkxHR+xJri_u&{wNX)l}u)z;OyT~TbbWl3HuDQd@N*Ayc5 zEsYg6MaICU$P`;T_7CczJU(Du2%1O-)RGuQLO*4P`K*`*HX1fZ^fnk9>D~kUYAxS+ zzk)F)z=TFWa`1_{Rx7*({BbgafMH@3$RXoF$~Yq-ixXR1xe_1!!)wuZLEGmV&{bZ* zr@qiJDV8HSh`8lX)a^-j2e|^}O4hh*TzMFGO*>xEP6idoA*GIYhO!moO`y*ZQl?mE zdBuI7nDUL16HwXCQ@Ev^g8pxb!fmCPRb3^TNI&FusYdTeDw<eMaP4D#P&3wBr_g{W>%D2mxjH#rauQjF$hz(~dy zmCeM`H{bZ%xT!SnBL~BmOiJ4{+Ppc;R%VlEgA|4rFcA796n$2GIDUF=S}k_R`^h25 z={<<;)0EbLuTv4D{A>&73HD1X_)R{0i1 zW94sK%L@j{@KYTxLYp*^W_wf6IHVa+Laf=$?#~tGC`9L221OH!F69Fo#N2OevkW7_ zLX-XxC7mOg6y!*RGDrH`tYjcf+aukmJDzf!4MA~*x zI4Sjtr5`qQW3-;*^|95HHuu%8BqjBFOW*!7=-7w?!Jg8q_y0tJw&AM5v^fJ5_9YJn z{M$AZVYcL=vrD6nw?TtUWB8_JV`KQ9!p(67kPOAyk`HW9$?+IN+GfgXOQR^#8f3J2 zwo5$-TU9vJDqHF|l}k8}$|Pad7NPY4Pq*8I zoMGRra8o(s9GQAP<{Y{qY6e~RX;6v_027g*2Gya1rL56)muSd09z9Q*;&_`hv?(rx z#KcWkYaokhI`TV037@Ay=z!5!pJQP^Pq*|VG&JZ1R!RT<7*8r3V6BXsya)Zk4%1A~ zhDLA?yxDoRE7#*|@>nHSYPMA4jXuX4r&tSI%kx=6%5nW6qE?cF_kG?;;Nah<;971q zadZDph2a1!j^G@07av%9F6IXj+yJfe6KY=v>3jeNsS%1!r~{U9Gzhg8Rm#Ao+4x53 z7|kOgu28s88a0*kmnLu?@j=)##|m;s^hV2!%6;q!I9zmN0$(luG9eEqA4_6PX+v=e z;!S+j0=IxX<>ITO&%1IjzC(-!w)spiM*_@J9#Oax-r4|tfuXZVEwZpHj<-}{lnQw1 z>l!I$YuVDMlN^MJW}Z?oiGoy-!nx9RqMU%D-$hYJns$m{4B?BV_b?m`vq5Z{TUfY# zN7!(qv4PXGWeVp?o6#~JHDRR(frZQd`yC7^tAQSMyTNFn=6(wIk^Y0^h$B%@ z6wQ$yJy78lZY={L{`4G*rErMZiWH)WG$=a{>=SAbj&dNKr(92ykg8~Hhsm)> z%$S07zEVSTq#jzXGKEo~;O_+%=A@~1wn+!3NkZxQ!m{~yOBd+5MB#yW9m(-#DQtK? zQhpCRFOr)p_514z+~-O()$Go>*1RToqX)|ay1p9|^E6o=S00fTz2Ta|#>fXPoP}=n zFsldC#ugYjPE<6Md<+oZsbmx;@xM@bpbRR}ePDxP4+}GspEL*!UpEvg+ahsV(njGx zi)BaUF`3d#+IN<&qa3e?5>2KYt}u?4Ax#V{I0o-{2U>bI#(WXn6lPafn6zaneaFHQ z!y*kZ+v%-zjWoZpwCNz7CZhx@(WK#&3_$}M!J(EO)|W=;rz@-t%*WLVn|$ANv$26E zOv6PcJCKa|g>vMSOp4=m*U&7l70z=)->6kz~n zC|FTIg@|An!_}AwO~cq$M2BYRNMNLvfpNgENV@fqQO9La@-xtE$?G5k4~s%gOBTuI zwv~Qpu41%a28v}8)ISph7&Z8Y9%j0c%w;}sk36Dep+?Tt(13Gl4k;s)@KOyz)kh&( zY?b6g`C5fBL2jeREZ8Q&Tz9Q$U_*taHDVcIuCiG6F4 zW}t5+iW=XB+aUTjHiF@sfsJov?M*@Bahe$l*YRhz4W>VP!?8b=%4Ymopm6MuL1TYz zwhGh!7)tEV;xq&OsZrGU^SlkBKd(nH{4uccr^KE;qd%h+uH(<~HkkhG4afeRtZc@g z(-e;VF=*`18CGH1A47@#IV;UTe<~C;{@iSX=+EsD41Wx4{JC?NX`Dxo#(+^_R|v0C zI3=yy%P92e_bQ54sxZL5U*SNSx0mq!n5aX@iTL};&`C1+vIxa2CRfg!nt{STqq&J3Z+3zV z%6A~5pp=X}DuQ(qm`2T>Ok`)bL(^>C_LKbv)kS+^%(pw8X9hNTHbUufo*kvA$+IyE z$9ZPZIM2peg>~}G5aT>M#`4%aD_7Ly*)=wZc{VSCktPNl6*d}bi=sYGHB{R}Q3=d+ zkSrDHP@aQcs%S^)F#u;%)0_-CTTv6V+&aS50w_7pT4m7!JCXoO!CKq6TeRS2Q*I?& z*OOv2z(SV>VTj)~f_3u7LqDxF2p+YS_MOrw2719HEQzIp5}Xvz3d+Ei3<`K`J}BmV zGAQ_Y2 zhaZ$rm%{ptOt9%98phmZ8oMiJ;mY>O2a^p$Ck`o`!L&`huV& z&;-C<>pjS0F#I#9fJvtZ4&X6CDVFK*?i5U2>;~H*Sd42X_*;TB86R*T@8F;ueoYF> zu~6M2D2Fk90`A2f95^Tf6M|}RjtaK#7~)*+2a^!pl%N2=J%df=7f}xk3a~zTQcwcn z1A|)R#=u}Z7GTE)WuTuHlwy%{Vo(ms$w3vOIXfuEV)bdkBrNTo9@OOVcN5?Uv^MdU#;`D&4zQ+W`Fze)?8rrT+1hr7T5Sb1SmmrCdqSJy&NZl*3)S*dT zjK!;DP>b^I1zgnHfHI1l?Gls#=^b!AYee86moE#ru7tG2FX*5g78F73te_fo?bM(I zzh?y%po|D6VVUEcfU76x1e5T4QBVuYVL=tvCjJqW;P<3p6XxOn2nt|P|DXskOh&bv z92DdC+<-IozQHEc=s|(AhO@e4nt;l*9hD6aj{WiAkQtAPT|+bsVhqDL0}qPtKsiEh2CN)iLupWo=Djr7 z1o(uY3h)U*aXVII2X%9Dz{d9AfNku-0h`w00b9}GK^1r!2W8-C9I$!J57;W^2M%2M zTTp!=>r@4Qolb}|dMnl2grcr<`Fc)Js};=YHWY8^k>0T`tFslgkkfv!R$a%sSPV*b zK>8l66&YGLsn!}$vIElhV0B(jYb`cfL4j8McC7nO;L#Tu)~x!{q_Y(FL&J|(AtRGY z5qf%1eDM&x5LqypDj3=^r~&<~pa8#pf=x((LCyh9GZLWYffA_bAg52kb@N^piXE)I?0^ZV7W#dwtpe zT9{CyNJw| zUEuptvY_5g^{^nJbSzI{ZKqsetk|`{X3JCL#~xW*Eb=If5i^`#qi}txf0n$M^DTzf ze>_h{qoDIMgfEfHaExG6>g|*)%X%JTkZL9O)wSgx6mFnPWACgd``_i9sZ#DQ$6msg z7f8sF{HBiAbOT|eI)R$$Kon|)S9_RoO3;Hbe%jIECh8i~bqg*)MkQZFUtKglJ? z??Ep!7&{xkwU(?@E-rxc&D@k@fg$4X$vX;mK{@Dh%!aqpa=Z z(AyLEY8$qEK9)~m*HN2HBKc$VMw1KzqS~y1A-)j4-j$c#9WHK*=59)@(jUS$P4c0n zJcjG=WdlC5j#I6#QX3Yn2g{f4&#qjTydKnJm1?a2;x%$iz)scuuKem=i{R4NN$P>q z*0Wq(Ei@n1;3OrrmhW*Z5Voskg0$!ja$&I#3*8SZjErv}jhkW1<4p#&m-fAQaIb{# z!lDi+5%ZM>(x^W{01KvN5$KB|m22V?8r+S7I3NZl-uE*_!x0Aur3lo;=2nMSKuk9?C7@ zL&(C^y%=)0e}`;WCZyKe?a9K_>?~QDy%|%le(x~=>-{&QbjeIlmiX7gj+mSW!hI;{ z9W|c03Hc%UV-lb9eJqe`Q;VRvp9b`nn}el+EXCKq@k**jHbj0fsh4HhS=T-oJTBjp-?O!DonyqNV~mVA|U zd$zon{S&+>*8t4s@yapk5eEI;WWQljjqgwYNnl^Rd-@5r9gA-dyvzJntiP;tUyZRY z7OT~;*2u9M8D2@PeAzZ5C8{xb%*K|+Gd_5vX3PSZDdcy)r3_@!2YQ8sBcmcBv{m5HFR4Y|DH{Z4+hj5&t>@6II3V7JNtPeyH5qcX?lVr0?3ka{J(#!BR0~;SgCl z_QRv4V&bzC<;vqOKVGgs;m#A})f3*u{(sn%u~sLL@=H8)P49;CS?Z4zzI1*+O4!>B8WL4>=(emZ-*T9Y)D$z_@<5*XBxvF$!soY)qWGUWG zYD~>-r31Rw_S@-p2l;Ab6|!NrVzU!+#h@n#$;~5PM8qqVRwj3i_*aZ!@2s(OD#Otq z4a}0P!8o7!JyjLTC%tYuKvoQ2i#pmIbXEiGhGQA58Q%gZRZ>G~(n#ckxuwu{@!ot@WqmZ~mmyGT{nHC<(Kw>915=I*O8Z0Wh7r_}cR8b8Hf7t6d6 z&m$2gsiB$(ZBK;{ioyqM{Jf{|IWYPO^kxRbIHtYyjA-?KU@{r*F$#y$2&2L?6pocv zX0X+!gF2!P=I%&q7_M*u_9LZ58@X@5&VjP?$Q4InzomdlUnCtl8n{If>=#bQVz|N> z)#GsDBMNJrtxiVGSJaqh*nF9GOG0ibd=Y0UD>SOuz(+HzDEN^U#XM892O00G%$|sn+&;r zyW`ks$Z3k2*d9p-v9NrU5mfw3EXAN>6g5)Sb%Wl?2rB-yu9Tuys&3Fb89|+Yi=}Ac zI7N+ARo$SMGJ=Z!6HC#;5sDhAc?##t^?h#d!*efW>>`Jc#;wybuj}@%va{>1uJT*g zFS|)~_c{B?=Du(AlXnMv&qQs&vWY#vZ22kY=Ny@t`$4XJQ1Dp+w#=HDpn@qF_9&c` z#@KOOuOd-n_G8|1Y{%9r4TrpO#sK51Uli>i6?run^!!^5LNUi_jwZ4$`@S6c?BIL3 z=KV+Pl9m}ojZ5X}AbPthBj{6wVM}>Ju4!D=L>70c=_0T8osBlsacFZ~`nxDK%6|XAB`S*A$kg2S@?hS3dGcZ2wmkVNZ#xWsusKD*gA*#|kkYBD@En=dbqA`$ zg^D$kHdxf`A$N8C5VX6M)>WSB@^cp+yN~UmhYb@}AyWPfg=14IGlFWOP!~l_(1qzBx^YKF(5`e4v$st^B}S@DVU3GY zOEQ8sD_n{Du)37P!xkw@h0*|>SFyseg~upr6fVwStFFuTP6pfC+WmEv&+-5~Ez16N zP(4bHktNBOFoZo(vHdZFEeBSnSdn~%?-HTAQp`9;ubx!gSa<REbF( zWXKdnkpdXlJdzG#>G~`Rf=K}BsSRgCCy`LpMAB8KDhSPd%G zkdCq|s~U5jX^LgZ#TVns_g|0*VcR%5mYV$(MRY^a!YXfTOqqVklKZni=aebU-4Xe4 zPX>3`E>_eQih3z(?7mUqe5sF8W4mI-xcm19U`5JTjL+x%3~WJXN?{MN zBR;#0Lz&Ow({Zv9FNffxaU7f9-Nk6_iN5aTh&O74=O+Ij?%q7SiXwXh?t5<~ov?-- zWxMQKz{`%ZU2q{PXjD*CGzlbZ28e)&BWh4oRAi!}g9{oJ0TsunIHDp(#a+j!j0W_{x;x!Bmp{J8-}ij|z|E<*-c#$TQ`KAbOOzl}U>zunmC>6+nRqYz zyNLQGdSgtz8@mz-S^afF)LFxs(^_@tLauyI0L2=>s&Q?VQI(mIChKq`giKg;qMbuZ4KRWT~qL$Uzi|2dz-UX$iN6FwqqpL{=D(Q6~-b_Gaue zuRf(mbicqm^XdVdm8pH|8#K*7nAA;CmyZ&Ko_KKgYP9@S40OSlLtc%jebLP^d}s09 zn5vD{#?+^=Pf?VpQxxjx`&e$TI`mV67Q+E>P}h3JU|pRqxX|=i>}6Zso%L;&x;}e- zwz@0(YK-nmCS>EIZg4-Fv!2URuQmP(gY(Iuq?oI&zy}@S^RYu2U0Ce!a6~-I)b9$gCo@&;A7$2s#d@RJyCa32btY z*M#rltBbux=pr_`3l%p3^x^u*rU$B`(|x4Y%Ia)o+|M$e z51fxzzwf0-qOUF_8kob;SldNjKy>9{qM+S;(Zg6%mD5G_LwW~|B8u+q%UJHIZo=gdD`O{zMEMnb&>5mCu9p6+Xb%gCxbtm!3*9c$S&W3aV%#=r5)lQ-T+XsNnkxb+!J$n$i0>R}Ab zAsoz9eGh>R{V$?^Q1l|&I7V?sANvJmDCba5RTtZgPQ8mm?eG}+?Wpzr9BQgo;2Rle za1MzF+8^Bt?ZR=CAueupRlRc6&~ngjW(e(Yq?OTlJVj4X6DFePZbt#IYptMo`K+&H zmp_!W{`r!HAZQkYw86~8vAAeHLtPoU30p4?nmGY`v65~E%8USRr6qJq z6rz-}Ix>Qk41xs z1P}KI@#L#vwzG7_?D%rNYsSCTXd&F?T1vmva=mP7vtBl}P%GQQjj925f`6U1@m9<( zL`+}12Awd)&PVA++hveXvU4C0wJGNrRtHaiWjr^Sij9|3QJ5;oNBVB9*$LeAi`drt z6YyKdH|+BHUR)0Fc6RN16YyJu+iAGFi{Ey35`7S{3TO*EI+`IplEM zL2ToN>X068%;7iFIzP+hW_dAinGji0oFdiq7t8Ct1qQE9bu+p4~}| zd$SY7mz@ETT@kD3?B+YkQg&Xsk~Lg1Y z>XplOhiA8#ac_2l__8w~vRlC_j=4I?vblQX{CC5%JBe{`c7ph_Ga#}nVim_+on+Zu zJ#qz{Ax{AH$3ElU?5=YVUv>sWcDFM@XLp~IEM@1F%N-Zwj*d%QpGIaNLFD3$4uc?z zYaDOJ2JB?vCY1~zhcm*pU;}o7ZsI~{fy7VXSUvO#JvOEdIEc)2?Tr$bpqscskoeh- zrBTV_PItQ{4)4L+~VyqBjX~fy3#uo_%=tI~}xGK7ykx)u#{ckA%y1 z5)N^?U9Gd6%HC0Dsb!PpVvf>T7CBDT$x;V(mc<;UvrHlD`q@b=8I)ZI{$#rbg_~^C zJUQ8>>1(o0v&v+foc$!5yz(TQ+~*{l{M;m)Tojn-7BJC%(1meLw#od#ggnV6gMuzN z&;kcCVyD|R?@X||*$KpUv+IC&vva`j=4}YOriNp&Oh7F1?PiT>;aPs{xRnNVHm}p4 zVHpo353@3!XIbyh(fxSh;QDe)+j(5{5t<=IImOJ1uALxXlTMns;S?_`O9TPO!? zwTnP3le$_Nue?ceGi)Ovaud~MI39grJgWM^KDBHq+5~eq;|mx)$y0$JW&V6 z>OdB2XRAK>SX{G=&m!SuYdOoh6k67$SjD(5g_d>BS2EtPype0Ex3x^NjLRfs?<_}E z2V6dwz;atW)@Ef?a;e*^cu(A#W?8=na39N2-0Z=0nnJ$J&C9NW?>f&eMEm2`(Lc$N z;mm?I<@?N$Gh3_fgVgXtJxC^RmSYIG>hL9#o6);K-TPy+C(G`J2UBe)T^-1vOsFI2 zU#4Z3!H>+amjlETX?L(wK_}xZcniy13Ok-Z0T27G1F0MCR3Jc4qcv))4#wq;f$Fp( zj%wkFYNpycu|d#>9NYzs%L!tO0?bh-J2EzPuqz-hu(#`6uc@DF!7PqKt|rQxYkkm1 zqg<;zxxVJe3eVWVpB{b!)ew^jE_h`*GJP1M)@dH#wsjIe{;LZYLBQ7}iIMoekX?&d zlrIn)66Gzr;X9xwg=T1SD{9?$kbrvkeAx(IPRtuA!VAqfMZdnKx{~qw@ij_ z%H%<)OqHH8J@3f6Iqllhsj2$tVttH2NK;WPiWP`OQ`L|17R&HWu{;PB%bKpcl5DH9 zBU4iqLSAZ5(q$^*2#-ah`_LW~i!udbL!!K8GJI1e4?<-s_mpXqBRfr1K82d9Oc!ef z0wGOBvDAb0W6@OgqrAm3d{ZnB!ac|dYOC7e$kbHURBEcVx=axS>X!-aL9r-PAT}h* zTPDLdW%3|YrZ{J(%QVrEou;x*rl#8F6bpg+#X@^fEETJMY)F)^Si*OU%0ZU?yd#TMokH&0I$rw) z1bj^e_f1h$CW-Q8To3foIAbR0#`uRLQ)ARYUSRjoxqc(5NMpc#QxtMFQQlnZgFYJN znlp{6p>sXNk)^tD*=O5%PIcLT`^PrApJJ)T^CW3#KJP_M|sO+_@+!Agsqjc(`B0I$WBw$qUFxED|E3w=4K2u z6~&@hfmk$E{U~p-4Br&XgHW-oQ{5iy?8wwqg^-upTXmU=IKp2hv@*dhE!h<~d0lSD zv1S@#SK}-Sw+d<|SUqeycTCuEmTPe$GsP~$DM=5T&eHHY8q4~u%X7NrJ+bnhLU~V? zyr)Ipvm)>LkM~T+PP|R8NapOKn;F$_POy%(Yu=b(t;Oq69H>M@XPcJ(gKS#p_p!?v z@hsN8%V)dpIC@FTLWQ&KYRCyY2XdBO$iJR7w0C7|C*dWA*cN`r*tEcG;$2#LmvnY= z3N!Hwrn{!{u4U}_8N{i@sseBGf$1zJypy|dSI(7KlQjP ze}9{noey9A&O!a*t5~IuYKk+wt$x}L5A7Kzif9+Iiu2tpkNQ{-ez*tk{vu_8v#x%8 z=4^s^CNz!|Y)4oJZP$y!7NaPA(A`vZ{ME?COCDL2< z?u)Nju#D?-c=+uXmi2j|mW|5rCtVdSYn7uJ*D6{zDyw#qiat@knq_^W?3Len!sUFx zvgUZ@$5)v_sAqaBo~PEgAxK@-#o znjjMF;%HHVS~dw5zDx<~%LX%8#$|&ZcxsYmJPrzVublAk2YdK=9==yz>+myiJ=Vx* zjl|`YFKrmdyPLW}Jd?sv=oei7ieKu`Q1WsfK}N+5S{bX%;KIoAs$8s_%Nca#CWucK zh-~9R@x8hcsE|fRAu}&=a9oROp{6hMBTcVa3d>kQXd_L0YSSCUV`M9II&QD|5Fu!LFx%Q`jt1Le|3a76 zvLy$<;bfbug9l;LFMPQt65H6I-aG~%pZ+jF`sWy5GJs;{NSsD9Sp{Xieh3nrf9cP?{ z%f~g2!-j{Wk1DxAD`Pg7T1t27IerACa|xIqn5?(Z`;SMFOGjG)`ao~c%4o!e)4DZx z>QSl_NVj8|y#Lp{SZ)2Is?aGj-NkYQgz<{_P1} z))*QwR7QR39Cg~WHH-Q9Bq%o4Is>1+z|99nu%9*zyO3o}8DPH3S{Ch2w~n3&%lPyb zCo7n0v+$>=W_h>_7v7cj2(|E_WPHt-)h_YrrMzMOc z?(X6esL9EG5 zR6Y4FC&8{=tqd(kRoCvY2DS{-N+TRYaazd)k!dP+a4m46;~ z>2&a7{Ux$W4(iYQoWQcJ@{Zvzkx3AnbvZ~m6R`O(=Kf1r#?}Gwk0bA+ys%_}9T*vQ zVB}`-q#rf{g6I_Dz1rNZ*j>I|$uma*JPmB237JDlN3 z?340!E3=ssXVNhPgEzLt`;s<7hHkX z7Y3qn7S&*MH?2{_Y2xG@PuOGG*HI-f1HIv7WJ)*?Ctza0shG)G>{n(D%&q z6fGC4>mM2P6s_Mtd_|W*Z_$Ft(d((fXkR}(A;hvLk&&2mrZVVFB#6vo4vK^|+snMz zfR*7ji-a079G}rvdHAXg7G|Gwl+LS;<$8Jjz@Rs;Akv6^vd-(i7pU+$FKmQ^yr!y| z^H2uHbw+QnjEox5xlfyJYAjYSZ!?IDZ~+18xO5go{`XXP;vJrLTdW()^%C#Rpf~X# za>BEei1XykG7jh`XD(n_KRI*z4iD)C4rtP=ENfB=t_o6G2}>Et0gz6xGRCm1Nkv>2 zhqQ_VnshbGnshXuB{-(woH1m;v*ojlmcn<3#;Ng#!zP^A7-l%Hyoz!34c6%M98MGq zf_z?>@(Dkk8@WNOJDoKvHo7EF=ms%QaTHDvQM_K>AkJ(#su@nmRTrFiZ+6nBEk9Gq zH#w=%e($$9e3B>LO^tk%I&}%Y0>CnVl7OBk{EtK)N6 zZlfk*q5PVItCl#s*owX|0IKyBN1mY;VH$6H4`ry&7CN)sNliG~%IMB=bJZLtljm$E zPJue>??^}oTB|!EZYavFwU22!sZB=4mfrmRzb%aDlHSiUN_r~Z73YjjQ)gWuGCnbA zWS#P7%<&9Qy#JK(1%uw<8AOWtGQPedbT-Sjnp%W&EoV)bi4S{?Rg-6^IcRSK!bbKn z!Bz!WxRyOZ)u;2))bic0>SoNuJa1$yCR54PPM^~rxT)m#m~)64gVl+avBi3n&*$AB z-Z^nh35Lm^zA{1Vn&spYYoWS!RXuV&NK>qAX<27i%Xk!Ddx(DUPk%R|OIKVtU)FKJ*j)kDVOGaW8S9F1Jfitq+HQ#Xk7Yd1~G^m7h+Gu`Wy zDzmK`1>b3cm~Fgr9n+eqA;;on+CU<=zeN4wOlo&?fKKYHj2Bqe6WpsT>k00gXFLkO za6l`x-$@Z#p%cqmA>z#;+mk~dPYwe-Ih^3l;Z#o!%UISqT)?usi+PCwOh4`C8WeTE;d1GnO^~W?q?T&JLEHr`H{vpI&EKuc&(8M&;41 zaumzis^2kI#<48J-@#aqXIb-~=b@|5bl!Gk+I;#wN6y3y+pe0@)STXqOq~9XOq@Q? zYYwf?k8))CP~S0*Oq^v7pEx%-GI4J5q_fVG&ObcqJmyJfuP2>MXZ=IzG;(ChEAMir z%sA<5!ymNsB6JGrA)q{Ga1hmuS~kg8IWU5+EH%gXGSLXPx(z#=W!SgJ?gFYN@uys&P7=&!I8csMV*d)v#~i{604D=qv)os`8~GHx#5O9E<-nZ6Y z`_vQ@JdQQ6HW{Z@M%I8{#y}@E11IU{u-smqF&pm`vTUg~xGJP&e5tlSZWuUtHawb< z(bTqc4HOeIK0rp#0WV_&28N3mMn)eQ8Jue!P6AW=l84>CSj)0D&Q$WP4xescAz2Bw z!0NY&B-I2nx+6D2--t}N{C7DxT@9Gxk$)ClxU9X-Wma-ut(`MU$aWR12%CT-7Ei1| z&a`u`BBYvSdYodgO;1taEnmoO?BsHK7N!;pud#L|w6HBW)(zO)8DkbQ|CUvfoZ#O| zTmsLwD}iU)arl{`b{V|KP`ehVA;ay&lk{5-kJ!hqd4hhcAdj}K9rR0g&HLGOFT9^! zf!{%P@=_{W)y4e&GD?_Z$AL7pbGR0DjME+K9J`S51b&e(*TuSuo3ctet>-_DAg+bmB2K z-NEQ>7jBw>t-jmY@06R;}Q5*=(pmo z3E0w`E?UpE>5B4Mb|F^fi*33wLQcGWG~h!1httDzG-= z&GGfzfGG1qyYdCv@w@IR-uL@ie*CKfW{9W2EW})ot-=vSf6zXC?F4>X*yZ@mw&Q54 z#WtOEV&mt#C(zFI<*!mvs}Xo6Vi#`aKNXB65I|M#q4<0txppPwYr(>pT4dLvJ}gkH*c@w@J;%Q+$62;eYuLjU{^fyJ#lHzGb2cFd ztZ-l!wFoV>D_-K-)IP(1>R#kONgXOgXa%x-n*UUwk;?3x+qmJXk@xf=u&dDr*eL+ssg+%U-x0Qj-wAdNemmIt z{9DJrwXmQLb`JRXT)@r=)_6OKE*WoEFQYMD$-h+}(ZhRH@8j3HE{chf))zQ3zWhad z;WN$ zm_h8ncCaeK^(V_os$B{0$;AJqrQA0H55uKHW_ zo2Z03BJ>DC2YpC!QFUW*Qz?=&n9?E#%|u8uat67(jqV*_9~58hmd9t%W}D)Yz^AG{~-nK`ygvA!pcySHZlk zJ5W4hmW6Lq_V^d$&*jYIAl76!RWdRzSA6p?q7g^sB-FTL)G2GR#u1dhzxEq5=%O#~ z=f0&ArKh>HtRJh(WW0mwH%v{yJ&ooL?NnT)3CfLC*PiOsxmb8HO%DmLd@$p-I=HKv zfsvzw_^e_lRg863CnxcP4^{<5su<%zBT60ISry~7x~of|*g>8e=BU=A)Wj220XF&G z6nO|Wl~}6jC{ImKU>RTg8mz`$i0!dCXz@MDpiIj*+EjTOaxZYQqi0B#v8>c#IP>tz zGlbKK>R3DZ945VE z`Wed>_KC&`4EF>+Jb;z|HqH_J!&Dx2g1!qTCJ;T2_n1>4x_m6Mf~6Q4gX|^dbXLQU z!n>JHa#>k;kPY8F#sfKw@Ri)e5H$=}P2O^lLk45JeUIFo8>o#MfDbI7l=&RYfZ$$Ewvn2SD^*{!Y^kZIST;GC7Iq!#54V-TAAAg_ z0^LMT3~6?@sWZCT)o83Dy9)As5$oPe*Gt(|CyuwSz+xA^6|>J{2=PrEbmLx@Td6L* zXWC}8;|nKIEUxwpboh40l<~BXg);VNN+NJm%sx>kMImy3cCN~&`%gIKtH8ZiRfkR1 zg;UC$9x4~x*&IXP7+bP4qF#x76=edFteraE`nHKZg*|^p&dHQyzAAg#Ksy=gs|qpW zOh1L9hhmHJr)>3%{ZCuf*t>1@zWu4KKC}1P>MQ#PTm5AJZmaUF%d^xKSru98+N{bf zbw^fJmU=L&I!isBRg$x^>%U7oG3$X)|0xskKL7F(UHjGtNV zs=D{VCHHBRH8w3DW1p<6zl@QQ>STDNJ*QDD+HHh-9XGGJI+)xGr;oSRXWG+riT^Iijj)C{eQ9XL#i6;)`snd7l2%}{or4~~| zrmKPi>|n^jOx1P}#t+LDcI&TD>VfQC+3KC_chGvr7LiJCwYh0^Q%(kU_!q`ntAkNX zOst{!Py{x$XZZ;AdFD?T-am3kr<-3wES>H)NA85q&79@teLl+;woR+UAgJU}TYBJ^ z24<~4m^0f=Zwxo~71j-HQ)kH2wl!bT@NwYYDehJI$qZAU9GS(C)LG;O^+p=-j-sC=vC_=_JsrPcucSpQ5)Zb-Q{&sn68cN?niLOtHi*rSuO{y|KIe;V`@f z>Y?Ie#0`o@ow4GAUzeeXXrMqMMzn=rnH5= z;_!Rq5)<>cGKzu2&c=fJ?D5w1F}qmnBoR{9YZ3KYH<(0jM=h2yY$;{bMfJpp`h?|!=(eYw zICnhF7^S*6mm#Dq49PB*T?6_4h`m6^j9Nx9ov_(}g_E-J)-Jp`rDI;;m||6Yn}J?u z=yY`r_S4CmT=zmFw0HUNd;;dK0LA-pNz2V!VAY+ zbuoLXR;3Wrv(>cIa5bHSJ=EYz!_ZKcdOcDeRh7}IsJc3~4wp{9XKJpxC9*xDYOt@Q zT8Xc=IO*E?<(MlY_A;GIF+%i|X6a=D*>!+Eir9bAgx{E8sVq1NBjaLZ>lIpYH7=$K z_jtw*Qb(Vl&Mwy|X3`pCfmI=!!$Ggv){tz*@L>Qf~V@rxlyZix>Eo{T<;sXBQ%TuoEET$lB9gp}17A1!(z1KXrN znXO*Ueis)Qb!^!c6x&L5!dR}zxFlhx^kc$|=f_*4>33VwEE zO09hb(Wa^CMVR9{P9aGCONkzMkTN&}S#KQ*G!zF$KBhZAC zox}1msv2t{3=nMAN{PU~SV-jA49*N&_;@+ovEo(?+uDX5&jQTBf95dZb^Nx* ze@uy1jFAuU8;8Ej`4UJI{MVdSzb{|kL7XCp-A zaZ;XNGNqxP9^M&%A$)SB)g zBV{}wXQZ4rd;Z)7vjH%txU~+MJG6uyDpaipj-)ZHE+k)rn`@Ai(+rNG(*@ z4k3pfKLao4HXvISJJecK=GUOq%BLuHNM+%?8n8pMJ}zN|#$NEC_A&K}%mKmQ)B_i} zMz7m>d@vCp)ED13&==CqAAzged4ADZC38xOic1zP9ypVn10OlazRGEhFppGFP_Sg? ztb)O{!m%7=P#hPOT>sM->E!#6LxGh0kmD#XAF>VzrhHF2j{>RlAyG5~zGCd*OaxNv zL*51w&+>9Qqq8b}2v&hsB3n34EfNU~F1Hq2z^U{he*mdANWsFgk_E+c7v*F4vyE8= zi_oM%DlphJLd|+2TB{Pn%|)h@Q8W{zU`a`7DYOb*WN}H!SwJccLg~zgRykaRo6Zs- zRCl%wqF{ZG68bpT0m*?waJBG_2CLeq^*nLTh=M~l-vNKn=+1#I;A4;B&`6V#$@&*<0MV>qJK2yJ7XELsI9A-dc-B(I@{BU+~dsq(cm_Rp|teF&a0uo7^UZeP3& zqy`SgMSdfsKysged?im;Y6)A`9Lc>0kOY3BL$NLE(vOtvdBc(N>;_VCs5j;BfzB9YyN}@Pj?r8<6IR*113mKaiU4Me-Pa_3~;7 zv(p^W+6<)j6Vdty__}RLQA(Hvf1o*{H4{jUucpg@WDoSV{Ix(T$LRLaX+8ub`Ih9> z0p5sKg8GoWy2I0Gj^wolNa1eLx&ciYY{O>^N3^~JV!ba~Gzx-R#neE|5v>{^h2y+^ zx`#MPFY+6Z;l7%-!$KpD<(_N32_X5klKaJ|Trl?+4M%c61D>ziNk_NXKY z^@wX6NKw`j7#bF(8nzadHEki{c`QegD6jvJbwVLv${-e5<+?`?^;nc}f09Z_oF8C6 z!Q%{Yw3i^xa5VdA0a7VAx;2Ock`+sY8u5rwoXjm+mdgx*428j33RJ7Rq@NoNZ}1pMjHuv7ysh z7Mc#O2w1BOXEiu(w@Z0OgVP!#L8r4Slrs;UTMTDpXkM3sv&(SuLpisD(*vVL=Y`=A zQl6i|S(b)#0%odL(s1g)iNiu0YM&`^Tk8xbygV;}v(IpfL(3e&mp<~*A3Cq_K3xjV z<_0*jHvS)S&}-x3l2R<~ur8hnh>wDT(~3*;m(Gjh)Qo+UYhFSz=MLp}YU>MIKg)QB zi80A<`@wi;yH%4AD8dI?Dod8#pk6kn+&EC!KN9)Dnvn;+H(1|DbbEI^%?y zfrCZ}IR-g-!DPXC7#hKYd`rgz@GTY+(e{&zMEpsKZS)1KZKGsP!OWs1Gv|1W16t!z zo{Ao+ZG%d88aRn=4u=41K9I8RUgScm7q44nM!OM6+#oWi{8={kFml)RqIM4U71iQR zaCE(ha}kiBZF~uit|@VD1BY7Ne?;0LY}RaKMgG1Zc2{t8Yfw65Awdq={3X4`<|iZP zsif*V$mZWMHvivXVZfe1<-tLg9E)^CrAYE0G%k{W^td1iClmD!8W*Ig$3;G*U^~*d zI2x*YTs(rj=u1legT}=nh|%L>fk)3`_+z_`dY<01HgBm~kUZinDw+Ry z&6F@T=Re+hrSM~9t2O8g?Vm43iwFH3+3K?}FzugT4((I2!*Uc++hHF_K^ocNOvGqA zJP1;-USx+fMQA(Rfk1ow_a9`3XG2xnVKAQ9WQSj2RB1arE?5|F$PSM<06QFtE}#J# zi{#M}~ z>nhv@r0jSvXBUt;K28>zwgMNoI4@3TB9Jm4=PDr8QXb~K3}ng(-EZ2{x;2&N`w^Tu zX*fL(#+hbM@0>CU$TDB z&MSurhwREdB%RN}8Ew)b?-;Cm1P-yaameSo?L%qE*&n$Gs%I=R6uHUR`ma zT3a}AWL#7R@;JHXMSfYNyfS~Q0J$G^eRqkuR&5h*?C^7?lY>m?5R6F1V4 zjt58EJaH13M^Vvw2c7wTe((Htp4)4=&5Wp%sX%J7ST?Q2A{@{Rese&49G$Uj`}I@8tQH zBSw4vmMF_$eTjQb;)~WgQ?RY zzwy5-#c$k)h8~3c{0I4sQ`(E)SR8b!pp)Nt4}+c7uCWOD1e#O*2cOX+E$uf75lNE& zAiuE&&9D8&97G0v3;B&!$d6)Tk#7(}Me7~pH;PcwbSuVB;V`w|fTIpM$ZxC!P8QLS z-zYr*zmY)QsPSTv@9|4EQv+ERcjj{_N3x8gkdQpw`Gk34UPmr-y&4B~L`{0EJKm#})!v*(+^L_nuea1sW!9tGsr{k=>n@_7?t^e7k! zBv@t|1wWcm0MoL_3-}Kj1q!QkJqmCVVIffOpiyuhN~%XeaFh_8X3st#=uwdR{Js1D zEW8KmuPwX^Df^p9ESy#s#=_58P_nFGPSJv5et79mUoC$fx2)|bDOq2t(M`6|6V=fx zt17s)phqIxSl?A_<6KHEa8SQ*!++iHaHk<&o%(bN7LvM8%fTT_@*mWv>r9_gI>Ceb zvft9KL>AQ=u=X||g<2GOo2lq&?QJfD7H*u?JILy4@LyY9AH)XBL*9mLM9;ZH zzzO#@yNqSN4i2r8{0CVkJ#nYKP0$+=n=ErJJfybF&7t)o%iP?6Wl}n{4&P+Dj&-PTdYX6=gfjq^Th>52fA+{d1Le`Zj50>Zlfx|P9an>+`-?baC{i1j z_yjn*2Z=Ka5fL}ik-DNube|H32*JEIfunnwIH!fCLtbLuPVo}EFgWJ~@**$s9g3>G z#GyfV1Pxx98!xdQg$a&K@)Gn^qV^I=Xk`ZSA}=uuO`^TT5r_|Z8=AlF!Wv1>UvDB5 zK7YNa#7k5J@*#lF=-Z2zI6v5c;Etuh;=NHGA982_ znFgeKH0llISR{^Lx4#Jcv&Uc=m5}R2mwPxLsw79nE$51P$S zMf2*}`~-ib6QXhY$iXsB@qlH>LF1I}H&JgkbX9E?>aNG>EnsH)Qj&4{nHi@`J=fG` z8tx4ASLG~c#3A3XqXL{gh@ir13wsqvsac)=nd3sPq7Q{(==NC?R%FZSD3C7 zkjgY#AAmCn7enZds_x?bK(?jPYTqCA@@b6%(j-m2P6ub7PwOv0cBaYe25?3n<}KmF zKx)!xy$(*ocL(7IAgi5pbpLeDMJ;?Oj|H+fP0FW(v(Kk>9*`|*wAO+%dX%pgK)z3- z^(Hv0eOf;NvC_12>j7AqALg|dW0=M=`-4+`sBmcRa}TlJBf(i~(!sRlIfOG89D4Gc z!u6jh6V6I->I?_2*>eb|5}f5GFTckUPBl2naKh7hADs4SI6s4vG#olZcMr*{%|Oel zHD&f+0}xIEoGB(9{~3UAjss_o;rLe{#Q8I4VXEbPlt+6%>Mt}zy)y;k+z5{LeyKT6 zfusFlYR>oIXz!Pr)8P>Db*VW=fTKMdagIX?gR4QB@i&_pe_5wW2y6c037YL zQgc24NBgMMoF;?BBcoLZAHa%eHQGn7hR zCxQ^!d@r0dqu5AiK0?8RZ2ntZf7WLT--6R3Kq8w@q6pgNF=*KW{4}!pZ;j1&Lu9bb zWb?Q76q|nm_S4Lt2ts7@gE2arQwkBvF?f*8zt}@;9$NnF^l)~kji zT5aKXbN(Y*;q@vq9MReYByLKW;}#E+l<<4Q5v|d~aiwdy0yKoZ6daY@i~h}I2;BU&F(I>wX0eT9^;A7IT9tui20X|x_U9MOu5gN+e7;Gg89+1~wCRIHEP~aCkQ3H?||%wfiVSbX;XPqV)!leBSYti!0?UL8vBZVVc^MS;hHLP`?;fU5=LRyGc_(;jc z1x?Knt+RmCHELMve!~&1uYe>?UN@i}lr)C%1%oFFN3_lclG9l73fFqra762SAl0oz zi`Hzxybj9~j%b|^q@roVT2C2{Xhn~PR&&uRLSDgMKGJYR>k=S^*$rzwXE>szj)6s` zX~W5eBU;x0sY=s^yA4OQIvc-|58IEW@0Hp5HhP8e)9MKwnJUsSSqLoQmm_z)=GQ$zAhk=w|(y-Rgh9g?T^Dz_s zCR*Vuz4Hx6v>pdicX`8FkrRX?S`&cen|d`hbs|CPb*bTq)-ynAOdE!4*(VA|w2mUg zlrX%%RvV6Jy$Yl#c*!x61_f#h5!TH*ETJViL7btaHn(;BWX z^tRz0h9g=Z6JlB;T&wp~;fU58AXTPb;dWSMIHL6(kP4&KHnf*Voh%&Dx)4ZhR7NFT z+j09$Y-6Y4h*riau=$v1oeX!~*yJZ##~O}ktp<|VCoSIu8bLq*uHlGQ*J;Shc!2Q! zDlr_<+5jYOdO6#ajsz*;=Y}I%eNTlyG;J8JHP3KFYa=1XABJoF+i*my>uDI3#^(EZ z%H@`Drs0TIB@oMu<#4T!4M(&(osM4qMq1wOVQ*^`8IEXG0!f%Q4A=V1a73%;bgV#3 z2^&!s=8%@3V>qI<5lDq;jc~0m3`ey3o&l})Vu$}gKJFNkyyhE@Xl(&fWBTi1Xk`RS z_?6*^R{t~M6AqTV&V@$Mde1T((b@EOH-ygIX1a zBU*0)DKxFI99qFPY+o!K(V7ON!g#jXp?N)RIHJ|N1Vob;CeDx&t~DId+7Bc@L+r2x zwA@2lSQDlZ25ByN3P&CbojTJbZz0L~A*a9HVteXbE>3 zj%e8nF*~HunqfGiwT%$tH%1{Z8C9BU*O=Dg2*kkqZm9M%$&r5v@ysRR7+v)~|*mTJtbH)|k97)I;+6&~QX+@-o<= zX^rrDy=ge2HRU|Cp=piqdc9~kqIKwBV40>~XwZV?^Ozhwhvape;fU6UKx)lB4tMmEvS{UAEF94~ z2S~Ze>m?7@)q28kM9aDaKFVAN=nJg~Wy6Q$b+qA#*403gCayl+Zn-T~-;6XuSv|ZhD!PBf-|_c)4&yYaWm)bN9A5RBOB8h*tJ0)XQj5UQ#Ys zI?ZrIYa@^fQ^N56`oVBSYuptWI~Rz}W4aBg*ENPCS|0+bUEZ+PA#g&PBUFUw?Nvy}lrX%%iVa7!?gLVZjZdkUVi7ETLh7Yf3rDn029h*d1)*A73`ey7 z2c%|&H?LrSop`lyMC%S9ImRCzioD!I^nWlM(K>t$Y|P|U1eKs2-e@?Y^#zcsaw*}A zP_1!)6^>~A6-dHpVZjvAU!NL|XbrA_9hwr3a4Y4}Uuig^^*WFm^GwCq&=PjMMmVB1 z1Bi8{)QhZF;lDnl4evJ`(fSEUxzXAPx-CkkhDTj19MP&E#FUW6m*n6|?;4J1b-E6{ zjBQ`E9b(!JS#QiS9MSqakP4$k>%(BZel;A?8ow5^!+#{NY*Qx^q^#E)j%e)xl1QU9 z@_ONj*5yEwX|#45j%f9{0oI#F>wLozE!t~ZAA-CHPI+fJbE!gPum?N-O*o=84@lhH zZ$c6wt-8%{L@TlmYd>>mHeBm?!x61@K+4Qr;Bc)*Sa4~MXq^irnI^B#4M((2z6sW{ zSNc6Xum2d1Xf3`O^)h`Cu9b0%a761`AZ1@PoYx^ec>^Pj^V#P#7pcl9MNib2WAKJ z%s{wSf#HbO9Y88fUU|qQSg+3wN3{CiiFJa>D_m=l;fU5&AeE*K+aWLVx%!AYf17U* zj%bwtDKl*tu2pR~qSf{;cy;4Rnj`gKUL}SjTK5B~HKRLR>vzKutvs5b%)B!XfnXc{ z)o?`Xbs$x9WPIf~_1Ax-HICRM9MO6ZNJSd0UYms@TGs=aG(y{ve%jg1j%@4y;>qEW zO{F}qxn1KH%c8dlawm#UI0Z358a?s*&=z^(w>j>JbUeh91dH^+# zJ@LDzlRWX;7jGgy)T};_p7-qW=e#*UdhCJo|`!MW^?3#kZrYC-9 z^^qrj@4Ogq)d$j{Cw^&{IkG_PS?x}p9wt5U+pD)c@!Jl$1`m2Skmg>pr&Le5)06NO zX*l%caD1%vSIb~VK;D6kO-EW(VZCz&l$=BCx%=H1C}}tg!P%OI^B6d_X*iAVL7#VS zxIAZoGcpZl3pmATIR68uA`NHqz1Ty*aPrVH!S=Zs9Mwh2oCxK74$jatoDo}4X2Z!3 zO=k@_Thnkp0!PKAJh`Fi47m?8V;asXaHgl>d;rcW!=Y;h!S>1hJK8V}XC*jwh7(@q z*TJEEg0!uM=hgjwtTzlNJe@`0EKkFE3Y^VpI5`-kw5v-)V`nuuR=0*ZSr5Qxrr{KV zGc65g8#pV|aO?-+TMTDvPI9tUK_yKpN3Nh&UDO`II zU&CeI2F{c;oIk)RPs5q`7~aB8!?^~WchYd)1xNL7xXe8s$Gnq037p*wkaR`^4RV%)Gs$qm zZFMI&%hGU~?trbP;hYFgO&ZP(;OsY?p(u02sf}KrQs8}X=#6gOKH;3MPr{EGPI$fM zf>V)(^B_3e({O$PXKxzL_-gpxL!``ws70_|SAer54d*p*b{Wp}&~#coh4z6P)a_Fk z%9#&NMH4+|9s4u<)XG$8*i7#PoV>sb;Uk}bM!^J50(mDKwpP!J(Z`bQ^}Z^E2S=HJtFgTD*$=Do05= z;q9{uoLkaxtbgK7^)#IGz?lTo(q#@W&o|&~Hk|PCoc|h{WQ?Q}&iNi3`hq}1wmPo{ z`v@6Mcsl#Q$r&r@g!jeSuVb91;rs;7X2S{3YvLQI*Eq?mFtp!q1c$z`*-*dl1!t?_ zgxl(nH?iI@obd8o0M3-8DUiTyZ1s`QN;eC2FIISm0Ug7QY9yq0GIDOv2{!xY#UY;f3G&x-I3g_$qXNuvJ zhSt5!+gJmn;hY6d?h%q#cskYKtTUYO_G$GF<`lyTPiHPT`A0UK*A8&Dr{T1G7w2e4 zNjl-}Qw&a-;e?mxNpRjz!#QX-Y;2HZ#kFRIhf zSY8g!x-^_!;OsM;@bdI~A8mNFy6z=#wi{0Pxajl&#?CR4S9sm$ zfiuT&!qa&aoNB`f@AvEv@kHIRl2>kMy^6pYnuhZzIE86AIUixYk%luHoNb0fb&uh{ zKBCUw9pE&XBxPO#G`QBvsf8a)!!$E_G^w)df z{G5iv92?m@G@Tr&dLTjvP;iaTXyN0QB+(|R9d=lre_yU zeD?$C)bjg`xKr#7QM8kLH2)kj?{6%3lY0PJht8#OAB(icuQGJP=olT)Isr%xzaK~G z{9oL0&T1}Yh7fYhLJ4(iP`xt22sX(|Q!nB)21k6Jo8Yacro`!m2x%3ULwBy9zD@Dl zEwM;bG+wL4`Le2MOB<0}gVXcU}+xm%Bdw-5>*Gzw-Mz$n;z0Ha{c0gQsX%qX}Hg=rKh z5RHPb%qR%fi4ibZ)!@M)T7|BO)?5jOF0S#9518bx=?GOQSitCjDq$sSh87sOBBE1 zbHSVg7zHD@q@N37IWiYu=!G2o6cdV}M?sHZ144&J0bP9}yKZRT!mF?P`~96x1BRD41tP!OYU4#fuAQ92DSdG*Yrz z=&$^_4X=o9r+%O39R;5Q$?<)Ks>Oeiq8S&t2$0{=2i1d)vEcZ%W&x=^!JG0LAk|VH z*7}vSe8{A);IaA1Sghjy)bk4}Pz7?=Ek+hTo6A`Lrv@C|V#Enw6?FPqT7x(#MiV%? zeTWl2n$87Bw-|9sQIw!j?WMf94T&=xoZz%Fu1;E&I558u4xP)a_`8hUFHy16>Q|jt zaVMQ9BR4lAKmb7VSCJXHn8-rDJVNI(%go4yEAYH+DrwTW%nmbhrveVnJ#;QpcAv~& zozXbK{-9M{J2P_EO7gzHG;)^=m65wB*vMeh$X$5=BR7Gf>Q!7WG;q@5Ib;=A?T*~C z0mUWrix$i-^?d5tT7~{9zms|?j{fo_;1RC}r(%P{Vf+ptbv|SZkm|dhwKDWb+4E67Leo?FR}+noe%jAi1l|bC-yCnju<8Q6SE46*{NEIDlexcIE6ig zLrtFm^1kzR3GETb0LgjGt93MxIv-L%={)Y`lo7{=tN>Ek*_+qRggoKZx*tgO(_Z9B zAmux~$ZJ4yp7kQ1kd_bG2PFS_FK0gx>oqTu^&Q&Tha5!6>%u{cEhw5_V&&j|30p5U zkJT5P#QR=kG>}?cH+MPtKnk1D=kMZZc{N4JVz3~=)!={D;66Xs zPJRX!7cD75pb7p{8e!vo;EctKiC>wc-)juzEYb-THg~KgvKgNE<$y0cqlMTi<&{Ut z1`e7FN_Wa!@W8*Za)*}xpfmc5PLa7_Q_8u3TD}!jW09+GwyZ}3Jemt$Fmpj4V)`>e zh~|P;I6rO8>5MoC{Ru7qL36>H`(-W|bVb;H?=%!Jmi1o5xlLH5(@46&aT!9>6(+o&_P z5eE`5XSR)FFz0I9AWI7-MYi$e$cXdxx<%m7X!9S`?>CQ>ejgLe2z2WAEeFu=lZvI^ zbD`xgkM#SgSkCCZ_elJVkY0^H5<>KDeft}0FE`Q;gt6qj-=fGM~wM2DHniKVanVK z*|?rW%6yICNXk2a)TGh+)^JFxprByM%vlAAoLoIBbuL|h!d*q=NjYicNFbJZ%WnVz zuJe=foNqW%o-II@kB~MbJ9TRz(ud$A(xlw>XW>Z7M*~@vCglsjsc_EzbZ&P8=`q?{ z)7?PIPts?0nv?wt^73)U04X%*aj1kf4M=_u$Bz+UEdWv`o{f=ff#mo&4+2U0QhuM1 zL#2Isv!47&`!xF%B{ZDA63u^wGXb0$ll!0PMdhn2^i5VOO)PSZuY?kqjuL7cBMx~s zu^M4m{C?$1^M2(}H^L*$Lpr(#DIK`ekaRYHqx+pWd%z){|M(X;x|dU@)ABd54dUE@ z1TekTJB|WJ+Xiu{ccf2T;w*4s3r4H1qinnqhO`-l?}^5uE1mJnHAr z>g$ZDGQ+Ni#y~#-A(~+a9V#g!>wBlYTwzBd{?Xcm6wFqwtF3mOJg z=v~*f_{*L)MLW|>U7cp8J`R1ctT=q8mXWp!oDFF>JHe?*!}%4Q{b@LZ|A%LvN~ApK zc8~o?dFFsqn1(}lRM#0!EkbPq4PA+Jmd%#D{HqknYd1I>8sNxE<~&%RS;@@A^9kNd z@yNOD?>Hmt=6L>)UjH+FFEvE2DG%BFkwAiGMq}`-FJ%mNhVyMts=kB9;MsFz431O2 zNGCvJaQ8DZ273aP)^*u52CK~&jE8b)4E}nujKMCU92$eiC1niaGNpyg>m4)(o1!*) z3}NEz0C*0uAM#$te)Lyn=Pq0@aHdcv zqQ4UI?211Lp;*(s97fLuV!fhQDZ0(C3Ltj@sgt{;{rA_mY_Na{xK$4|q{2 zA#(--sl~}RpS3ZP2c*V#J$yj`Sqr4f$9W7$(swm}PXK8~x%fCEf#f8;xt{=}Zk!ic z2xJR7g}OJ@^FNn^(IjsX2eP2lyT3(H2E@4>zgygtPsG zb7U1)+FRRk`j<(g*>0APiw%*hn^4M4WE*|@YgDmTG zX{{comw|)JJM|9o*aw{=9vjQ2kZTU)u}6;= zk9`$Fo$IBdS4};Q$Nozoo&fULkqP3lzi|hkhfN-P?^v`Su!ioxH^GcX4Wqx$NavsK zAs+h^ug6|evS@z6oT3HArC4*gyU_eu*P}MVHnt&Os&uMVH`&JScA3ugsLydq66`Os zjg4oEZD51Pkc0Yt8k$6}mTC3`Q175VeSU)UX*puidG!vOg>N%`ntB$dZ(QkFc!;=C zUrN-c`y1#}>8~gXY-U)xOIh5b12n2$TlV(F1GOr zVq4c^=<)uDu?^gu3OQ)J_skR9z``TsAlt|phxS8UL*u>2Tp90l=IbxB*iS!WKX~HO z8S9HYHq;6io$F-%<4?kr>=1CO5#n*m=!rmTMa$gl|FitYJX2$_kV0RXKLQf>mGEaEmajZ5@EP{F zFXdbyRlaN8lLDOCKx$s_*6R{N(%8mr0j?K=!05 z&q)ETg+OwAt$G!ZpVOqXDWLTXkfhHJYk^ezS~Z$opVI|MO|`dG4+FA2P3}_zT4g}$ z-teZg2FTDft-2+k^%9UA-$?l!NM4$BvT#G&)%vr~se2=L?K5d^a{Uv#M&~CF9PJ^A zGnt&IH=5v}YsEq|h=)8jG(>&FKn` z_I{~36Ts2_Fg2$D9PJ^A6W)d^z|kHuHRm>Pw1-U1c>)~mAyaeS14nyE;)J))&){gE znVQqKiFnb}oRQ#YznYqJGC11PrsgaGM|)c0(8|QWP9Q^EPkFI_CeCyqGSgD5K4^E- zZRYM&*Ij8cu|} z`wArM=i|^m`g+35h35`%*U&=#1$|nvM$dy-N{1ff@nm0ooOiA)22yR_q#&h>0?183 z@~gdC4+Ba1v|bA!p96{ev|`P1?pfnaCmuk?04ej$=BEKE^l2>(AlCv(`n3K|>G(?c z0+1Ttn&dwLP9z6@)wj~?2&C4hH9EjKg*d*I!%`r1KCPPqoJWCF`c`qffLLSn6(Q~S zz7KGkw?KdSR=NFvy7|t2as}K555B=;nVslz-iGE_44(_ zKp;tm#{9Dt)<63?MUrl>5@T07#XbQ?p0d z1f7~l+ShgKc$&Fkm@QVhiMaV`Q<>nroE#5vrX&UWJX za{nm6`5%ySpVo1Bs#=Zpj`#nEx$l9Ksw&@~6--ppwNTNhCPT$S++7w}40ZUk2D;(~ zq(tQGush2xEW6|G01Kh6N=k~l8Y(8{W>~1CYf+J6Ziz)kwy6~*)mmtn|F*Ou)A~K{ zJ@-BLo_Wvg%-%ct{oPOD&NI*Z=e+NG&OPVcJNIq|VsicgBsRlu>!{;0kyC+049+Yd zedqe6mI4`L*t$t@wgIWB@=G0hd{Lyzkg5e@a<&7Bp68d^Baj0?`V7q@asPOS;qycw zDZ|!h1ZO3XNTuJ_E+88WsSnZ1R1HoGkRAiMRv_O1(qV8OBRyyPZ9NBMyJ2hS2QxV* z0O>HK+JNjeq<$(m$K&4l*eCtACJJN@kch!)2GU_5*AeF|e?>hgIK4pn4XG3GgQ3xe z)G8n*=Vw5=X8JwcFOY+ys11X20+5K&Pp1RvF#1;wkeP<{D+K3G(lgC({WTy>hSZFY zWO6nD=`o}p5XciiItCbU9DD*s8^hMefS8%?`?pGYHmz(^)=wgDgAfAQFCMBj0XqxlyUqX95q`e&OCf8*OjzB z-J{p1)sg_Ix1mSPs7Vi&L>5~gJPBihGlL~giIp=295u(zuIIDhs9AS*pDzJN&APMe zxf2{U56|vT4>)Qbo?Xv#;HY^xaqMg1Lr;c3y6w}@cA2j+;Ha5-c0Hd0N6qJngNt{T z>x>tJqvq<_^?ZeFIWzq1dVT~>#F+zR*YgrMYR;cs&*5WuKA&ArIXG$+kX_F_aH2W< zxfC3=E+9SjINu45n)7G(=O^H(l|puZUH~VS!=Iy0L42IGLv}sm!BOji?Eb{TQLBmU zdaeLRtsRK-5o`bY8aQh0K%7&ooF9@cXU16 z9JO{JJ#^oS9HT11QL72!lv+8pq{mrJ5QnZs%Hv9K)M_HTt*?PoqjP#Zl*r-kS#Z=E zg!Evu$g-z**vEOrL7Y+G$oR|zN3Bzcv&hQ11RS+aAr4&^mGQX?9JO-E&iM&AYAr(? z8hhnFV`Pht*^+DV-X)`?U0>Q0ghVl5a$GIyK2Evt0dxJv&eFX{};efE1>Lp z{tS*yf| z_O|aLTh6+P^jr)*(&v}JQ7b9p*!7$<4)v_{tbiU|kj^-|z)`C$(qnJ?55ZBZE#lbQ z{wHwMYAd@x?>h}`cVjrStsx7;oSHV&1IO5pbHKP>$)LFF=$KI|aIBI1_9DBR2 z0!OXvvitKbaMXH`IQDk^3LLf8%dV%q4E{JPMB>=nbqzRbJxCmTyY2%=tp|x?Z`W?( zI5Yh0{`{N#an^&xv5zeu9M3Dn?0PN%N39u&V;@_d0Y|MOiDPfqKfzI}NaEPrHL@J- zit!j_A6w1@N3AQf``ieQT8$FNp3`f=Q7g^tdR`=doK+-o>^VJi0%}!r>}|gY9JLxH zJ@&R=3XWQhX7^_+IBI=L9DBQd365HyX4g|T5xH>Ip2V@Y>l$#>8kRWrc6}2ZwT2~* zyf-dl3FV&~>z`Jg%elW7wgY$dID_h{8AUmv``Wv^b*g zzmC@0*u41E#^yF=jzLblSMu0mHj8|u<1EdITAvRZL?p~z|= z5pCT}FiUl64oiI%NU^iePi?pR{E+6b)RRDZa@cxab6DzMKsr}*yUO4*`{n)hzRApC zsWCumT3G57NO?ua@>QC{QcHpKYFp+n>R4*6=CIU8Ah9O4MXMz5V5#qF4om$4NZ;33 z3O9ILJp8NXuvFx9j1oG_cBv0&4oj5+>AsI`;g%HX%wQWG?XrKSPt*0!ct+x1z^ zVW}1%k^9+}U22`?u+%0XH4n4Y$E>!tY7R?%4@gN4sh?;LOFadoQ%jY?mUnOr_h}AG z{S8QLIeW-;rX*SFJ!dk9rH%p8-O5t-bHOQ^!%~xgl;~02oNBPG^E8L0E&>wO9-0#n zmTJ`;mbx5Bv9@Jz*R7hvQd@xZ=V;ds&0(pZ0qM}^0(-muq&Y1029TN@?K<=<=CIUp zKuWZfJ@Th&4ogh|64lYLOU=<7mZ}93(dTZv)aNyarLG6kucKj?`nu+@)c1j;bi3&H z7v8~Heo}K->JLDo+C%&J{F>&l)PI0<=q!(gA-3TC_1+kBSn7B}w1@VJI!$v}>MS6A z+LpPm!&c{N4ofWp61$!Im%T5q(j1n$7D%Lxr7lIgyuB~Bb(iL_)HXtHVJS?geFsbZ zRC8GBw?L|MMB`P>VX6ND>Chh9WB9(Q%wegI0I6ywZ|CftMNU)CI!dJ9Nw z1$)?Hl{$JFb6DyWAiX+YcByHa!%`Oj>C{s8b~S4bOI;46TYE_D@(ym-t(wD9TS!kc zx2p*vG8#{44om$7NK{MJS)~r0&K#CH2}sv6wv~ny`{n&bzsyq{mZ}93(RFCg*A<$> zQkzJRp7UR9_3#nRVX5B&iE0n+b@-;{u+%X#aK6yC?D?9gIV|-lAl2HIJzp)F!&2*j z^j^#{v{%&qn!{4R0Fu&DaceaGp*bvdOeG?(rO1}d*C#ZGr9KNJrpMmNkn#?ezf^Nr zY7>x}6t~On;SV*3rJe&4$szTgvzfzECjsfy6=iSNIhw;#jX-*|Eo?sc4sO@An!{3C zfJEE5UG_EFk2Hs+egmX>6-&`pggmFbt~o4q*e6jNT52<-4$(fchhsE{rKS?1XDL*N z%=P|SpgAnn45UW4YYn8lGX%?jQFB=8P9S|+Dg`Oou7@>;rJe%P^(Br5&25lT_h4JE zYYs~tITQKPb?8Nc1X-$7b69FNkX|iipWCD~ho!Cq(ycu-ul=#D2Q-JJb_40jA=R%r zEOq28c&Mf9dmv|O4ofuv>C{qQ)cw)8T60+Ht3bLoaO7!U)SEqUyMC-WEcF7Ae!ZKq z2Fa4O5jlrBEOj)HUcKr+2exFEOErh3W&-Kb^Qe=pQVTVQrIrGzxs}^h11T>e+^!DI zVX00az1o(2mu8pdu+)Em6l+`6Ru3m)Q&@3WstHJs-Z@!s_3%2)VX1q7^xeblT4a^_ zk>;?}uYpwG$Wk;1;23y+y{S1YbzBu4@w1X8WrWtUp3IV`o65ItwJ_mp314om$FNQss@3LeT4 z;Fx*LVX28gI<(ZGkn#@B+^02%rCNYQ_56^|M9lU6x=C|bsvAi4y__$a14yYKYYt2O z21vNU+_se?X^c0IyU_7VGN&0(pJ0_oAV9)m48gFQoYSZWTCnvHDBF118+ zSn3iWojE-Gn&z<7P9P=Pmi?Uatmd%PE2QVk?4dmxBQIbMOPvX%T6<`>RjoNJ^*JD2 z+7{g}AkQgnn!{3Sfz;@$uB}$7FKZ4<-3O#k&xmNWk+ym?hoyRfq`t|~mDH?NI{!-#7ibPkwF2qa zefdPI)GeCBQr`j6qpu;F_bs!Bzt9|(+6N@{U5=q$>c5)9QtzJ+sT{UW(j1m52NKO; z>yw(pQlADA(K848`Kv*5SZW23o=w~?yVUiX!%|-*M6Y4(qv%gGho$xd>CPc_#Alep zQl|ka`7r&qi>_RM1OLi7K$GUM)Mg+xQI^^aDLFI$qvo*G(F@SOv@O~Pko~J#b6Dys zAe|3!4DDyVyETWU9wj~B9$4xRn!{2Dfb@TVV5yOxWe!V?2NKI+Yp&+7R5OqoZR>JG zgZqc~SGVS{)GI)`zr`NfrA}MO9F}SV(y8Zcv|}c1{YrCKYVzkW$G(AW*=LoPX%0*E z0O`^FYoRsE&uR`!{f+c=vn{*S@QawkQYQe3evhS^thOd;4oiI!NJ`tXOD)tKmTCgh znZwpP&0(oKf%N6D^|0o!)KfrWD+g}Zi<-ky{{a%Yo~7*hni^*gOI<<8H(2VUD2yW! zM|E(O+@U!v^=%*}dXI>%azcxHu+)>9!&3Wzq_h;>%_~QMq8jF~)Nw$1^y-H0-(U;g zU*k20rDl?zySZKOhm`d2i<-kyj|1t{Qj@Gw?@2I+rKSOiXsKyd53kT1mU;w8ua^3N z)mCH?b6Dz3Ak{gfF4r8EdK5^14yl7`nZr^sAbonD&FOYP7cmg)u4)4;ZhVaq$XwvI|Nho#N~(v?H%2F+oq z-9Wm3LADrqjgZ}bWP6sEZIbOdZ&zZ9ToS6e~{x5z-yW?bT z*EVz#dC)Ig$KXa^`f^B71OAn?WoVa*A#pxp<=jjhC#u;w*nWOpJ|Y{O^j1KIAHraP;itPjy;Bd2WLwT&QT4xe>DfE1f0la1N*!hoUu7LkApKm2j?Yl*5=^6 zzY+aC2d502y*W5@z!}!T?W(Zmv>u#T4$f+D+H-I=fYY6Wb3ZuyHOHRQo#2ePoPD-) zeg{rWbL{Q<7dY)XI3t$8XU!>z*lK9GpAAS(k(JEpWDJj(x1#1u^L9##POki6WJ?dKx%8HOH=JCODC+2KFZb&e$BBRp89e!MPorwVFd~eChM|z|?^yXYv%T%Ff|J&q8CF||EW@u~HD|t+Ga8)Yb!^MdnF>yW=GguD95~%MI4i+9 zpgB!ef9?RM?u+b?o%0wty*W7h!I^@KcSB)iNRd50hc~0YYmVJk2{vM2!1ZQ6k&iBEYf;qpkW%uWg;IwOwJ*RJjvqN*Ltu^*REDVOH%kM4$ceUbm!mP(G;B4HuZG}IYQ(@(t2F^y!sj_lr zg0oL^>^WTv&e$)pKX#uV181$~q^-90gL6Q0?0ODv!+z8TwpC}%`wvMswmkAYLA zIW<;2&w;a5bL{7fx4|jCYhYU^uR`86$KJoDfwNX~>^@%%PPgXR^;`|k0nM?;=d0k% z`x^Ufula|;*{V7ATs%XzG{oL38YJ-VaV+4$jceV;=Pl z_Q&4#ap26)!I=-vTFs$xUdH)0aQ5Wj>>+=)us_t_rJiHg;Jl+b_BuQroM&=yJ_pX& zd)Ss;&*k8(&B3`FoV__XFM(5j@4&W7FTwdD2j?r`?90K~56+bP*p_|HcF3hTpXT74 z1kO&)v5&oHfiq$&+p=@!gHxA-(+g*&utchvq^L8{e3k!`!vVi2OlMW9$tx zbSfq8zun}|k6ey}?E%uqQV#N8AiXd8In7sMC2mOF4y5bn{wwnRK#GlP^yjTDibP{{ zojU6FhzEd_7*bCGsW3Qi0_ivO9RCG)XxtAlg%E>N52WVv?9czjRr}N_s^1SOqNSHS zu7`&zJKz;f2EoiSNqiq1l^x=Y0pg7$^gSIfP}`k+5ob0KspqJxID^E&6y3tP3LKSF z;(P)e>GpPTRF;Wz1PmPmo_W0QYR)ooj>VVKpG&||wLzSX;2dfy!6&+_p;O=0P$s@7 z;E&LwswKOv;&ohO#A$}qdxWkEa8!*Erxf4Iwto&BRdvK^2WP0zvz9pe4vK@VdcF;g zs!Y-|2^`{?$GI@S_|u2EcUio?6PJxe;x7be7*?ahAv&aJ!QrL`^@;AXxB<_ZRCifC z4C>Q@hE2yv4S0t+de-6JBL#=5;Yv>L^m) z!6WS}dZcY@Yl*j|>DhGt(YB9r`V)7wfnD42Z$HN&yzh&sy2p8pBB(|n_X8<0I8O-V z1t6V2_Uk$5noQ(FKx%gRIi~~ZV4od-<_e?OE$4#tY=b2^0-O(y%7xt)xkn@0PCc>>vv`bq zpP)zOi}aw&SVp89!BH6`&PS}A2f$GoBu>K0`2{#CgT%qa)ne;hRP}=64|hkT(kJka zHPLt)krrV+s79pya!7|}8j;Sa;t}an=x(DSWgavl?bjm`&3~jS8j;?{9^(jnJEZ9A z@P&BhK_k**@8uC`8Aix*lYmb&A|3P*9+8HMQI-T~M7nknk4Oh)9g((xn`=Z`m&b^d zMrl!S@x*ngGY57akq$)-si$QwuB}~`Xlx!=ORnnUHRM#iJv?fC5@tL#u7t>xE5~O? z@}Tvogt8*!A5xKcJWiS;#p4+v($U~_VLYTT46(eadl^5vlZ3hIo(``pD+!%dXhjtf^4H9i1RXO2nf|- zY$Trby56(rxKPYuZaZ zkG&;MzNlTMuk?v?LG4zxD#str#b(ZOmZ#`bE~@{^x%fPCA$3tMzVIOD;#<-oAkGX# z#~FWEVn}hm^LUQ)->iD5FTZCr_hr%}56VUN0J-2epQhuyvazYIHqlxaEY9SGiZj)` zd2pO*9q05W_+~pO&OdvNgpSe^Fp{WR#b{$`yR2u~Zm#E1(5T`p{T)o4AMWQk{}3L@oKc*U zI?l98k_Xjur;c+J1pBygK*#wqaAW`|&U*%kGg+p+f&+To7%TK}JzuDE5pPbeT-H*T z^pe4Gj^#0K3@*+xe&jRN^P0bNoL>PV^Gb2<(s9mS&)quC)YBl8anQK25~tDk0$2CO zXAtm_;{5Ueapo9atz(#OYHM4b@*=2ojzvAI7)GsQFR{)7r&FI#afWTLizgzKw?pv% zA#~0KvN}?t5&RLELp`OO&%!cauY+T*Y6sIVy7l;jKQfMS)91_^J-=#36u9G|?cA+6 z)2TMHa$40SVC2VDw$r#WoyO)-FC|yz~xNU5zES{S}+ExJ%2nq^q1SNsZ=#t zIY{&91q&8X71Nnbtu*n6?-&OTf6T_A@2Tb+U+0=11C!*Pc~H$iscZf>_#_XSw_K0z zLYW#;bRGVcG#Y<)>3$If$3Fi2QTGchAT4_6eEOl$d_Mg!^vHwyP9(-TeV-%%p)qRo z_jqoz0f^b(xqscJ`&WB&ZObwYQeF?!HShESYP&Qwn40g=HJ^Qqy75iUSN1XLZp_tl zopbl=Tx1`k8a|YJj2aQk9%qi>w{;9_8=D)`$#&Z~U!WN7)G@T=!Wk2$FQ7h=wSOtj zRFWQ;Gi$+!+?=VDhirPt2KB*9|HC=$!6$RfBo6h#r*%%_1c`(CSL8Te7i7Ab^d2lCBwG=fu&L6dr(w`x;TK#D#OJYzI=S8e&6@dvB~ zcjPbEBR^cVM4qy9=G&Z|YvHI|^;34rzQa9kn6<4mLVf_9T8)rLTVkPB93yoGqu|&_ z$chhhuj~OwnxoNgN-TQ@A>@pH+x6%-L+Ih2`@GIFx<$M`Ra#o{j0$5uzV7c3+5;-Fqo7t0=Jj^Xi`9;iL5R9kX+UCXJh$)=WC zugWh$g{v4wt>uF?6VyytwR$s<-Fzl;e0z}e7|6pwIw$h{nMl6|vP*Mh1|LP} zr#Ra9pTYDLtr=O$Jb1Ucfk)#a>NoNr^udET%U{Akc9kGemT%EnKEYZpG#-}V8#Nxj zjlbxeY#ww*OX*68;!8Om;s$|87rsG9Kz362S01$5`iriXKfspML$k^=M)Ryvj`5_G zDylt}y`qRiv&u2sc~*%(GI{}5U74=BooZvoNUn_uFeGzIwXyvn9%*g+E9yMhnIrF% z)5lNb5#TjgmqDU@t&io-SD((;4CpaygYz{*=c_&4p0@8)(A#~;i?FMJJ)F}4;=Jku z9OswFBK~h46z7K?<~Tbi1e1VI)W5oQoU@O#+fL#*HwYaBP@KDB+2hPHyhz8ewly7Z zz}+EDN&mz#N=bEM7#(ou&5QG05U}s+=QBUtn@61MMsb|)#EI<#qWu)-{W{K%;*&gR ztUDD$3e2H4Znbip)v?Y+6il-YNh^hC)XAKSG7zLH8pqDo;}}_#2jy#9EPK94!dV@E zpU1J8KulYl(@S+uvE`6%@NYt`_v zwL);He!lSt_tQ_wq(g%0XD6g7n|L3hHHuU}`*YL}ohys+e|4^;{w@y$EHe8PuCY-V zSO8=kR6o07x$CD%*AH36Y1emf{dD^4XBox?Z{nrTU(quMGp?F;$RzKyQ^RRBX&ax3 zNBLS(#`(%Vt{!-l^Ob#E9d>-~mH3je9OuPkUK|wXy|L_Z<`~|kV@N8VqZI0cYd)VC zMj=H7Xp4`Gp|w<<7=C&@#}J({Bk$xG)%;04xnmg3BZj}!F}#>mi-Tg=AIlxXAL|&V zuw1S6m!YHcABd`oq5a%Mq(iUAZiZ8<;5bsp0qHc5(}0wm#Um1t&I8hIAoW1{4P-Tt zRLn1RElC;3JwRepnIrT58}#K8$1DDa$GRwhTzMawN8h=zob&!RHpbBTGY-o8ydKUw z9vf~sXsn~$c-Bc~D20b}IM51F$7&bUwX6 zpHJsWB|xaghEC01V0j)(&#j#s1u*eH3s+Py}AzT6HAjMX&y92T|bNC496^c zRutzKe#CL6JxX~{+fN_QZJ!T<8EUSd$TS{%KPHqEvVQ1pmg_JKqWOr=HNqAFl=t~L z@=p1>SLchaM95<|dI}v!;QvF4=$vfU59gv^=c1``5pHNHvz(j8>iCdG^9U9ns(g7+ z-oK^u{uErd?-IYM^M1Qj0)%4Nu471Z02K>AnQG%ET^ls_qy201pnM&R<$%f;1|rKr z{bJ~%S2QtUtGyv(V^mA4NnP+fr1X5Gw=X@Q=e1p>iq~m-) z=T|@$8l2aF6wmi_hG3|;$l#0u(s7ZWa~hBlM%!aRY7D9QKzibSsg*z$8JydJ6es+g z?Lg`b&hLP9FH#)UYhDCWZ*blQ(r<9ydm~Dr)-N>*NP{6&0;JmDoCT!DK;{7HFpvb0 zP6N3DNSA?p8A!K*d>=@kf&3Ckzk$36BvR-1`7I#ygh9*%BC1-Bya{>?&dETQ810$? zq@&)iX918BJiUwbs2DB*(qu?o2Bg>Ed>Kfy!FdQsM}uF_(?GfmP_gG zMKey0M6Pyv2mdpeQA<}{5rzZH@i|nb>TzW21i|24$8D$Ldwe^js2~4%OYms)TRWf6 zdh1eHwTa=6&U!aL#%H}7S@@GRtfM~OhHel9wEn&SH5r6pLCz+ z*Ko@&om+<#Jpf;B6&xBxf2T*$d6;^gC^&Ssngp2c793KvLwrvFjkFgw@<(fA9N(fHK*Iz1QpFI8Qm+Y4aVb{zdB)FE>m!ihj? zmbg+5G66`xfy@L_Zj56W04ZMTmr4Uk>v|?dw*skYVotoJxi&ejEK*|Vc?6s(2J&+t z6$bJwkm_Zuhcv%Jnw$N|unk3#6^8XOK&nwP-k4Acq}|{w2GVbEt^~5$;A{rcd$C{7 z{Xo_joJWAvr2U*<0=d-S{1r%SrJwU}AbU#P+Ms4d4!Ie>05#fv6p#)>&xt^aFI9R} z$xQ>&X&|2=4kp^(IJOi>mw{YQoDM(dJ|G{CfSm+I3DXZb1sUez>W8^EBe1Q z)(!tDk9D8I7Q!^)?Krd$GU#uFR^H>i%mtF z@b`dY-D5n~?T63ieL_6e-LJ>Gxi0kT%tDv4bVq|?=dyWE{|tRxaMq;3UghJkDba+RUyQPT4T?oHeaR4XWA zkE1)I7<|WIdV%)GQsJbMdVy*e*`jleJgCAycldkVE5(1nBE;;KBtaE^>{DFf8$}Nw z4psQD$GO7)jCRr4+B~Sj`|_yp%kJe0zX}RuucQjE>EH_g9{izxWgb-FjVJNhTD!0pL40?{Db5tG=@W_cAp$r|X&e zTa2___^mJIDg)+Saj5O*Le#8z?q4)=QRJ+B(ESxsKK<*3k8|EHfgy8`k^H9q^`qZ# z|2oWUI1zAA-fPizmG{#WnDH;=J(eTyl+%4zaUXmI8l*YOSLf8+`C6#+HACp(d=1CM zOzk7N`D$x+62`8-gnaeqkuSxeT+l4Vtmi`KtM)X`7akpuaV?wtrhM(*!}GQ2nc{jPr%pxLEc@DPQ0IE$8dU8PQW8DPRBA`O1DTXh$CTdVU?} zi)zD+Gg+g2ZJ(MuU;R2?6+#c^YfeVKQuQr#=aN227vG9~HaB0kaSZo@Hq!4qbuP%k z$cG`-g^_>mbv=(oonXFl1&{ZAg!0Hhd0j)z#fl%XIo9N0>^E8(zMwzI&gyrHgY|(jV_ZPWe^qyd| zMRSQS>$${dASDm#JG-ZHeCSGtJZLU41}kxD^pK*L;Tg5iJGk#$tou&gvc@*w?WHdD zd{jc}LAMg1({{wc>1K{YNC7GN7S|6!Yk*X1glC>gGkN$X!fqyrD=G$Q%89M#=2KA+ zb*g2}BCeJs*4?KQY#dZA|NH}2%a5&XrE2*LPV}l;mY5E^+UShdlTWo^r!&{gbJJF? zmQ!F$R;IIep{qsCs>mg(mcFUEt7XJ5xLS5X%4`}}%MH3(7T2X)62`U!ev9XTscqS- zMd#h&P)^UlFmb*cIrX1H<()^8)Oc?De8UcZppoRc#atV&ASDm;SNgwH8$0^AHhwD; z0VdVPr)F_&oQ|`Pq)~135l01&LyuBCTkfIM_2mp|AP;I=GM{T?@ zmE)6rB-x{DV;iiPwzxL#^=iX9l3YWh#P001LGEt^r|0K9Zg90IDQf9#(=;RsRV`$l zD&fghTnS&rnE4Tcje{!T=09^KR0)5GOqFo$O0I-^p-0lF5+c}-JPiLCQWV9%vRWw1 zf5LOaRF-kGt3?lG`QVdzZzuZ*Fl<`xEU)k75n#RWhqJs_XW5$M$k&m<$df9Awh-FpTAdr-Sj0IBtOFw54Nj>F9rUU7Envr;FLL1qu(YE5Lk_j}c?Bnr=zK+a= zRL8GaijV}5o?rWsCLqPX@gwa(V!!nxR{}}>&W~IVq~=*hxbLW3APzg3Q$l9`_HqBZ%{&dcdZ>R* z_&oQoLvZzkdXafh|BB}5Uo>ay)FW*>KFNdn;4o}Wt3G%?PW+OFz(G}qZ#(OhIVq+fkS=IJ9sqC zr^g+BJ7@6gFoZ6eaZr!D;;-D}{)bQUpdMFxGxxZKk^qD<*pVZHG|~>kc>^a$v|a8D zkYehUYktF7J{AoJka19!=jV~-u{z7`(2xeSF3xi1myqBekqtF!V<_~n zl(IV-NH^;tQ;}Id#M^mOQj}Bb#~D7mJISwsF4hg*uvtnFrkHWKKa`HUC!5N7&=8LqkP@o&-ublvzEh|3E#r! zMBo57=;((O((%NSA=#lPgedC+-zrXG8v=9lg#>VwU{=e*+~;TicN8l475>lM&& zs~)P2Ez{r&z8&cPs7_rQ2!g}*)NySbeJszYmn}kVtjyfEegIkS`=fgnhTY5~?uvCh z=dX=NAXUsg&Jp<~=`lEafehCi(u2iTB>HE+o_=t2CFs?b@`u{K0U@9>nRf)MF?*b8 zOz7XiHTDgh-zR#8+`p*ChWwpt><&wW)Gk)_ZCqnJW${24)mSu-8f(a-#$Nm**H|Uu zBVD2zE73J3@8hGUQH|}$qsBUZ!{>r(NSJde9uqp8oKgjf?C4)^j?k4bu8~f|qbF@Z zQfT~ultLzqMr#bDd<<+F$iyFEs_!Cr2vr*L>jGKdD6EeW*2fC#PZh{|m#|(Utd|Sx zuL|p(f!e-VST7gWD}?p8g!PSqtZxz4D};5LznFO+j(%b0y(^IQt-|^gVLc|SA1|zL z31q!nSdR(oGlccA!g_Zg>)V9&8Nxd4N1Bn33G3SfS>GY7<8j@lt#TS;OzSnmdQTwh zJB9Um!uot+eYLQ@E0FbGVZBCJuM^h4BCPiYvi^*)UMH;6?8%J$y#=zqM_6wV)|-U& zZwc#r0=0dwu-+uB)4ADf`$NKdUm)xIh4pq}eT}gGJ7Il)AnPv+>uZGd4q<(tu-+fY z`WwRfT48;iu>OXyejt$b1H$?`VST-@{$F7|vXADggPq&FC9JO();opu_h13y)}cGM z85YPoO__~)p3o_*ZxGgx5Y~$WSsyB_(=6WbryLg_O=RLoVSQvE>%)X~`sIOXeUq>r z71pDHtPdB~Hwo)q!urRA^)Z307YplM!un=my-Zjy31oeQu)bMX-y*D^F05AsvOZE+ z-y*DU71pN->#;!AM+xg&h4pS>{TyL^W+3ZPVZB>e$8AJrFPJz-Sg#Ib9X|&#HBZm|Z^kFdT|SYIKmHw3bdn>sThzf)M>C9JO% z)>DD3R|xC7g!SFR`t`zkdm!smg!SFRdatm)QCRN?WIZOV_X_LJ2+1qppCPP2 zBdqTc*0&1loq?>+6xR0$>wAUu?+WW116i*Y*87BYC^q}W#3zLHu0Yo33+wxZ^_PY9 zK4E=JAnP^4dcUy#hOqvIu-+ZWdY!QThOmA>SpToEzCDoj24Vexu>O{?ei$wwn=|U3 zK-Qat^|yp|x@cg`GbfG^)^`Q6o)Xq+Bi680K2%u$kg(nx$a=f5K1^62F07Xc>w5xO zUn8s!7uJh~^)rR_zChMHg!N)!eT1++Q&`_0$od9heYCJXMp(a8Snm&HeWS2GMp(zA z`^-9=c$KhzAdvM{X#8nR)$GxvWUk9;q)OC=u5isENZs$1_aK(4H*GlA-5&zW_x9z0^ zw4JZryo>EBFXwz&?y2BwK=ed$)pq=maqyL+F0PFtq&wr_>z<#|ZEvcLR!Q_{IX zf$4AK%A;y~6xSIUHUB&Ec083!U$>&~P6blzR05 z7L@fvZ8x3b>*m@YTMXSdVyvG)`&IbA^JF~7P2(TB?s@A@zV7)6T-U)34H*Yr_w0I| zuY2N!K9(a1&WKHX-SaLmOrJ@F_EuwgT=!guowr=~yp6*HB9MBti$* z(v~t{z01@cd;6U@Q(ie@b&zl(rmrvS`0&-_Nt?tT>{xG9S0inC3A{AsQ4{|lu5t#m z-Y=|o2{mv)y3x)NUh4p@6{jZ*N z_xyFE?t|IS-BVBrDuaCPu0Ub9Iptk+ZUt;+9-^Xb9QWLs|dSCP-FO$??{m2kp zEGT}-j~ol6#z4ja=`xVBfpi;40!WX6tO3$*Ah!aEV*3F9I-^@8@*N=62J$qJ4g>i+ zkS+r`3b!fs8pwDc{Tku=Q8A>k_g^U4V>ooqe+$(wNZGl_(flX*+|-B@^Un=i^nvCZ zXa1AVO|+LM51Ma$SI;-D#Yn9(>u1vWt0Twxi|*y?(({d(_#_WH$L-VSxM^TZ8r^4g zp1#jYo^MGjod*w0QzOAZ_wse=^B`^6F`dpscfkpu?k4fzx>v(2Xd34c?*z|fBQK<05Zn#XAh9h z|M)e(2Bgu(K-LlGzkaD(fZT0p zz6VIj|NNXsfXpyF`~{Gi2J#$`Zd4fMOU3XXKst*2$YEbayA0&RK>82zbH)LQ4DlnC zK#C1yE|8dkB!SczNIQ^j1GxrBuYr6GNVU<5Z9w`A&d-7L8_2W7!FFMhZt35F%ro>H zau>eE4c;DS6p(5IDF@Q+BC3DQ1QL6XUuq$cUIS?c(s_uVb0v`CVSeOGq~|a{@>L*x z2J#&s{RZ+=AkoA9QhR|^8_3^*bQs8yUqdSlWGs+g133ps1Y4Y5G#Y?J4dgN))dq44 zkd%RZ6G*3l>;%$nAb$kXV<2w=={1m}aZ>3skP;yM1~L;!>b-uSg7;&(ynlzvc5M;7LA0 z56yqN^!#TGbeQcTrI&%TAFD03-_j2q`-H9Qz&YtPUgHlvNv&qI&^==sn0%`e?g zl=k5W9eFX({AbNx-UsN%4}q!-T|EC;s^>rUCn^-*jgbUDhjc0vc5TOr;G~%25M~1D zF^~k1j*(oMM7n}BAIFHURY!{2wFRdPENpxS*DBqiPUn*$7Js-_=X2k&a7ZQ9&+%s+ z;XZBk8O(bxB-l8per_$oFD`)Mee~)SW-!$66n6ZC>j#fl%GmoNI@QlET|ZGEQWe$D zo+G(_y1$iuKE76%U4%sWkARFPc!!Z0{NR4bqAvE%! zp8M)2x#vFdAv{@G@Tlkh59OwM?v2tI)F#2He1d!K(KK+2gL>}%JbG?BPMT`uKOl4v zKt1=Sk=%1H!DuW;0P4Bt^XR$zUgn-V4BZw#W%M1~b9d;T+m>od? z0lwLeyTIvSjzicEq|-ot2BgP8o&(aS5w0<1i)!o=VTx;P4Zd+k35!2mV+->b`M1|| z{iIN8w5w*pyehw5h-Dijj~v@42#W!|Yajy#!bgPxp+ z|79FBV$aMY?=Sz2^G=bnkJx|Hd9Q707W*A|3LUc3?`9|4h<)f5%%AbjO*OK`>suUu zb>y8-H1^hTE*#`INEPEUlQ$lo2&CIU&LYhQasiNj18D;i#oHJ?J=X)NHjsOOqzq&y zkl4rkQqKYDFpxKZ^ncvXIs6`k{xpT4RB(I%NVkiqY|`05SEj=$1*aO1hW0!>8%QT! zPU;~S0qMnyOFZOaAUzZOwk`wGKhckD0ur0-m)ZuTMkCytR0gT)zKFfSC5~78kL*oy zfRw$-GOD}RMn_HJ5&Hx-Vf>dy>@iEY$NlWYNaT~E#Hq(kJ(PRgY_oJ-ZPeq&Vopmd zlp#g4vX0nea`ZTwYo#Df3WgN*xZ2JCP_O*K819vGVN&*78nM5qN9;wW0{0X3+=Y4c z+=jn%&n>~ev3NH36@Gnm8mtlCBS`Zu~EE@t=+uICP5 zlqK7!#r0grBT|<5P_4dx1J`Ob&eTbtCG{uO>J3M5t$sue3mGh`)#a~ntv)S_2Yfm^ z%*>-!OVEQ=t?tjTqCQfs9yOV3wGw>?K*m9}`jW2IXvVkdBh_juk6PV`Ne+z|=sS=w z?-$|O#Y|nR@-2a6?f1xX2WMHjtFQGd4%s?hunL{`>0jZzUxwykd7g1l-n%g=RkO-z z!XKj3+c#eN3BP?~xOE((yf@^?JH1Qm;QRRP8`u!A9F+G9&g8r|;}eFCjDy~+F$t$< zlo0g`tIw48wRz-yKK4>n-q%8#sfzn)*O}CFVN2gv(1A}*uhjPy=sw6-(kJyHq~yEz zyLFnE8Ay2=Y7J!KPH|;_OCal2;@bLNVZBdS@4=+b^~b#?-W|w#r?4JHkd2m>V_|0^ z6VvE+F2}vPJqaV5dd^$zs>Sr^uv78il4Nro!s;CR(c|`V1|8&IKzd{D6(2L5&i9THUE{vql#lh@!umpCy+&BSsX*4p zihAB5toI1(O`(~U%$a{5xtgjQ+M+)oM z=*qCZFc0f>qUQCr0A2GPqUuJ8yhlaew_;ggj-oR1`B+a2>&3$Q2w}acK-N>j`fy>r zSXf_BAnSF)ItC1ms(V-7P+@&^fvn>Nq^7M2Z)Db3Iqiy>V_l>`*5?W9{lfYi!up>M z(f(xZ@A*{S6k&aju#N?5M%$MZ$oeQ@eY>!}Ls)+Ti6}&m8!4=B6V|s2>kk#k`UqjY zTUg&FtlwK8>&3$QR$;wcSih-2)`tn}n}zi)!upZ|SsyB_cM0p8h4tA5vfl5Vt=u~# z*9+^N!unq^QG^3Dj|$b_Ul!Ka3G3^H^*sf$zE4>15Z2cU>st$Cy-!$QBdm7_>l+JX zeXp?IF08K+*4Gxu`W|6DEv&Z->*)en?-kaYg!PoLes+PZ?-17K3+uEhar>9*l@p&C zs*zAVZo9BPPgtKXtpB(`*0%}k)x!EbVg3FBS>GzG&lJ|Hg!Q#~Snq%oRMB|o-iI&u zWY&mr9v3jpESHZGv&viYnAhcFy_gsF?kIWPz+N6xI(2>u;fQP3yx7WW8Ege_2@X7uKK5V?Lix%~uKQ z`-SzFh4qIDWPPTvzE4=+FRXVJ$odRny-!%*C#=)^Q*zDg@`-#*Sl=tG_X+E33uL`Q zSbs)X-y^IqD3JAXVZB#ae@0lZDvzjo23SoVUuwGsu>)XW{cBWWCSBW+3>^!c3cfe;fWWaI0 zM_8{G*5?W9OA2ItpRk@5*6H^gIHgi6-2J-V0$E=#u0fCTa_U}-jAmBC#3i~~;_=#K zdt*AX{m=ein;wTdI_UV{|5WrNk&g@HOo7Y=vUNJOlBHS&=L#VF1Te~LByv3vo|7nK z3lP48;voE*yR9vis7(^r^XL0Q^W#AFeZp`3Ss?S=du5g8$kw6=&-oQ{91!lO3K<84 z4*H~!GhD>8UIpZh7~RRkoX;8@ydAr}F`l4_r}L{iw4%N>NlmEO=a2IWNb!|xW$OkY z>b(q6Sf}@U)-Fp$)Uy@|q2sIIj5S*N1dy%h-d^PQ0^w(!DXABM^c1VR)D`kNkS4cQ z6>`uwiy|A1N;m>Y8edZND$Zyi4MtSY1Hz+?;52NJP6X0p zSf2z0!=aBe7syB;ZYvfi)3x|C->9FYqZu%?A5?TT%#bDXXaR?IX{dHo{oDkE@4!(= zH;}DH)jb5HN9Ub1{u&4!Ufcf)#2Yv0ySISMFxqv*gU~bC-``IF;=0iN_|)$B?6fNgs*WZJxL&SMk_7` zLQ$pf73WeQNU5*w*8`!$^Z70yZy9=Xknhc`B8}$m(xb8#w0pa|@7| z;mA zSGG2$laXp8gJ*!#YvgN=E2T#DtDscrb(FjRG&!7@&-&+qY(k^F9`_|6ypyA1_#lw& z(BQRw50LdnOZNdWd%>H8;P9&Di0`4Eb=Aca>6S)(ub$l(b#r<$IHuGjAkS!9G(Oj2 z=1GTFV`qai&uGPGfo#=M#BKn>_wHgOS(aQ@n_3m=FrvB=96CIo*8$VSNrs$@`+)E|SNZcpAQeVbp9VsQ7qRDnY%}`Te}FU@tvL4kMUh>G zo)dx4;mv7Ffy^^T^;tmn8G0Il?0^(`r#!q7NVn1U+kw#Gd3Ya?Ery4W0eRW5wO>fR zMN&q@j(P|Yb1f_D9|F>0%otAvvQ8svc9F=K$(#;Oxz3K_)J3Au>{a+2aQb5Y6nBn0^f$T6MKLN-HX!b_qIY8*}V%PxWfT8&^AZrmsPwI9cX0_Z4 zq()28YCTbhH;@`F{Ruc541b;n(qTmG{f}h&a|)2P@X)K47!banpXO{WDFiiAY}lF$ z&MsZ6aXkAO>#c}-iy6f*9;$sYK%N3ZhdXM~nYy7hk}~xCg=`s8{{TXxmKU+ZdJH}E zh;gjw)%zI{L&wH(;EXhKF$qYYq4{he8+E%#ECHlKBWg~v+BtW5BX$co^9?-0O9v3sHlEX*xDeF zdj;}c7g7GKg)^o<B&HO`fbfvnXY#uJNLTGM#i&!7GK;mg74Hl(fsvfc1`GZ2_^`Z2!1@dyyU zuRtMxAU%fWzXGAd8(WGV$Jt!_L*E?%WVC^N6bK!pRcSs0NX&@pg+ORdqB!w*OEX zoC>7I&@&mx7Q^~HAUm~Y8nGMWtDSavBlZ%~Y@9uBBt%=MF|!$$D|!rDUk7Km&S|_p zoos5ta~KTHc5vP>BEQSfOg5eevc=&14M@Myier9)H4(Tf7bGIy6XC9DVL#hD? z9Uf;DkR3)#uLr{K%^~fP$Q?ksbi@ex7LdJ$hdn^(@Ur|YkZ#SPh_&M6y~~Kkepkx# z=Y(C*GflNbSw9U(iE-AO3S_u}d=`ke@+Ci(0jbi~3Hdw_Iy_sq3giJGZx|8#0T6zJ z5}m)&t+X!KZnWY_q38Dkc?rlA!=Iv`s-EKY(@{X8diuWix!Vp+?Ia#8Y4cZ{0#9iJe&$-l-5jARY25%mKI%u z5B%AM@t+I8*VQ;%L-A8FYy~pK$k$p|kD8^d6Y;qj-;YZ+VBt#d zgBn+tT(o>~JkgqHUYu;>kB!ZEa2S8JXi;l&1%GO4Y}P`C2J~#r!TQq`Hr0|a4FUWu zmJv;O{JJ*V+PqkO##x1)ld&@1*t{aq)L2&y|CS}w$<~>P=DH?aZ9vH<y?V7TRcJ!x%=p=Jrk+x`Ii$V4w6wHrQKGG}mU4{r&8nT7E-kHXNVLY&t%=5T z+pOBkxe5GJIlZhB(o5!?J9m71TngzJSK^qn!d$lkcd zw$?;oMTxnU=g%#V`;^R0Coe{8W=}@Eo0qEy&>Awa2(RC2te-W%t#xi1UpAu55QJIt z;*|VM06a#7_(ROG5uvU1M3*;|G1WQGtB1(E(!Svj}T?@x9;SraiK*_voeRxVlM zYgPa?rDgH+;!dtwm)E9eRU^eK=Edhug7;-5^)0O{6RmY|TzYB6l?oI?VsU0-t4b%% zN!BiJZEIYSJTI{{Iis-^38R__;LY?>6&`3%6&AjV22fcVQR6w?UV=Wivaz|&`7^#? zLTzj9__FHSC901(pW+y=;tM9LzZ;ut@vZZ9X=yd>*UrS8CE4ohhNUGAKE0)hhN zt2y-zK&m(!*`JQSUR~=HZ)q6;Rf)E=4=gKdO{SV~pW4}tt#G{-W#5`?u1(GfQ0f>x zFeag+QR+&^Ur5(CFG#dD(h$T|RB^%7IkTottE%*BMnf}7-M9;+w8T+1y$RzdI@09n zRa58AJ$n|k&lZZ-Mpzzx#mQMl+DJO+|5+A3etG{cS=|%$@4%v zEuqr#=?%%+rIqb?zE)dfOEWy5TjB&~@~pOMxa$oprDdN?rk&=^OtdwqPFOKFu_CFl zc@#y=eCTJ==rnWFsiy3wwCu^77oS%WpI3_U8p*1N&zd zF8cJblZeyA6-kNp&s!L0Cr%uxN z(ddig5SibRQewI+^@rvd`B?A-$eV0c;l*H$jWhsbv)KorAGvljI0a3eg4t%YU-!{Ap9Gu+_eNQG8aMF2mCte;h5dlkK(1R2qvKOcvB!VH|EfZCsjc zTIGIpb|J9gpm$yTGjRX3-Ac%uhx68rUx}P<+gO$V|6TYgh@Nv5R;_<#;}6RJf3q8Zy9+dinJ1VDakH|$5a^u06X%#L?GiRkXL0t- zBKXdprLq|P|Km);^Mksk>J>|PA5w3|y1Sfu^A_8Swe5*Gmdftfhjmswg^*c@Pp?yFz`%Zk#9<;}H;<%=798k|iFd^K5q)uz{ASq!`WJKy@P`*F_&Zf!O{ zeBWnrMs54*-D_V!7B{slN;I{_>#^jg#wYPkUwm9KF1}#FZ0wTpd1Q9Hw6ugGs01ok zR8CZXam2juusg06pt|vfkt|;#i-~k%bTAJVU^|W+NYpJ^j;-Z7$}R@H^kmww#A>U) zWo~J_y4p!uRhe@J!?tHF?lP-W+ne!~jcHnJv?Uv`P25necEIvt@)>tQRaq%1h_}?6 zx*MuXC&WM9O#5u{=`GF9Gt6j9B7eHiLsNkp zI&Efj1ubv=&Kbk2W}H3!Jm>nD*%L}}0V&yv>!gWvvaAQ{xvXCjsv(_tfu;BF>}! zq0SNoF5tY0W+?39wsGH!3>DaP^liInmaL1mU8Hb1B%FY0N0Y6&cUQ1$l_bexF4(U+l@lixT&` z(7Cy}WUQ_wjw?c#C@x>rMA!dYYbzV8&s|ZCYuj-YS!N?EvDu31Sui^f^_Vr2`npwE zGPI>D8|@m&P1>AU3NLW2pXR6MuAoa}6XUq9RvItG<#tyEE*rGrr!XpN`8a?f1`aGw zIrg(Q3HFpFOuiIX8}iagGZa0E_NAF-C^kG}hGL1NUx`sGwy^uire=G=WS=%><-7AC z!xKAM75X6fRFXWzvAwQ-nrr&loz2ZRE|UA)D>)OPQ?)0rIF~ED%e} zo%>!=Ex4%x_a>!yIPpu;G6na>)MLe;cJ>ggq|CPY2P9jKyX#WZM?IVw_SL}UY)sIY zK}%X^r8?VaO7dd5V&;xletGo9mvN##G44}Q?4_ET;RK2n}c3iTFSFY z++pUNL-ID|p4T(a)A<|sa+$YH-iN{VPu?;aZB#os&ME-+8qsC>GGyMF@nDO^w`k_s zI0Ei{>r7hQZ^|l+Z(3UutK!Ycm2upXy*SoO!t9dqg{R|o-9Mw(g{V^V=f-?TV)g?T*v!GBv+4>(Km87Mb~dnNdX<-}%#Qwy`uLbEcq?8}qBo(3{`Nz-A7%0}NiyNyWd= zN6c+QnT3~gV3TfGhcFAxK5|)zy6k=9k<)c0mu99}1}FEBm=9I*{l6I`zRf<4t#@qhIXBzW9Sa;{AH6IO zFDznNT*<=B>CfQrh@l(!Xm19sbD|VZgZ6vyY9_-G)l(|f>_4Om?FuHx7{3Pf!w4M| zXU0bBkPsTQBZJpcI-Y{kg3W4`BjrvZ^k}C7w9W2SK@@4X0<^Idv8qkr$)mVT7Py44 znlrS7afp&fJM1B=+6lLzM>`cH=F~te_noTpR{DdjZzoPZHQJ@YCyqLPE$$)42s=mp z3M0Vn7#T`JxPzrOM#RRp6jsV^dy$E)+T20QBpt;FV=lrCkd$AlMYre5p{n zv~vNv5uJ#a(`^|AI0ssFY3Bm8)+t`+cP{iJOlS5KUP~BbZ({Lb50n~vZ)K> zBE_t!aam&;KXwcgF|8wvGtNm2L;Vuk`lh8qP>-Y{?bhIn9zWN_2%B1k897`EIv38= z64D`hU_*F^{8~adG#L@%-xJpcKKW#73E>c?XewvUFO1s|DBsGEc26>Y`h@%Eaa9z* z9IoKsJq>yS7RKbe*;HDAJ55zTxC=118+3I2CJWkBN*nI8rnBSV`?YL_tFE9fQrp$< zPz&Ost1gU-_)Qnavt_uyl78VHG0x`bPlX$iE1&e%bt zL_V2%LO4aIYJM(3z^oZ6Lb!qlRRrDoa74qH=IiQ%@9@(}G>qvox}-fmXn~^TN<54U zrQuv)@h~np%?R90RTLl|#s#Mt!CheSFfPz4J7hJmf-r8BhIPYJ5XOx%=OHiwM*zogm%E~6(LIk;^p+D0Sq!>(%}|(C}#{EVVqIf4dshpMHp99o`PH=vT7kK`p z#dQn<>~U!&0rwTPymn&nwKN_-Jq#QLS6G`55Cfn6;L_TG!MA^6Yq&!2=NgEBelcz%i-tsnD(re(aot-|Zw@aWx?5CY4V?A>0VMF{IrHwMSDrzO4aIj9iKr z@ZqOd>A({VsV78iCeW`9gI{9S;@X7(!@vYQHwgFP1g=&sAI6EscDG6cG{BM7#s}X| zwC#YR+H?Tl%M!T0>gG>X9eP>X990z^a$@?VRGa{pK7{eGrq!== z8q8a0gln;82KblI)G6 zqA;!mEFhmJg@{SEVx;kI@M9G_mrZMk$oU?<7IZK$RD^JaUjq=Xx2abNC>;fGCdB?M zw>@c`AWZq2Itt-To-M~%6u2a`(}S`VqH(ws z8nhrB(GaG&{PS#T;Fu2HPMAhvAD1@zgL~^KD1;jUXFe0zi!f(Z=jU2pPY$u#v1tku z9siB0Ar^$b8FSbLp;8qhL_B8>zaUhuWLq%>U55>pGS9!!k)I$p0s;&tbd( z&8K&Gm&b!|5b*vks|n$f?hH#pI%QE5!Y$|Ly6RFtrochxl9^hxLqYD3aUb&FW-Xis z?a1J-JeRkvOr$F31pk?gPl0wLKx-yAFRTx7#~{mxaiZLL7GB`H7Fj%u3+iPZnNJD| z5KyToj9caOW&zs52vM&-72#b`W0kX$79cpPIj)ZI&gd~Euq%#+@Q%1cTVOXJAI6CZ ztxk@^<;GM}0Cz%Ft?P}_Q6Oi6R;|yMLZm5pvAB+etd`R8&g)9*8(Z7xLEGvkyuddu zXVDfWWtl2N6_Q<9q1_8wS~l-O)mWy&;KgRq6e?aD?jB9QwM9F2>7%F}iwc&~{tHO7}&A?@t#mjJGpG9ei zg0yQ36~&3(7+9F1%&M@!ZiXvK>16@NM7z?!1(`)%f#VpW9HoOH$H+ zq(&FcL9LA)oSRNH&8o$<;nLcML~A_VnrKY7;n#k16Zoex`&|w5;`2)4^GfMqxD)76 zWa@%r0kyG%*X4bVSWT4Ui9q{Gd3yyoiS4C&q|8aEkb*6CPsm6d$b%AHlzoT`Lhn)g8>Rh)~xQp$b zZB-tILNtpXh)Y-JL!8gty?Ui2j63dgKf}3WDhcC``&?CbZ8i9zONTeq3>{C1MPx(V z(cx22kZ2U7Slk?kaY)A{ltUR>!Z?I!KUQO*yz#3D;|iwaVO{a72;+*=r0_ve8p1f@ zG$@oKJ`G_UDa-Z?mr%~-&>F_!(s#t+99qLTjJ4Xi?qaPX?9xJL3gZ|SSp{;;qDeaz z;Es=pZOa$oMQ-@*a?ouup9bxS_h#1Q#aO2XSaw%dRxX-z?(Dg7+pBY&{Q_(j%usjh zzI)cPH1OPatc8`f7QUnA^lPL8B(1y|Z%nL=j7v7e>su4clA{AX21mbn6|bWWsfzB^ zpYG3*%=B0_?AQC;ODU7C8z~xvH1d1zrr9b&UlHb5y8Q? zmny~g2GWq)GT;5_Z|mTFQ`)>&cZSsFyt7cgzB6o-jlCm!q(E4OwwF>GI)hYAPNf0T zV}GlpKT82Tb+Y8WSu%9Pv%D8FtX^`{dl6&EHe24I=+`*-)QC4AhF532zwrMx_pQ%u z+&sVehu%!=IBEK=xj3!oNz)w5ZD;yrN0!$1HquJZ?#h?oF1I5(PH)e-7YLOe94_dC+lD)A+QyTBM{nCbs&{O864Q8C zZ!Ev@J9gvPp z3u$BN*s$0U`0-DTjqI6tEo>wu_vY6~GVbNBkz~~CT}K+W}ZgGT9QqLB*eZi7CG z=ckBK;{7=JJ8~F=W70YnTmR6A==TW5O7MsQ6nDAlQJj0^QTDi?cl5X(c0>Kxp+BrO zxC;mYoD6Dxb!_BfJmhVfEA-tszf$61|s+)RC(o*%)R z^OMTnFFn$}Z@bKST%X;Y%;TuIsc7zH9@$wTyW_Z<&d?v1+R?RStP|knw!b0APt8WV zR?leGUcEa`=bq87yAJnXZ}=#h_nZzFE_*!I3_U>8?A5LRy6EZGl>dHr<6Bina^URi zE_rXi;PhW&!lgF+GrH$QK|eU)Ux$qBm7i7Nvd)ndIU_;bv#H2EBm8z2Zpl=n4v$pH zYbxbLdgPzG`HJIa&ma_C zSU6Jj;*!6}KY2cDN0FDf^lxMr;~U+KInztkGddfSrCyI0VUFt2Sv`UlMt8FvOQ!lZ zv?GZ$B|2WBn&vSCnz?uDSW?Z9K9Xn)l*h|AL--g%PH&SsmW)%%M-p+K@OTNQbdMll ze{m3tbu^QnoWIg)f=1?iCs-*4#}#qj}tK!>w=g8Q+ip2d(}yci)T@#eq!O zz{AcvXO7F&K3A}e)5Ay%Fu|saTdrXl*+qYa$59Nazlq~G)WZEFV|(c@!O$z@;kMVy z%iZrWZos|3jzmsfuQ8f6@*s~jlAv`QQu2<9kv-gXqr^z^yY7D&Nj`H2#OP^~-rk@{ zJ|j#aZ%vRL{ul2uC^!3$UNAt{6hdG>UQg#0zi@N*a5o+7n?JJL{NAIZ*LZM|z||iT z#+Oydf=~3r4s!!yp#13-{aS3O9|yXLAls;iDq{RAGgnVRh@$Pm=_~F+*G-?Qwtlb| z4d~wFanhdU@ob0kK+)p@Lfrd2nqycqV2%Owu4lA^l1C8 zJV&nOA>W_uj&ZN%)pGj1uIL8-7w)6Q{XO*2ZkE?|NB_;RTH}SL8(iZ;pIv=Z{dY56 zG&hZb&zpYMHOr=@n_s!YYSRwYP%rWJ_E7g#k8|9*C&+p_`)=1u`ozqsA3b6A zx*cAwr`_=K6=B?VtB2|JqONdPRny)wFV{q5I-jm_+3bs|Ujs1QyqwX^ChKmsriv|= z{;IKtj+lMf^xf2uobm~EMK@Jb3yan2`(~XoK`@JI+NJ_y?a)4bxDKLMxb#TiLv-}j zuQuJRuAD&m!mVc549%(q+rzY-)0MeY{Gytz7n{DC*UM>pi{4&un#ItxY^YgqG-1)j z#heJEz2&0mc{Hx4U0vO5+8L2$e8NZyFaYLaUc*h)oP%;xo7Rmkl)x%O{kZNb2zoi~ zo`}BhI)*I%?yD1K5_-}+(tlLBM*brBV+ega_GkA&m$>zQUC)~7BDCDjR&$KJ&qy>#5_f;abHoo3%?i>)t#}w5 zZVsbLm59W0`gC2};v0;hkVg!j*L`z~X;jnHXfVFCcu&1r(D&_ZwrH-gr2A4oC%he= zFO*RZTZ_{(5L~shP1n^eR1;TGeXr`STXoLaU>En03c(nOT3GpHGn;mILwi*5O^KF@ z9r7-~-pKv}w5vZv7_uxf+;`^IP0_}de&kr%g(WjQ$)Nc3Sl@}a%XG_Zwz z-nx+%ViErN%Wogvf2pdk)yc_Oy{x-iXzf$AUac0{UcSb9H{4;xP}&!C&u-yDPxq)0 z20&hmexO#ohC`7uCZ|Qp+CEhZ%xw{`b)S`N&q$zWH(gzyf4kS_EE$I)u3en+72ffF zA9n5h?|tYO&_fep1o0m+j`f8l$mWs?U}R_Y+AOukh&mQvH`g`%4y*|Y4%f`Xoi38c ze?j_L;2{jjM4)Wd7a!?RHFgXl_tf_(^u*52YM9+ruZ)Fy2}NtZ*Ndl@`O(P^y`SZJ z9u~)czorT!8!Tz2wVicJBVnxbEctaEO$*Rf1dbBpd}>x!!7wIjKKMbz5TAg`K=Q&F$n8gKZdWJIlP zt!=5d&uWoxaZmfts>-`9>}+^HRlAvy1DUwgkACj+jyNd{@zIml6qd`O#}HSCLIob* zjXYZT`D);(Y7Rz#h+bN=jDXu`LzCVaNJx5!+R7t5f|p2UaGy8r12&glBHOWCcei6X zKSp6etI%Q%uRSB!-I&>yvovk%iR7JAX#tU7&E)Y5429DDn7s%~70RQE5~xFRv5et~ z1^OB_*Ad~kNoI63Ct*i}vuf!Vtg`-j6xA}%c<0HdEi14Z(O43i$?d3RsyU%;p`1mR z)bkqSM6pe6`~n2G+Q*R5o;Oa_9by=Zx+AC37%1LY3dhO>By3~bP+(Lb`Zsh_FdeB_ z!rwmM-{(A5+&U@I7=^0e>gpjfS)}dckgx3}p#0^ebw2@cevSuKX$QhlYSP4$#p)KJ z@pO|7*y|2)vStZqHQs_JK%)U+q9q92U{dO=1FWjzBtuRz>WIlQN$Sl84s>_3z)p)< zXL4rcIZ0s7#({;i)qSa23=*|YIt0b6kYr1$T;OZ5`jsNnKFyO7+XAK<66N?s&OPFw zh!fhtrQ|LJ3Kmbz<>aaKG(gsvua;9p1QU6mDuAr9+R%g36-!TYcB%lPh8k|sPhCL( z(mo2H?urB`js-xrZxTxo62zV*QeF!R+rb#l*)6`R5|AV7rz{;WpC}a9q$)ItDV}E1 z@jTrG&CyN(5q%}QJZ**I=&Hh)rX2PHO^M=Z%EE}Io@$P$9kVP@jar1E$4$;UM_CV> z#BkiovWVHp#N=s4NRDh&98r#KUY>M}n=`s?(E zYItmMP&R`TW)DX{o#1P^YzCXcksV=^l@Wv3^kzZk*4r!y-TG~khtT!ESqR7pNNzNI zwFszL)WC>I4b*H#FvX~bX;!1TfKhYyJB6r4PJuaF(^ZV8kD!?WDWV##sOILJpj-ee z>M4$DLD?QiS5VJ@6lD$9RHIogsiq)JRlyZiJ*1l198A%T5ES9aObBjMh$5=Mieze8 z1l2515sonw?Tkqh#Pd)^JwZ|Aaaz^)D{F`#Wf(H=ENhr{@&F444E6keOasIwMFWzS z1hwrgq4(zLGnhh6lRH*`aeLlE#r4qZJS?(Lsvi3s)@9a!Exi^tRMmm+SON)ihQP$@ z>W@<#s#4$q2?RrZyXu}0vceM(NY$9$*5?gdsl710p1gjOE=nIyC_);dqy0DJ2hNO~ z4#D@0oW4#QLGIzuA^nbc_VA#Pm4d%Y>wh{iOXlfY3lmYBilR!({?=l=vluFNqj4yx zmM*Y%x)p)GgEdrIcnmf42!nVWg1b5~dKeX((Ku?DT@P{scVRsX z+v2fo$B28I5{ic{#W=#y9gpZf9U47^3A@oSrf@x!DO^lUT9DP2(0dwA5mIQ}YfT^? zLJd8_@EwQXu1<^|HpON%WE!T2OT(g}%KP4Ks8VRsONEjQm4Y5)sE$H#S0}~~m1Hv> zDg}#%O2PC{m9{f>ta9MEpAk+xS`qjN!*wKzJNq$uz%--Lh($m>WD!t|8M!DL>O#NP zhaoRhoQ}c!kG#wT7z;vGkB3tMk1&`=p|_(4qX$wl84aTX=|NN=F@zYQ;=bI@yDU8J zWsDRLRSZAEXdR2>?yig;vxwDb*kY(2xfrSkuN?NUqnAgB`DVE~UtbC2GP z9>SQ}Xbcmu9>fGpqZp2vju3Nq#C8SV9bOUvu%V+8+=Ylra0JIFvQq-v=#B*ImBR$( zGy#o~<3M9%c+d!vi}-9t#lemGOKwZxn2g#Xf+1S)B%LBWCY0oFP_( zCxoOAmm^ey$At9YWGIypVp4K_%MdDoV=|Gk%~0Bc5fh6ieTLc|D2ShiNFhjY=vrx1 z5~JP*-B}$9D}HiIo85>$N0Ez7j^kXxkY8PklUXkE16AwU_!+J*A1%J!(TN81%zW<)71>w+lLX|@24<_?VA#GbjXZ*Twj zMA=)|(kO=uCA<{tQK%)viEH797*Y>;%O+v$3mmE=~mJ;@%Y z?>SEXA<8+)Ce3e^u68i8k}aZSq#ENMr{Dhq)tn?%v)iSpysNwvODH)hMz}|k;y+I{ zD@EDtRw+iFWmb%3oQxb3U;$1f7 z()=r0#bKfc(Z3SJQ8LO@xB6$oW?UfA=nR7s+8tUbkZ2Uyw%MY@1${^`r8Ii5`H*0) z5VfPqBr;czkX4yLc6nr&!BI@DXA^G5O<8lGasbV-Yd<_u*pD}nE%o0L>9w+<_DdqX z?IJRvK%$-Do+n|9-KRu(JBum#0*Q7u)0FI|MEPMBGbKtS;+vUf%YRFxv%dM?I;x`He);XXYImU&$GiR%f(9Fip-5e$f6XLNH_-~w3DG3qshQOiKt6kR%Nnj^)i_4kt!=7J4OYr;?$N0RzrcL z7(axi#FYnbt8PZYk0jr#c++$}{bHHCt!Rki2IL52VcXgcU5%?o;}boqrFqsbPGwlu z2wGk_m||HYsP1M!TdIoA>WXn+GcP=8o{I>o^$eDlTM=O&GESLK3RIM4=a7UrG9+S| zq;E25k(A)7D=Cr|ND00N5igEB4K0lnM+hSelpOeHl}G}vU0s+(=a-_=3buGlm9R(i zt(Z!YY4A`;HQ|fO3T@=j&6cuU!CQUbsC(tyEhpCVPF!=cbS0Q$xNVThQLzWff*C#-#6h}S`kNaY|$^D0wk`8C!8zztbBnXy#OM1K0IJqxFAB? z^W|nR^<595LV?ahOyb8qIGr1R-tQrRA&NznH!}b_FKhoPQLw-7#fI~Z|4xy1gb47A zIYIX;=aY$=aOEh?L#)FJYsd4q~bOYD?Zy!L(!$f8ATC%UC%LFn< zqYzu;mip-pNu7+ol~@rhNW5FG)|GJX5vmd;0+9l2q!fPaMS(!`y9Z;5{HH+io0Ung z_bQkqV#5}`L|wm&wdCENQlN-E?WB*lwAiPp&7=GlG~E8ino}zufe`jolRnx~g{_bn z3bz;HB0&cmcVy<^__Y~u8#Q*K9bXe2A|6{11Q|!3-3B-OQDFw%txbw$smhMTb{=-WB%8DG0dLiu)}TP59WoMu)`7J|gWkCAB?p*# z-{^B{iiVvi!{Q)I1R^_m{vMC>zv)3Q;TaUck_29|L(tb=1wxBbb(#{|jwHw-cp7t| ziX`euiYkjFDks@Seh=u9EpT0y=zPlOA;wgjU#9p%iN5XCF(FPgSg;j&9(EvmwsznN zPK|F)o+8eL)+_i@u4TI%v3s6_=ZVz#f%fXDOeBJ5iNI&&^ClOm4?G4)T#--N7OU3t z?-nMmoPi1gm|Iu~a9-u=hysE3*1Viya%qipRFObkf00=3OCZRK!DNdDk zwbNN)StKZy&C8pDi^rgT`18Fbt`2{R>~NbkeYW0 z_DfKJMguGzq%e1Bz2#%sXVp8r(dRYkYaQMoM(=Gkd3RtReJ$4@;!^x3_4zrjAUkna zka_L8pl5y+L{>aW!ER+uA+jRB*2#oVGfmQ!XlOHlWL318z(b=6NLD?Sk9g#gA53I} z8;2!O{v3p~mn#}omd&3$i-Pal$mX>}x-Tmj1dN0iM(Jugt1tg-8$y;*L!_j5flun` zVVoX9K(JwLv3G3kSQ(q_OJxOP-95++E?aD0Dl1r8&f#(`iZe`1U`y2_`R^R1Sg%dn z*~T56s7hSyTfw>{Ubv;s=@O4<(^vf7=a6d<^SZ`HVZVD6HF|z6A(U zam#RATCU)I*rpW${!Gsyn9foZR+poa>HhJR{D1+oq~x zn#S@PQpFAyyRAKj0dxSS+|Hka8L+j-FaXWN-*XwTwZ||(FSC-Z;oQPE&*mg1Glr$o zM$aq_2ai&ToM4gMcz%Cg$5%v|MCN!-vH;|e@i@e7yP;d?>i@$1BN<;)a(0z-wb)z7 zs{Ml*gy+`voN5AQgm<@Y+-G3`i1Pz0L*lP-(F*Qd#^Yl5&8+66XB-`fZCH%L2TpXn zfR`cbp)(6=cuK_|7Q}AU6T>55CI?(% zWHP=}u*&b&;3S({gU2LfkECR02CX4VuoQFQNVZ5bH<{DB8YGIyo{p)-$6WCnuO!1jI*$H8G<{UE-gzj zt^9GU>J|X*+%>`vhp%x3ck&yThqU1s;xdKfa+wSqH6IdyBY@BPjmkx$Zv;`9y)jIt z@-KE^d0GDPP zmuFIFW6ovHY!*iTIQF7h7$$cKlmXbp(>y_uzM7I0z=RW#&KmI;XMg4!jM zgq0X6BZF+pX)N3bslc~R_skAOL@38kCQGu=UIw!us{&>!uMA?2$257dz+#G6;4qJv zGMM6J`18qv#8pDWLtRQ_q@@u&qkA3$o!LfyH#pL3*czL0D1Js1udHON@_C6-M-)~_ zKa^OGRFZ+qC3 zs=PymmE9+^MVu5ofs8*9+yk;vdS3Id%!>Pb-5=*E%|noSvAk^DV)8?ULIW`Re>6%slmyD6<560ZtO?j;wT+DFy>Jlm^2 zVrnS~*E7n2im2;@7m-914!ZRBR|j>MX%gJ^RLkyPd1x=fd3GI&VLtWJ7Kx||U5qmjfYGRZ8O9P19PeQ`od z)N6Z2SWs1atXP7&_@r*yR*F0CGfp(NTWfL(1glcaBGFVLOqD1iFrSz7@hk!%h2vS( zAr6zq5sw#AB$Ct%(E{adWYRA(RMM1)l*~??XJ$VnE$y`^#W@t3ie7?_oyZUgFly|e zJORzNoh{*ocE;p{&KxEdvj$tk{M2=0?O$&X0KLLu$h_vl?Vf=GFE z{2nzVz&W!Kfzzc&AY@Fwhwi16@RUF!aVZZbvb7@za1xu{gBfuL%7qa*fR)UFz~S7O zqv4VQ?8{AZGCQ(&dwM6B+)$44Oe+EPspbAhrbAJ_E0IDVg5#Pihp8b3z$)DC^D3>F7BM!8=~m~5eYq}2xTV!ln#DGy_p+-9An_253_VP;32hlOj(B7)(PvIu~&(2vBb z(I|m9)jJ9a}Uky84!= z1HPONcX-^^a`zq0&4y;xRu5e>(5)R* z{5Ua%U>D>Fg&1Gg&1>=wH|@|YYtX`vgXrGK7uCbGuZW?Suc(n_)80P7Ic)km@Y4^! zBk1@m*gGfo92WT6pxm>~S%mfDtX?xycUZs|b@$VmuQA+p#6k7Felik$iOUpa!-PQW zIt2dpK2@(C-kurW2xU5-dlW@{X1bEr=xR#bN-I@YUnaBZVnJ6Dyjb`3X1@9#md*bx zntpgmzjXTp7YQIkuD)2}7RC?L9zw1@H|_k}xfOK${o(2BbV*oNm_OHp#r(YL-p}V4 zP*x=)>Hz(?!r;Wj&L3-H0$AV9B?lM%*H!C={i6N2>2TM>z!;(By4@_RX31)^Xs)|y z_f)mu4aeE@`g(I)-E_<;4SzL&!;K;eBb+Cf6=1Q#t ziCb9aRo%{3bNKCW2{({WT4s@J^m#Ktbq9<}wOYTxGt|1oBBH^~n#LyLA});R&Tgjg zH&+O}E(2*%7^t&+hz~S@%?fuhDhtRgMInw=iwjF2Px_T+PqT~V14(-vTeteX#hz?l zUDB*O_w(o59hB`9qqz+nk${HH>bb2D6UYFg>QJ+vFGGv`nWB9B{664JbQS(gt6Y2w zH9+;^+eLe`3Pq?DVSJgkw;N2j$-163H_hx5E>RBnAaRMijaTgi=9cD+?J>>E^LDma z^)O?f=?-Av1Td-*oy&S*=drDZ@+;_YC^r*B4!mpO6V01nR;%xUsvfpdc_b4#7NSbs zZ`gFWA?NR?>LnLec%A*ShBaJ0#PtOzs`{y3)I(6QQ1Jt1+R)*KolKFXaWk*0P3z{c zz4G>jmDGIo(B9QkOjR>I=>Hz8)eBx)s@3)1Sd{28rTXzj^p%_0_DYjfsNpyr^aiI_SN5a@=D1 z0QEU+XBi|UMGCkG^f2f7ieShGVk`hf^=0!2L&?GhAzeEUvz2LSG+es>EMU>JxM~XB zo_4c4i;|XEWQ%2n4Soa``KBdzfqWA3JnD`NnnJTx$xkVa1#~M1OpDVJs1Zh#*CaEp zTTwDVyPUx-E9(kX%Yt(NlnJ9#eg1TwmROP0(0g(O%^5M49P>@30sGjnLLUg8H?!$2uitR`)ECtdw82oJKPW%stb z{#CPkGQySnTyF+)TKx9|72r}dc6%gJrcB|~xb~ffo-A5BB}?vUK7vvC9er}mZaQxs ztMw`eyIHKJiU8NB)8eEgDY#8anARf~hj^wHsqH`U-rZMlq3|pHPp7n^R&88x(;?0| ztZ3z{{<~Shi*=}7f7jd$?hB^7S^Tg0BK!(Ou|n~`A17>s-4}KW@J8(yp~0Nh({=;X zT~!|hJJdEg!7r-y679BFAn|Y4+>Pa$Ha287|7_@&NQdj?q7nq|JSRBH}ZR- zIx<_X9pb#XxpDtrpL(+MKo%FV%p5xRu-+Nrx`elDl z?N-$S^x(#?;hb3x97sTDZ5S{LQ>=j=`;InQtc;<|^&vwRZBeH-9c^lTXQLt#3ENKE z=ioU6wyA5lMYQ2C08$2wyegwj@H_`Fx|5)HPdVgVYu?JM2B*W&<(T90Emfdx!_yi{ zol=8p6yvDvM=->}2_ja^GPm9*P3(Hi>!?}cWEqvTgTUJnAf zU#D>xN?-!TE%Ry{`ke-YNBDnR{=D>B>mQ z16$hVfMpB{%yzxD99G?GMJAccr);R{79Ua3x5L-_2ms{bzPROX`e1R<6>RLG0c(y2 zIV_R{VeVJaIUKIG?HGGNo+r-%1$*@DGMBa@sznK6827+!UoUPD6dKsmapZlWYuCr# zEC$Eg5=FB{-IA|vtzLK;TZ6&g4w*BEn!F>kE2Q8W+ZZm>UzQEW9@!drKP~K~T}G-F zmfC?SMgw`z5EVjQ3*_JV2M!Xyj2Wkn25dI zi-$rmm=@Om-ArLSdoy1WQSaH3HGE8GL3>(3A#D z5~ad)E!U6ag@=l;n~TM43Sp`~aDlODz75c9SJ%)23I;fOSiD!?vFKR}1Dt;Q;T6lF z63pSbGKhVOAf3<;SArEdbSJL%y;(?h$!hW{FBl^U*fQ5xW>v~BNL&g6bA-2NcR4C( zu?$4b2H^p?o=`kzzG#7Fx~RGZin=}S$`ebVt5hncs9}(lV;xK<#b}v}X)9Hzkpa0{ zX2YdqNz76^8iZ0aUXkE@xn9TJjCGX%#{NZ&&%^th5oteVHe~M+#W;NJBG)2+H6$_Jl;nLZBeh&c#?{b=`+4_I=n} zx=4u&M0nyJfwmIO8eXPB0R!E`0#SyWu-&Et=NLGkbMxqX(*hk1tDC13RfoC}NZ5Y= z8RUZ^+CLc&!G6#XH#1uXsm}eZCjw{)CR!}8ZU}7c#1pjTUF56UV)kN7uXccS{rGqNIH;)g9*|%&1JM69x_e z`+7O8t}%M><0vS}<0^C`dKhneT}h#JFGzQy)4LcQ)*)A`IeuhyYrWJA?? z4w*KL@{yUKeP2Y?154#Jl$fVD5u}xt7bV`eXc%V zzW?>SI{*5qLh^#&IGNZwoqNA{$*12h-@bYC`ppYEoxEyh-}wOZ?b%PSUQ~ZH-2gA} z8@7rF{Qq?F)*!LV{LKp4Z1gUF|9W+S#=cF?fB*Dbb$R~fw~y7Ai^&x=J*kH;P!60r zugp0z2Ag8YQwoOi|I{>7{b}SRd$g?%dJU$35IN!^%e-JJrANp*J^#=|3fpi=rkk zs?Ug&eKBXSrsJQke!G+%MF;xTqNanW_lOoW*ElQ*y~zlavkmkCJo=`4frLr)qQ=z2 z8LB;)r=GA7e)L7IZ_DrVhW1+=7@ot@nVwx(aH*33fwSvlp z$EZD#28|y!3ulbZ)W~QXMf6H`(SQ2zaq&$oNHFZV|Cs2$S z>7129^f(6%G%nCV^FG2ySi1&MI-8(CLN#ZE89)U^UiYw^E2LR)@0}80y{QnET+SEd zsIv5Lu^74kr`LQENUA|IPd-NOI`AX$&%tL`$t`7b$}ylvX=WI7M1LAIj&!C6?7Ci7 z)y37XbP)18(ojC)FryjX^N}wgf1UnN4UZJ?oUIWh` z;2?%iuqP~!_cY#FRWocgf-UY=HC^_%&@%HxI)22!lP;6F5=p zJIwU=#%7x8u^q0io7Ytx@_ zTt2Tl9xiNNOboLZYYD~o(K8&YHw*Yj9j$ln{AgzUMzH+rYL1oMQ0K8U;(@ZaI7so6 zgkGkfFTUOHH!F;U)>f-C<>iw55)u;0hzyDnQ`u^&d^UF&>?O-78%S$s# zSV}n6g1?3@exL~R8Ve(3k~n-CxW&-V;cgnQ4WPe%S?t9WU;zMe87!gVf_L(4W%1$u0t@S z80g5)_6m?+?f*)=K`;l#=?M4Eq-T1U!&>#;WRGGohSRu&(@f1rw#G~-<3^>^S6JhkLUo!_KW| z-1RNi*Ux&now#^^r57~kv)S`zZW=YWd+?;J$#G`cx{-5WB#c`f%yBd_i;*41X%7Z+ zin}YPh@Dw&f`@DT4kyB7x-h3~zMK=Ug=nXrn@-4J<~@+32l2xBuKo6;*W)|8qrC$i z6*=$F==>SwP9YiM!7*wE5E8StQu*9uX0_hJ{ei^mM+6TC?8k!QVr8*i=YgM_Nx;@V z_R?vNlk!1udQN2ac_3zOxz#zduc2*YG<|uC=WGc@5NJ3sOcV!IKCv0ER1hEKCeVl_ zwxqnxtAa(u2H-sbVKx?hz*r)?&eTU1- zsS{jsY2sYoVdJ$NZX%^V-qzhW@^-PAruG@%&Zh}HZ0F1HUc(q$7(43>8UvdO!LR}C zwfi&DAb8+x;L$-fUZe|sV^Z*ViC~wHj99XRr{82z5?_p_37(Ypr;dBpAetDP*z$^N@lG?B9if1SMgNTR1R{XVR|F2-ff z7wN!w8cSs>*;(osq=_lRYmC-tG0}M!y-K?Tsec-V3d{*jS4nv7m))1l@tXJ)d z9RGI87sl%l#2J|MCq6ZYFpO=ciNqY)C5~8n#?P<3&&#whWsD(}iz-79;JB}I&XSXg znN@TKep|P=L5=M{Ie(l>$XJ*B(~e>k$xl(FuQslCOB-tNoTW}aDFhFR*}ZE&FAnvw zWh>4oW)rGOR@-p^T`)57Efb^UX+-vhgAoXZ(76N8sb8l39c3XifFEC{y*??o2_WXS zw`3f#PNcpXuhy{7g00CQ*HPx(Ow*c!8DwT*GVO)odj+$0<;)q4i)M##Ep$)Gil(;I z8$!b{t!e0!im{qze2QzyQO~Y^rY>{>tCW+~jU5$Qgr!KfO)fv|aw;Uo#g5ZSMnE2A^v4tTXI|?2iCNKwbX3(m>>lLNZXADXDj65EIX}&+YyTh)9`1zUx_!wm@)~4oiB@ z@#bn!mk9?UuW%awzNfXD{$rO}#`Y}F2>c+xM30&y4C{2@2H6-s&dUk0((5$|u+H;r zCwHp{IG@y67tO>q>=RDuB;}(8$FYny*j@E3JL?qm5B%r$4E*y-qakr5oD@ebsU;86 zDTG}#_tJzd;>6&E2r$b&??GF=PL89ZZA#Xy2$SCmCAfFNQE|f-HcJ=V!v9A5D6iX9 z#FXBB2tx^SFjwWgX|s%)sD=!HvuLpAk#+;A`B>qro5l2&g8kNRo#a9@v|PG4JuPw3 z292q&-H#fyD;~UP*VCJ!hMGG?5S9V4=e_g+Zq?oQe)w*(S$JsGUcd}?ZbL7fU$Gun zGaHsM(WYQSr3ekIAleC?`}6!}S%jZ>U>}K*_2*;J5HNDQ^>pDjH@ojH=trO?E!6CA zlbtBj33{p)sVt0C7_6a6IOAf(^0}0@EH=W0XE#`H_L}=u(Gg|qOD~EiAsA*#c;V7v z!7&Vev>_Gg^7oVdG>FM!HW>TiG&9=tL(}DX2gWgH6)BQZ4lud!xlfj*tr()Y_Q%k6 z!N-HMx7e1mES2N8&C4-1By&DZJA0g1({ezw3qmo3F>&QNk`r8> 8); - } - return crc32val; -} -uint32_t crc32_inc(char* c, uint32_t len, uint32_t crc32val) { - uint8_t* s = (uint8_t*)c; - for (uint32_t i = 0; i < len; i++) { - if (c[i] == '\r') continue; - if (!c[i]) break; - crc32val = crc32_t[(crc32val ^ s[i]) & 0xFF] ^ (crc32val >> 8); - } - return crc32val; -} diff --git a/tools/makeheaders2-src/dirent.c b/tools/makeheaders2-src/dirent.c deleted file mode 100644 index c322a7ef..00000000 --- a/tools/makeheaders2-src/dirent.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * dirent.c - * - * Derived from DIRLIB.C by Matt J. Weinstein - * This note appears in the DIRLIB.H - * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 - * - * Updated by Jeremy Bettis - * Significantly revised and rewinddir, seekdir and telldir added by Colin - * Peters - * - * $Revision: 1.1 $ - * $Author: tml $ - * $Date: 2001/09/29 22:09:24 $ - * - */ - -#include -#include -#include -#include -#include - -#include "dirent.h" - -#define WIN32_LEAN_AND_MEAN -#include /* for GetFileAttributes */ - -#define SUFFIX "*" -#define SLASH "\\" - -/* - * opendir - * - * Returns a pointer to a DIR structure appropriately filled in to begin - * searching a directory. - */ -DIR * -opendir (const char *szPath) -{ - DIR *nd; - unsigned int rc; - - errno = 0; - - if (!szPath) - { - errno = EFAULT; - return (DIR *) 0; - } - - if (szPath[0] == '\0') - { - errno = ENOTDIR; - return (DIR *) 0; - } - - /* Attempt to determine if the given path really is a directory. */ - rc = GetFileAttributes(szPath); - if (rc == ((DWORD)-1)) - { - /* call GetLastError for more error info */ - errno = ENOENT; - return (DIR *) 0; - } - if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) - { - /* Error, entry exists but not a directory. */ - errno = ENOTDIR; - return (DIR *) 0; - } - - /* Allocate enough space to store DIR structure and the complete - * directory path given. */ - nd = (DIR *) malloc (sizeof (DIR) + strlen (szPath) + strlen (SLASH) + - strlen (SUFFIX)); - - if (!nd) - { - /* Error, out of memory. */ - errno = ENOMEM; - return (DIR *) 0; - } - - /* Create the search expression. */ - strcpy (nd->dd_name, szPath); - - /* Add on a slash if the path does not end with one. */ - if (nd->dd_name[0] != '\0' && - nd->dd_name[strlen (nd->dd_name) - 1] != '/' && - nd->dd_name[strlen (nd->dd_name) - 1] != '\\') - { - strcat (nd->dd_name, SLASH); - } - - /* Add on the search pattern */ - strcat (nd->dd_name, SUFFIX); - - /* Initialize handle to -1 so that a premature closedir doesn't try - * to call _findclose on it. */ - nd->dd_handle = -1; - - /* Initialize the status. */ - nd->dd_stat = 0; - - /* Initialize the dirent structure. ino and reclen are invalid under - * Win32, and name simply points at the appropriate part of the - * findfirst_t structure. */ - nd->dd_dir.d_ino = 0; - nd->dd_dir.d_reclen = 0; - nd->dd_dir.d_namlen = 0; - nd->dd_dir.d_name = nd->dd_dta.name; - - return nd; -} - - -/* - * readdir - * - * Return a pointer to a dirent structure filled with the information on the - * next entry in the directory. - */ -struct dirent * -readdir (DIR * dirp) -{ - errno = 0; - - /* Check for valid DIR struct. */ - if (!dirp) - { - errno = EFAULT; - return (struct dirent *) 0; - } - - if (dirp->dd_dir.d_name != dirp->dd_dta.name) - { - /* The structure does not seem to be set up correctly. */ - errno = EINVAL; - return (struct dirent *) 0; - } - - if (dirp->dd_stat < 0) - { - /* We have already returned all files in the directory - * (or the structure has an invalid dd_stat). */ - return (struct dirent *) 0; - } - else if (dirp->dd_stat == 0) - { - /* We haven't started the search yet. */ - /* Start the search */ - dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta)); - - if (dirp->dd_handle == -1) - { - /* Whoops! Seems there are no files in that - * directory. */ - dirp->dd_stat = -1; - } - else - { - dirp->dd_stat = 1; - } - } - else - { - /* Get the next search entry. */ - if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) - { - /* We are off the end or otherwise error. */ - _findclose (dirp->dd_handle); - dirp->dd_handle = -1; - dirp->dd_stat = -1; - } - else - { - /* Update the status to indicate the correct - * number. */ - dirp->dd_stat++; - } - } - - if (dirp->dd_stat > 0) - { - /* Successfully got an entry. Everything about the file is - * already appropriately filled in except the length of the - * file name. */ - dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name); - return &dirp->dd_dir; - } - - return (struct dirent *) 0; -} - - -/* - * closedir - * - * Frees up resources allocated by opendir. - */ -int -closedir (DIR * dirp) -{ - int rc; - - errno = 0; - rc = 0; - - if (!dirp) - { - errno = EFAULT; - return -1; - } - - if (dirp->dd_handle != -1) - { - rc = _findclose (dirp->dd_handle); - } - - /* Delete the dir structure. */ - free (dirp); - - return rc; -} - -/* - * rewinddir - * - * Return to the beginning of the directory "stream". We simply call findclose - * and then reset things like an opendir. - */ -void -rewinddir (DIR * dirp) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return; - } - - if (dirp->dd_handle != -1) - { - _findclose (dirp->dd_handle); - } - - dirp->dd_handle = -1; - dirp->dd_stat = 0; -} - -/* - * telldir - * - * Returns the "position" in the "directory stream" which can be used with - * seekdir to go back to an old entry. We simply return the value in stat. - */ -long -telldir (DIR * dirp) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return -1; - } - return dirp->dd_stat; -} - -/* - * seekdir - * - * Seek to an entry previously returned by telldir. We rewind the directory - * and call readdir repeatedly until either dd_stat is the position number - * or -1 (off the end). This is not perfect, in that the directory may - * have changed while we weren't looking. But that is probably the case with - * any such system. - */ -void -seekdir (DIR * dirp, long lPos) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return; - } - - if (lPos < -1) - { - /* Seeking to an invalid position. */ - errno = EINVAL; - return; - } - else if (lPos == -1) - { - /* Seek past end. */ - if (dirp->dd_handle != -1) - { - _findclose (dirp->dd_handle); - } - dirp->dd_handle = -1; - dirp->dd_stat = -1; - } - else - { - /* Rewind and read forward to the appropriate index. */ - rewinddir (dirp); - - while ((dirp->dd_stat < lPos) && readdir (dirp)) - ; - } -} \ No newline at end of file diff --git a/tools/makeheaders2-src/dirent.h b/tools/makeheaders2-src/dirent.h deleted file mode 100644 index dcaebd22..00000000 --- a/tools/makeheaders2-src/dirent.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * DIRENT.H (formerly DIRLIB.H) - * - * by M. J. Weinstein Released to public domain 1-Jan-89 - * - * Because I have heard that this feature (opendir, readdir, closedir) - * it so useful for programmers coming from UNIX or attempting to port - * UNIX code, and because it is reasonably light weight, I have included - * it in the Mingw32 package. I have also added an implementation of - * rewinddir, seekdir and telldir. - * - Colin Peters - * - * This code is distributed in the hope that is will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAMED. This includeds but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * $Revision: 1.1 $ - * $Author: tml $ - * $Date: 2001/09/29 22:09:24 $ - * - */ - -#ifndef __STRICT_ANSI__ - -#ifndef _DIRENT_H_ -#define _DIRENT_H_ - -#include - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif - -struct dirent -{ - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - char* d_name; /* File name. */ - /* NOTE: The name in the dirent structure points to the name in the - * finddata_t structure in the DIR. */ -}; - -/* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - */ -typedef struct -{ - /* disk transfer area for this dir */ - struct _finddata_t dd_dta; - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct dirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - short dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - char dd_name[1]; -} DIR; - - -DIR* opendir (const char*); -struct dirent* readdir (DIR*); -int closedir (DIR*); -void rewinddir (DIR*); -long telldir (DIR*); -void seekdir (DIR*, long); - -#ifdef __cplusplus -} -#endif - -#endif /* Not RC_INVOKED */ - -#endif /* Not _DIRENT_H_ */ - -#endif /* Not __STRICT_ANSI__ */ diff --git a/tools/makeheaders2-src/makeheaders.cpp b/tools/makeheaders2-src/makeheaders.cpp deleted file mode 100644 index 932b67d6..00000000 --- a/tools/makeheaders2-src/makeheaders.cpp +++ /dev/null @@ -1,1161 +0,0 @@ -#include -#include -#include -#include -#include -#ifndef _WIN32 - #include - #include -#else - #include - #include - #include "dirent.c" -#endif - -#include "crc32.h" - -using namespace std; - -static char finalpath[4096]; - -// Printing -enum class PrintColor { - Default = 0, - Red, - Yellow, - Green, - Purple, -}; -void PrintHeader(FILE* f, const char* str, PrintColor col) { - int color = 0; -#ifdef _WIN32 - switch (col) { - case PrintColor::Red: color = 4; break; - case PrintColor::Yellow: color = 14; break; - case PrintColor::Green: color = 2; break; - case PrintColor::Purple: color = 5; break; - default: color = 0xF; break; - } - CONSOLE_SCREEN_BUFFER_INFO csbi; - HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) { - SetConsoleTextAttribute(hStdOut, (csbi.wAttributes & 0xF0) | color); - } - fprintf(f, str); - SetConsoleTextAttribute(hStdOut, csbi.wAttributes); -#else - switch (col) { - case PrintColor::Red: color = 91; break; - case PrintColor::Yellow: color = 93; break; - case PrintColor::Green: color = 92; break; - case PrintColor::Purple: color = 95; break; - default: color = 37; break; - } - fprintf(f, "\x1b[1;%dm%s\x1b[0m", color, str); -#endif -} - -#ifdef _WIN32 -#include - -static ssize_t getline(char** string, size_t* n, FILE* f) { - if (string == NULL || f == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - int c = getc(f); - if (c == EOF) - return -1; - - size_t pos = 0; - size_t baseSize = 128; - - if (*string == NULL) { - *string = (char*)malloc(baseSize); - if (!*string) - abort(); - *n = baseSize; - } - - for (; c != EOF; c = getc(f)) { - if (pos + 1 >= *n) { - size_t size = max(*n + (*n >> 2), baseSize); - *string = (char*)realloc(*string, size); - if (!*string) - abort(); - *n = size; - } - - ((unsigned char *)(*string))[pos++] = c; - if (c == '\n') - break; - } - - (*string)[pos] = '\0'; - return pos; -} -#endif - -class Scanner { -private: - char* start; - char* current; - - FILE* file; - char* buffer; - size_t buffer_len; - - bool readLine() { - ssize_t result = getline(&buffer, &buffer_len, file); - if (result == -1) { - isDone = true; - return false; - } - - start = current = buffer; - line++; - - return true; - } - - char peek() { - return current[0]; - } - - char peekNext() { - if (isAtEnd()) - return '\0'; - return current[1]; - } - - char advance() { - current++; - return current[-1]; - } - - bool isWhitespace(char c) { - if (c == '\0') - return false; - return isspace(c); - } - - void captureToken() { - while (!isWhitespace(peek())) - advance(); - } - - std::string getLineString() { - std::string output(start, current - start); - - output.erase(output.find_last_not_of("\r\n")+1); - - return output; - } - -public: - int line; - bool isDone; - - Scanner(FILE *f) { - start = current = nullptr; - isDone = false; - line = 0; - - buffer = nullptr; - buffer_len = 0; - - file = f; - readLine(); - } - - bool isAtEnd() { - return current[0] == '\0'; - } - - bool peekToken(const char *token) { - if (isAtEnd() && !readLine()) - return ""; - - char *last = current; - captureToken(); - - int length = strlen(token); - if (current - start == length && !memcmp(start, token, length)) { - current = last; - return true; - } - - current = last; - return false; - } - - bool matchToken(const char *token) { - if (isAtEnd() && !readLine()) - return ""; - - char *last = current; - captureToken(); - - int length = strlen(token); - if (current - start == length && !memcmp(start, token, length)) { - skipWhitespace(); - start = current; - return true; - } - - current = last; - return false; - } - - std::string getToken() { - if (isAtEnd() && !readLine()) - return ""; - - captureToken(); - - std::string output(start, current - start); - - skipWhitespace(); - start = current; - - return output; - } - - std::string peekRestOfLine() { - if (isAtEnd() && !readLine()) - return ""; - - char *last = current; - while (!isAtEnd()) - advance(); - - std::string output = getLineString(); - current = last; - return output; - } - - std::string getRestOfLine() { - if (isAtEnd()) - return ""; - while (!isAtEnd()) - advance(); - return getLineString(); - } - - int findCharPos(char match) { - if (isAtEnd() && !readLine()) - return -1; - - char *last = current; - while (peek() != match) { - advance(); - if (isAtEnd()) { - current = last; - return -1; - } - } - - int pos = current - last; - current = last; - return pos; - } - - std::string getLineUntilChar(char match) { - if (isAtEnd() && !readLine()) - return ""; - - while (peek() != match) { - advance(); - if (isAtEnd()) - break; - } - - std::string output(start, current - start); - return output; - } - - bool gotoNextLine() { - return readLine(); - } - - bool skipWhitespace() { - while (true) { - switch (peek()) { - case ' ': - case '\r': - case '\t': - case '\n': - advance(); - break; - default: - return true; - } - } - - return true; - } - - ~Scanner() { - free(buffer); - } -}; - -static void MakeDir(const char *dir) { - struct stat st = {0}; - if (stat(dir, &st) == -1) { -#ifdef _WIN32 - mkdir(dir); -#else - mkdir(dir, 0700); -#endif - } -} - -static void RecursiveMakeDir(const char *path) { - char tmp[4096]; - - snprintf(tmp, sizeof(tmp), "%s", path); - size_t len = strlen(tmp); - - if (tmp[len - 1] == '/') - tmp[len - 1] = 0; - - for (char *p = tmp + 1; *p; p++) { - if (*p == '/') { - *p = '\0'; - MakeDir(tmp); - *p = '/'; - } - } - - MakeDir(tmp); -} - -struct VARIABLE { - std::string class_type; - std::string variable_name; - int block_depth; -}; - -struct CLASSFILE { - std::vector includes; - std::string class_name; - std::string parent_class_name; - std::string file_name; - std::vector public_vars; - std::vector private_vars; - std::vector protected_vars; - std::vector public_funcs; - std::vector private_funcs; - std::vector protected_funcs; - vector classes_needed; -}; - -int num_generated_headers = 0; - -int FindChar(char* str, char c) { - char* strln = str; - do { - if (*strln == c) - return strln - str; - strln++; - } while (*strln != 0); - return -1; -} -int FindLastChar(char* str, char c) { - char* strln = str + strlen(str); - do { - if (*strln == c) - return strln - str; - strln--; - } while (strln != str); - return -1; -} - -string replaceFirstOccurrence(string& s, const string& toReplace, const string& replaceWith) { - std::size_t pos = s.find(toReplace); - if (pos == string::npos) return s; - return s.replace(pos, toReplace.length(), replaceWith); -} - -void WriteVariable(FILE* fp, VARIABLE var) { - int num = var.block_depth; - do { - fprintf(fp, " "); - } while (num-- > 0); - fprintf(fp, "%s %s\n", var.class_type.c_str(), var.variable_name.c_str()); -} - -void WriteClass(const char* directory, CLASSFILE data) { - string class_name(data.class_name); - if (class_name == string("\x01\x01\x01\x01")) - return; - if (class_name == string("")) - return; - - string direc = string(directory); - string basedirec = string(finalpath); - - direc = replaceFirstOccurrence(direc, "source", "include"); - basedirec = replaceFirstOccurrence(basedirec, "source", "include"); - - struct stat st = {0}; - - if (direc.find("include") != std::string::npos) { - if (stat(direc.substr(0, direc.find("include") + 7).c_str(), &st) == -1) { - RecursiveMakeDir(direc.substr(0, direc.find("include") + 7).c_str()); - } - } - - if (stat(direc.c_str(), &st) == -1) - RecursiveMakeDir(direc.c_str()); - - std::string filename = direc + data.file_name + ".h"; - FILE *fp = fopen(filename.c_str(), "wb"); - int err = errno; - if (!fp) { - PrintHeader(stderr, "error: ", PrintColor::Red); - printf("Could not open %s because %s\n", filename.c_str(), strerror(err)); - return; - } - - num_generated_headers++; - - class_name = (direc.c_str() + basedirec.length() + 1); - class_name += data.file_name; - std::transform(class_name.begin(), class_name.end(), class_name.begin(), [](unsigned char c) -> unsigned char { - if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) - return '_'; - return ::toupper(c); - }); - - fprintf(fp, "#ifndef %s_H\n", class_name.c_str()); - fprintf(fp, "#define %s_H\n", class_name.c_str()); - fprintf(fp, "\n"); - fprintf(fp, "#define PUBLIC\n"); - fprintf(fp, "#define PRIVATE\n"); - fprintf(fp, "#define PROTECTED\n"); - fprintf(fp, "#define STATIC\n"); - fprintf(fp, "#define VIRTUAL\n"); - fprintf(fp, "#define EXPOSED\n"); - fprintf(fp, "\n"); - for (size_t i = 0; i < data.classes_needed.size(); i++) { - fprintf(fp, "class %s;\n", data.classes_needed[i].c_str()); - } - fprintf(fp, "\n"); - - for (std::vector::iterator it = data.includes.begin(); it != data.includes.end(); ++it) { - fprintf(fp, "#include %s\n", (*it).c_str()); - } - fprintf(fp, "\n"); - fprintf(fp, "class %s%s%s {\n", data.class_name.c_str(), data.parent_class_name != string("") ? " : public " : "", data.parent_class_name != string("") ? data.parent_class_name.c_str() : ""); - - bool did_private = false; - if (data.private_vars.size() > 0 || data.private_funcs.size() > 0) { - fprintf(fp, "private:\n"); - bool wrote_any = false; - for (std::vector::iterator it = - data.private_vars.begin(); it != - data.private_vars.end(); ++it) { - WriteVariable(fp, (*it)); - wrote_any = true; - } - - if (wrote_any) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.private_funcs.begin(); it != - data.private_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - did_private = true; - } - if (data.public_vars.size() > 0 || data.public_funcs.size() > 0) { - if (did_private) - fprintf(fp, "\n"); - - fprintf(fp, "public:\n"); - bool wrote_any = false; - for (std::vector::iterator it = - data.public_vars.begin(); it != - data.public_vars.end(); ++it) { - WriteVariable(fp, (*it)); - wrote_any = true; - } - - if (wrote_any) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.public_funcs.begin(); it != - data.public_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - } - if (data.protected_vars.size() > 0 || data.protected_funcs.size() > 0) { - if (did_private) - fprintf(fp, "\n"); - - fprintf(fp, "protected:\n"); - bool wrote_any = false; - for (std::vector::iterator it = - data.protected_vars.begin(); it != - data.protected_vars.end(); ++it) { - WriteVariable(fp, (*it)); - wrote_any = true; - } - - if (wrote_any) - fprintf(fp, "\n"); - - for (std::vector::iterator it = - data.protected_funcs.begin(); it != - data.protected_funcs.end(); ++it) { - fprintf(fp, " %s\n", (*it).c_str()); - } - } - fprintf(fp, "};\n"); - - fprintf(fp, "\n"); - fprintf(fp, "#endif /* %s_H */\n", class_name.c_str()); - - fclose(fp); -} - -vector ClassNames; -string FindClassName(char* filename) { - FILE *fp = fopen(filename, "rb"); - if (!fp) { - fclose(fp); - printf("Could not load file (FindClassName): %s!\n", filename); - exit(EXIT_FAILURE); - } - - bool found_interface = false; - std::string token; - - Scanner scanner(fp); - if (scanner.isDone) { - fclose(fp); - return string(""); - } - - token = scanner.getToken(); - - while (!scanner.isDone) { - if (token == "#if") { - token = scanner.getToken(); - - if (scanner.isDone) { - fclose(fp); - return string(""); - } - else if (token == "INTERFACE") - found_interface = true; - } - else if (!found_interface) { - fclose(fp); - return string(""); - } - - if (token == "class") { - token = scanner.getToken(); - fclose(fp); - return token; - } - - token = scanner.getToken(); - } - - fclose(fp); - return string(""); -} - -CLASSFILE ReadClass(char* filename) { - FILE *fp; - CLASSFILE test; - fp = fopen(filename, "rb"); - if (!fp) { - printf("Could not load file (ReadClass): %s!\n", filename); - exit(EXIT_FAILURE); - } - - bool in_interface = false; - bool found_interface = false; - int in_variables = 0; - - std::string class_filename = std::string(filename); - std::string class_name; - - std::size_t first = class_filename.find_last_of("/"); - if (first == std::string::npos) - first = 0; - else - first++; - - std::string split = class_filename.substr(first); - std::size_t last = split.find_last_of("."); - if (last == std::string::npos) - last = split.length(); - - test.file_name = split.substr(0, last); - - int ifScope = 0; - int brackscope = 0; - int in_struct_or_enum = 0; - - Scanner scanner(fp); - if (scanner.isDone) { - fclose(fp); - return test; - } - - std::string token = scanner.getToken(); - -#define throw_err_start() { \ - char fmt[4096 + 32]; \ - snprintf(fmt, sizeof(fmt), "error in '%s', line %d: ", filename, scanner.line); \ - PrintHeader(stderr, fmt, PrintColor::Red); \ -} -#define throw_err_end() exit(EXIT_FAILURE) -#define throw_err(msg) \ - throw_err_start(); \ - fprintf(stderr, msg " in class '%s'!\n", test.file_name.c_str()); \ - throw_err_end(); - - while (!scanner.isDone) { - std::string first_token = token; - if (token == "#if") { - token = scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - - if (token == "INTERFACE") { - in_interface = true; - found_interface = true; - } - - ifScope++; - } - else if (!found_interface) { - test.class_name = string("\x01\x01\x01\x01"); - break; - } - if (token == "#endif") { - if (!scanner.gotoNextLine()) - break; - if (in_interface) { - in_interface = false; - in_variables = 0; - } - if (ifScope > 0) { - ifScope--; - if (ifScope < 0 || brackscope != 0) { - throw_err("Malformed source code"); - } - } - } - else if (token == "#include") { - std::string rest_of_line = scanner.getRestOfLine(); - if (rest_of_line == "") { - throw_err("Malformed source code"); - } - if (in_interface) - test.includes.push_back(rest_of_line); - } - else if (token == "need_t") { - if (scanner.findCharPos(';') == -1) { - throw_err("Missing ';' after class name for 'need_t'"); - } - - std::string rest_of_line = scanner.getLineUntilChar(';'); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - else if (rest_of_line == "") { - throw_err("Missing class name for 'need_t'"); - } - - test.classes_needed.push_back(rest_of_line); - } - else if (token == "class") { - if (test.class_name.empty()) { - test.class_name = scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file after class name"); - } - - if (scanner.matchToken(":") && scanner.matchToken("public")) { - token = scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file after 'public'"); - } - test.parent_class_name = token; - } - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - - in_variables = 1; - } - } - else if (token == "{" || token == "}" || token == "};") { - if (token == "{") { - if (in_interface) - brackscope++; - } - else if (token == "}" || token == "};") { - if (in_interface) { - brackscope--; - if (brackscope < 0) { - throw_err("Malformed source code"); - } - } - - if (in_struct_or_enum > 0) { - std::string var_name = ""; - if (token == "}") - var_name = scanner.getToken(); - VARIABLE var = VARIABLE { token, var_name, 0 }; - if (in_variables == 1) - test.private_vars.push_back(var); - else if (in_variables == 2) - test.public_vars.push_back(var); - else if (in_variables == 3) - test.protected_vars.push_back(var); - in_struct_or_enum--; - } - } - } - else if (token.rfind("private", 0) == 0) { - if (token.find(":") == std::string::npos && !scanner.matchToken(":")) { - throw_err("Unexpected token after 'private'"); - } - if (scanner.isDone) { - throw_err("Unexpected end of file after 'private:'"); - } - if (in_variables) - in_variables = 1; - } - else if (token.rfind("public", 0) == 0) { - if (token.find(":") == std::string::npos && !scanner.matchToken(":")) { - throw_err("Unexpected token after 'public'"); - } - if (scanner.isDone) { - throw_err("Unexpected end of file after 'public:'"); - } - if (in_variables) - in_variables = 2; - } - else if (token.rfind("protected", 0) == 0) { - if (token.find(":") == std::string::npos && !scanner.matchToken(":")) { - throw_err("Unexpected token after 'protected'"); - } - if (scanner.isDone) { - throw_err("Unexpected end of file after 'protected:'"); - } - if (in_variables) - in_variables = 3; - } - else if (in_variables) { - if (token == "") { - token = scanner.getToken(); - continue; - } - - bool token_is_struct = false; - if (token == "struct" || token == "enum") { - in_struct_or_enum++; - token_is_struct = true; - } - else if (in_interface) { - for (size_t i = 0; i < ClassNames.size(); i++) { - if (token == ClassNames[i]) { - test.classes_needed.push_back(token); - break; - } - } - } - - std::string rest_of_line; - if (token_is_struct) { - if (!scanner.peekToken("{")) - rest_of_line = scanner.getToken() + " {"; - else - rest_of_line = "{"; - if (scanner.isDone) { - throw_err("Unexpected end of file after 'struct' or 'enum'"); - } - } else { - rest_of_line = scanner.getRestOfLine(); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - } - - if (in_interface) { - VARIABLE var = VARIABLE { token, rest_of_line, token_is_struct ? 0 : in_struct_or_enum }; - if (in_variables == 1) - test.private_vars.push_back(var); - else if (in_variables == 2) - test.public_vars.push_back(var); - else if (in_variables == 3) - test.protected_vars.push_back(var); - } - } - else if ((token == "PUBLIC" || token == "PRIVATE" || token == "PROTECTED") && !in_interface) { - bool statik = false; - bool virtua = false; - if (scanner.peekToken("STATIC")) { - statik = true; - scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - } - else if (scanner.peekToken("VIRTUAL")) { - virtua = true; - scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - } - - token = scanner.getToken(); - - std::string type = ""; - do { - if (token.find(":") != std::string::npos) - break; - else if (token.find("{") != std::string::npos) { - throw_err("Malformed source code"); - } - - type += token + " "; - - token = scanner.getToken(); - if (scanner.isDone) { - throw_err("Unexpected end of file"); - } - } while (true); - - std::string rest_of_line = token + " " + scanner.peekRestOfLine(); - size_t where = rest_of_line.find("::"); - if (where == std::string::npos) { - throw_err("Could not find class name"); - } - - std::string this_class_name = rest_of_line.substr(0, where); - if (test.class_name != this_class_name) { - throw_err_start(); - fprintf(stderr, "Incorrect class name '%s' (should be '%s'!)\n", this_class_name.c_str(), test.file_name.c_str()); - throw_err_end(); - } - - std::string function_name = rest_of_line.substr(where + 2); - - // Remove the { - function_name.erase(function_name.find_first_of("{")); - - // Trim whitespace - size_t last_of_whitespace = function_name.find_last_not_of(" "); - if (last_of_whitespace != std::string::npos) - function_name.erase(last_of_whitespace + 1); - - function_name = type + function_name + ";"; - if (statik) - function_name = "static " + function_name; - else if (virtua) - function_name = "virtual " + function_name; - - if (first_token == "PRIVATE") - test.private_funcs.push_back(string(function_name)); - else if (first_token == "PUBLIC") - test.public_funcs.push_back(string(function_name)); - else if (first_token == "PROTECTED") - test.protected_funcs.push_back(string(function_name)); - - scanner.gotoNextLine(); - } - - token = scanner.getToken(); - } - -#undef throw_err - - fclose(fp); - return test; -} - -bool CheckExtension(const char* filename, const char* extension) { - char *dot = strrchr((char*)filename, '.'); - return dot && !strcmp(dot, extension); -} - -#ifdef _WIN32 -bool IsPathDir(const char *path) { - struct stat fstat; - if (stat(path, &fstat) < 0) - return false; - return (fstat.st_mode & S_IFMT) == S_IFDIR; -} -#endif - -bool FindClasses(const char* name, int depth) { - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir(name))) - return false; - - while ((entry = readdir(dir)) != NULL) { - char path[4096 + 256]; - snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); - -#ifdef _WIN32 - if (IsPathDir(path)) -#else - if (entry->d_type == DT_DIR) -#endif - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - FindClasses(path, depth + 1); - } - else if (depth == 0) - continue; - else if (CheckExtension(entry->d_name, ".cpp")) { - string class_name = FindClassName(path); - if (class_name != "") - ClassNames.push_back(class_name); - } - } - - closedir(dir); - return true; -} - -struct ClassHash { - uint32_t FilenameHash; - uint32_t InterfaceChecksum; -}; -vector ClassHashes; -int GetClassHash(uint32_t filenameHash) { - for (size_t i = 0; i < ClassHashes.size(); i++) { - if (ClassHashes[i].FilenameHash == filenameHash) - return i; - } - return -1; -} -int PutClassHash(uint32_t filenameHash, uint32_t checkSum) { - int idx = GetClassHash(filenameHash); - if (idx >= 0) { - ClassHashes[idx].FilenameHash = filenameHash; - ClassHashes[idx].InterfaceChecksum = checkSum; - return 0; - } - - ClassHash ch; - ch.FilenameHash = filenameHash; - ch.InterfaceChecksum = checkSum; - ClassHashes.push_back(ch); - return 1; -} - -std::string classpath; - -void LoadClassHashTable() { - FILE* f = fopen(classpath.c_str(), "rb"); - if (f) { - for (;;) { - ClassHash ch; - if (fread(&ch, sizeof(ClassHash), 1, f) <= 0) - break; - - ClassHashes.push_back(ch); - } - fclose(f); - } -} -void SaveClassHashTable() { - FILE* f = fopen(classpath.c_str(), "wb"); - if (f) { - for (size_t i = 0; i < ClassHashes.size(); i++) { - fwrite(&ClassHashes[i], sizeof(ClassHash), 1, f); - } - fclose(f); - } -} - -bool MakeHeaderCheck(char* filename) { - FILE* f = fopen(filename, "rb"); - if (!f) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Could not open file '%s'!\n", filename); - exit(EXIT_FAILURE); - } - - Scanner scanner(f); - if (scanner.isDone) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Could not find class name in file '%s'!\n", filename); - fclose(f); - return false; - } - - int interfaceStart = -1; - int interfaceEnd = -1; - int ifScope = 0; - - std::string token = scanner.getToken(); - while (!scanner.isDone) { - int64_t tokenStart = ftell(f); - - if (token == "#if") { - ifScope++; - token = scanner.getToken(); - - if (scanner.isDone) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Unexpected end of file in file '%s'!\n", filename); - fclose(f); - return false; - } - else if (token == "INTERFACE") - interfaceStart = ftell(f); - } - else if (token == "#endif") { - if (--ifScope == 0) { - interfaceEnd = tokenStart; - break; - } - } - - token = scanner.getToken(); - } - - if (interfaceStart == -1) - return false; - else if (interfaceEnd == -1) { - PrintHeader(stderr, "error: ", PrintColor::Red); - fprintf(stderr, "Missing matching #endif in file '%s'!\n", filename); - exit(EXIT_FAILURE); - return false; - } - - // get function descriptors - uint32_t FDChecksum = 0x00000000; - while (!scanner.isDone) { - if (!scanner.gotoNextLine()) - break; - - std::string token = scanner.getToken(); - if (token == "PUBLIC" || token == "PRIVATE" || token == "PROTECTED") { - std::string rest_of_line = scanner.getRestOfLine(); - std::size_t found = rest_of_line.find_last_of("{"); - if (found != std::string::npos) - rest_of_line.erase(found, 1); - const char* line = rest_of_line.c_str(); - FDChecksum = crc32_inc((char*)line, strlen(line), FDChecksum); - } - } - - char* interfaceField = (char*)calloc(1, interfaceEnd - interfaceStart + 1); - fseek(f, interfaceStart, SEEK_SET); - fread(interfaceField, interfaceEnd - interfaceStart, 1, f); - - uint32_t NameHash = crc32(filename, strlen(filename)); - uint32_t ComparisonHash = 0x00000000; - - int idx = GetClassHash(NameHash); - if (idx != -1) - ComparisonHash = ClassHashes[idx].InterfaceChecksum; - - uint32_t Checksum = crc32_inc(interfaceField, interfaceEnd - interfaceStart, FDChecksum); - if (Checksum == ComparisonHash) { - SaveClassHashTable(); - return false; - } - - PutClassHash(NameHash, Checksum); - - return true; -} -bool ListClassDir(const char* name, const char* parent) { - DIR* dir; - struct dirent* entry; - - if (!(dir = opendir(name))) - return false; - - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - char path[4096]; - snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); - -#ifdef _WIN32 - if (IsPathDir(path)) -#else - if (entry->d_type == DT_DIR) -#endif - ListClassDir(path, parent); - else if (CheckExtension(entry->d_name, ".cpp") && MakeHeaderCheck(path)) { - char parentFolder[4096]; - snprintf(parentFolder, sizeof(parentFolder), "%s", name); - size_t sz = strlen(name); - if (parentFolder[sz - 1] != '/') { - parentFolder[sz] = '/'; - parentFolder[sz + 1] = 0; - } - - WriteClass(parentFolder, ReadClass(path)); - } - } - - closedir(dir); - return true; -} - -int main(int argc, char **argv) { - if (argc <= 1) { - printf("No source code path!\n"); - printf("Usage:\n"); - printf(" %s [options] path\n", argv[0]); - return 0; - } - -#ifdef _WIN32 - _fullpath(finalpath, argv[1], sizeof(finalpath)); -#else - realpath(argv[1], finalpath); -#endif - - std::string direc = std::string(finalpath); - classpath = replaceFirstOccurrence(direc, "source", "include"); - - struct stat st = {0}; - if (stat(direc.c_str(), &st) == -1) - RecursiveMakeDir(direc.c_str()); - - classpath += "/makeheaders.bin"; - - clock_t start, stop; - start = clock(); - - LoadClassHashTable(); - if (FindClasses(finalpath, 0)) - ListClassDir(finalpath, finalpath); - SaveClassHashTable(); - - stop = clock(); - PrintHeader(stdout, "makeheaders: ", PrintColor::Green); - printf("Generated %d header(s) in %.3f milliseconds.\n\n", num_generated_headers, (stop - start) * 1000.f / CLOCKS_PER_SEC); - - return 0; -} From 0cff1e32338ac987fa00343856f5a96b54025e4b Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:25:09 -0400 Subject: [PATCH 02/13] fix SDL2 includes on macOS --- source/Engine/Includes/StandardSDL2.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/source/Engine/Includes/StandardSDL2.h b/source/Engine/Includes/StandardSDL2.h index 41c735c7..7057dff4 100644 --- a/source/Engine/Includes/StandardSDL2.h +++ b/source/Engine/Includes/StandardSDL2.h @@ -5,13 +5,8 @@ // SDL2 includes #include #elif MACOSX - #if USING_FRAMEWORK - // SDL2 includes - #include - #else - // SDL2 includes - #include - #endif + // SDL2 includes + #include #elif SWITCH // SDL2 includes #include From 8e5d134b2a2bf8a8a7071fa63ef4b2b8b653c9bc Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:27:17 -0400 Subject: [PATCH 03/13] fix SDL2 includes on macOS --- source/Engine/Input/ControllerRumble.h | 2 ++ source/Engine/Input/Input.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/source/Engine/Input/ControllerRumble.h b/source/Engine/Input/ControllerRumble.h index 2b67727b..c97e6fd0 100644 --- a/source/Engine/Input/ControllerRumble.h +++ b/source/Engine/Input/ControllerRumble.h @@ -1,6 +1,8 @@ #ifndef CONTROLLERRUMBLE_H #define CONTROLLERRUMBLE_H +#include + struct ControllerRumble { float LargeMotorFrequency; float SmallMotorFrequency; diff --git a/source/Engine/Input/Input.h b/source/Engine/Input/Input.h index b88fa2d8..d012c8db 100644 --- a/source/Engine/Input/Input.h +++ b/source/Engine/Input/Input.h @@ -1,6 +1,8 @@ #ifndef INPUT_H #define INPUT_H +#include + enum Keyboard { Key_UNKNOWN = -1, From 7e399e2dbb02556c5ebbcd9de1093243b1df060a Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:28:26 -0400 Subject: [PATCH 04/13] #include Matrix4x4 --- include/Engine/Rendering/D3D/D3DRenderer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Engine/Rendering/D3D/D3DRenderer.h b/include/Engine/Rendering/D3D/D3DRenderer.h index 22713e20..8d506287 100644 --- a/include/Engine/Rendering/D3D/D3DRenderer.h +++ b/include/Engine/Rendering/D3D/D3DRenderer.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include From 726855839914b3e99b2d0b7d6075bc7d005e1b3b Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:29:18 -0400 Subject: [PATCH 05/13] trailing space --- include/Engine/Audio/AudioManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Engine/Audio/AudioManager.h b/include/Engine/Audio/AudioManager.h index 6b83e69c..aa34badf 100644 --- a/include/Engine/Audio/AudioManager.h +++ b/include/Engine/Audio/AudioManager.h @@ -41,7 +41,7 @@ class AudioManager { REQUEST_EOF = 0, REQUEST_ERROR = -1, REQUEST_CONVERTING = -2, - }; + }; static void CalculateCoeffs(); static Sint16 ProcessSample(Sint16 inSample, int channel); From fe58b88b21ec0ed8a62e705f6cd558906dc38fdd Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:42:00 -0400 Subject: [PATCH 06/13] ignore builds/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d70d313e..003e5726 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ mono_crash.* [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ +builds/ [Bb]in/ [Oo]bj/ [Ll]og/ From 17fc614433c4495cd07e6d344970d452a362c63e Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:42:43 -0400 Subject: [PATCH 07/13] LINGUIST --- .gitattributes | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..3502ba45 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,30 @@ + +*.txt text eol=lf +Makefile text eol=lf +README text eol=lf +COPYING text eol=lf +CONTRIBUTING text eol=lf +COMPILING text eol=lf +*.s text eol=lf +*.c text eol=lf +*.h text eol=lf +*.pl text eol=lf +*.py text eol=lf +*.sh text eol=lf + +*.s linguist-language=Assembly +*.c linguist-language=C +*.h linguist-language=C +include/**/*.h linguist-language=C++ +meta/**/*.h linguist-language=C++ +source/**/*.h linguist-language=C++ +tools/**/*.h linguist-language=C++ + +*.pl linguist-vendored +*.py linguist-vendored +*.sh linguist-vendored +Makefile linguist-vendored +doc/** linguist-vendored +etc/** linguist-vendored +data/** linguist-vendored +util/** linguist-vendored From 76bc9343ed862f0d6c0be43cb4327e550b85ae81 Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:42:58 -0400 Subject: [PATCH 08/13] please IntelliSense --- .vscode/c_cpp_properties.json | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..d80ebc6d --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,56 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/source", + "/opt/homebrew/opt/llvm/include", + "/opt/homebrew/include", + "/usr/local/include" + ], + "defines": [ + "MACOSX", + "TARGET_NAME=\"HatchGameEngine\"", + "USING_OPENGL", + "USING_LIBPNG", + "USING_LIBPNG_HEADER=", + "DEBUG", + "USING_VM_DISPATCH_TABLE", + "_THREAD_SAFE", + "__VSCODE_INTELLISENSE__" + ], + "cStandard": "c89", + "cppStandard": "c++11", + "macFrameworkPath": [ + "/System/Library/Frameworks", + "/Library/Frameworks" + ], + "compilerPath": "/opt/homebrew/opt/llvm/bin/clang", + "intelliSenseMode": "clang-arm64" + }, { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/source", + "/usr/local/include", + "/usr/include" + ], + "defines": [ + "LINUX", + "TARGET_NAME=HatchGameEngine", + "USING_LIBPNG", + "USING_LIBPNG_HEADER=", + "DEBUG", + "USING_VM_DISPATCH_TABLE", + "_THREAD_SAFE", + "__VSCODE_INTELLISENSE__" + ], + "cStandard": "c89", + "cppStandard": "c++11", + "compilerPath": "/usr/bin/gcc", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} From b99b81d4cd577f09f033ec4a1e25b9208f0bde2c Mon Sep 17 00:00:00 2001 From: Alexander Nicholi Date: Tue, 1 Oct 2024 01:43:05 -0400 Subject: [PATCH 09/13] fixups for macOS building --- Makefile | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index cd41dc1b..9a5bcebd 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,10 @@ USING_CURL = 0 USING_LIBPNG = 1 USING_ASSIMP = 1 +ifeq ($(PLATFORM),$(PLATFORM_MACOS)) +USING_ASSIMP = 0 +endif + TARGET = HatchGameEngine TARGETDIR = builds/$(OUT_FOLDER)/$(TARGET) OBJS = main.o @@ -57,10 +61,10 @@ ifeq ($(PLATFORM),$(PLATFORM_MACOS)) OBJ_DIRS += $(addprefix out/$(OUT_FOLDER)/, $(dir $(SRC_M:source/%.m=%.o))) endif -OBJS := $(addprefix out/$(OUT_FOLDER)/, $(SRC_C:source/%.c=%.o)) \ +OBJS := $(addprefix out/$(OUT_FOLDER)/, $(SRC_C:source/%.c=%.o)) \ $(addprefix out/$(OUT_FOLDER)/, $(SRC_CPP:source/%.cpp=%.o)) ifeq ($(PLATFORM),$(PLATFORM_MACOS)) -OBJ_DIRS += $(addprefix out/$(OUT_FOLDER)/, $(SRC_M:source/%.m=%.o)) +OBJS += $(addprefix out/$(OUT_FOLDER)/, $(SRC_M:source/%.m=%.o)) endif INCLUDES = -Wall -Wno-deprecated -Wno-unused-variable \ @@ -84,13 +88,10 @@ ifneq ($(MSYS_VERSION),0) DEFINES += -DMSYS endif endif -ifeq ($(PLATOFRM),$(PLATFORM_MACOS)) -INCLUDES += -F/Library/Frameworks/ \ - -F/System/Library/Frameworks/ \ - -Fmeta/mac/ \ - -I/Library/Frameworks/SDL2.framework/Headers/ \ - -I/System/Library/Frameworks/OpenGL.framework/Headers/ -DEFINES += -DMACOSX -DUSING_FRAMEWORK +ifeq ($(PLATFORM),$(PLATFORM_MACOS)) +INCLUDES += -I/opt/homebrew/include +LIBS += -lobjc +DEFINES += -DMACOSX -DUSING_OPENGL endif ifeq ($(PLATFORM),$(PLATFORM_LINUX)) DEFINES += -DLINUX @@ -126,13 +127,12 @@ LIBS += -logg -lvorbis -lvorbisfile LIBS += -lz ifeq ($(PLATFORM),$(PLATFORM_MACOS)) -LINKER = -framework SDL2 \ - -framework OpenGL \ - -framework CoreFoundation \ - -framework CoreServices \ - -framework Foundation - # \ - -framework Cocoa +LINKER = -framework IOKit \ + -framework OpenGL \ + -framework CoreFoundation \ + -framework CoreServices \ + -framework Foundation \ + -framework Cocoa endif all: @@ -143,7 +143,7 @@ clean: rm -rf $(OBJS) build: $(OBJS) - $(CXX) $^ $(INCLUDES) $(LIBS) $(LINKER) -o "$(TARGETDIR)" -std=c++11 + $(CXX) $^ $(INCLUDES) $(LIBS) $(LINKER) -o "$(TARGETDIR)" -std=c++17 $(OBJ_DIRS): mkdir -p $@ @@ -218,7 +218,7 @@ package: @install_name_tool -change /usr/local/Cellar/libvorbis/1.3.6/lib/libvorbis.0.dylib @executable_path/../Frameworks/_libvorbis.0.dylib "$(TARGETDIR).app/Contents/Frameworks/_libvorbisfile.3.dylib" out/$(OUT_FOLDER)/%.o: source/%.cpp - $(CXX) -c -g $(INCLUDES) $(DEFINES) -o "$@" "$<" -std=c++11 + $(CXX) -c -g $(INCLUDES) $(DEFINES) -o "$@" "$<" -std=c++17 out/$(OUT_FOLDER)/%.o: source/%.c $(CC) -c -g $(INCLUDES) $(DEFINES) -o "$@" "$<" -std=c11 From 104fc07b51544be82247accc8ec8aeb967078287 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 6 Oct 2024 15:18:06 -0300 Subject: [PATCH 10/13] Don't lock or unlock script mutex if there is only one thread --- source/Engine/Bytecode/ScriptManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/Engine/Bytecode/ScriptManager.cpp b/source/Engine/Bytecode/ScriptManager.cpp index 407ef1b8..1bb7ef96 100644 --- a/source/Engine/Bytecode/ScriptManager.cpp +++ b/source/Engine/Bytecode/ScriptManager.cpp @@ -612,10 +612,14 @@ PUBLIC STATIC void ScriptManager::FreeValue(VMValue value) { // #region GlobalFuncs PUBLIC STATIC bool ScriptManager::Lock() { - return (SDL_LockMutex(GlobalLock) == 0); + if (ScriptManager::ThreadCount == 1) + return true; + + return SDL_LockMutex(GlobalLock) == 0; } PUBLIC STATIC void ScriptManager::Unlock() { - SDL_UnlockMutex(GlobalLock); + if (ScriptManager::ThreadCount > 1) + SDL_UnlockMutex(GlobalLock); } PUBLIC STATIC void ScriptManager::DefineMethod(VMThread* thread, ObjFunction* function, Uint32 hash) { From 2e5eb10279fcbb7c92a92bd02b8822c041db8036 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 6 Oct 2024 16:09:31 -0300 Subject: [PATCH 11/13] Remove all remaining traces of automatic header generation --- include/Engine/Application.h | 8 - include/Engine/Audio/AudioManager.h | 8 - include/Engine/Audio/AudioPlayback.h | 8 - include/Engine/Bytecode/Bytecode.h | 8 - include/Engine/Bytecode/Compiler.h | 8 - include/Engine/Bytecode/GarbageCollector.h | 8 - include/Engine/Bytecode/ScriptEntity.h | 8 - include/Engine/Bytecode/ScriptManager.h | 8 - include/Engine/Bytecode/SourceFileMap.h | 8 - include/Engine/Bytecode/StandardLibrary.h | 8 - include/Engine/Bytecode/TypeImpl/ArrayImpl.h | 8 - .../Engine/Bytecode/TypeImpl/FunctionImpl.h | 8 - include/Engine/Bytecode/TypeImpl/MapImpl.h | 8 - include/Engine/Bytecode/TypeImpl/StringImpl.h | 8 - include/Engine/Bytecode/VMThread.h | 8 - include/Engine/Bytecode/Values.h | 8 - include/Engine/Diagnostics/Clock.h | 8 - include/Engine/Diagnostics/Log.h | 8 - include/Engine/Diagnostics/Memory.h | 8 - .../Engine/Diagnostics/PerformanceMeasure.h | 8 - include/Engine/Diagnostics/RemoteDebug.h | 8 - include/Engine/Extensions/Discord.h | 8 - include/Engine/Filesystem/Directory.h | 8 - include/Engine/Filesystem/File.h | 8 - include/Engine/FontFace.h | 8 - include/Engine/Graphics.h | 8 - include/Engine/Hashing/CRC32.h | 8 - include/Engine/Hashing/CombinedHash.h | 8 - include/Engine/Hashing/FNV1A.h | 8 - include/Engine/Hashing/MD5.h | 8 - include/Engine/Hashing/Murmur.h | 8 - include/Engine/IO/Compression/Huffman.h | 8 - include/Engine/IO/Compression/LZ11.h | 8 - include/Engine/IO/Compression/LZSS.h | 8 - include/Engine/IO/Compression/RunLength.h | 8 - include/Engine/IO/Compression/ZLibStream.h | 8 - include/Engine/IO/FileStream.h | 8 - include/Engine/IO/MemoryStream.h | 8 - include/Engine/IO/NetworkStream.h | 8 - include/Engine/IO/ResourceStream.h | 8 - include/Engine/IO/SDLStream.h | 8 - include/Engine/IO/Serializer.h | 8 - include/Engine/IO/Stream.h | 8 - include/Engine/Input/Controller.h | 8 - include/Engine/Input/InputAction.h | 8 - include/Engine/Input/InputPlayer.h | 8 - include/Engine/InputManager.h | 8 - include/Engine/Math/Clipper.h | 8 - include/Engine/Math/Ease.h | 8 - include/Engine/Math/Geometry.h | 8 - include/Engine/Math/Math.h | 8 - include/Engine/Math/Matrix4x4.h | 8 - include/Engine/Math/Random.h | 8 - include/Engine/Math/Vector.h | 8 - include/Engine/Media/Decoder.h | 8 - include/Engine/Media/Decoders/AudioDecoder.h | 8 - include/Engine/Media/Decoders/VideoDecoder.h | 8 - include/Engine/Media/MediaPlayer.h | 8 - include/Engine/Media/MediaSource.h | 8 - include/Engine/Media/Utils/MediaPlayerState.h | 8 - include/Engine/Media/Utils/PtrBuffer.h | 8 - include/Engine/Media/Utils/RingBuffer.h | 8 - include/Engine/Network/HTTP.h | 8 - include/Engine/Network/WebSocketClient.h | 8 - include/Engine/Rendering/D3D/D3DRenderer.h | 8 - include/Engine/Rendering/FaceInfo.h | 8 - include/Engine/Rendering/GL/GLRenderer.h | 8 - include/Engine/Rendering/GL/GLShader.h | 8 - include/Engine/Rendering/GL/GLShaderBuilder.h | 8 - .../Engine/Rendering/GL/GLShaderContainer.h | 8 - include/Engine/Rendering/GameTexture.h | 8 - include/Engine/Rendering/Material.h | 8 - include/Engine/Rendering/ModelRenderer.h | 8 - include/Engine/Rendering/PolygonRenderer.h | 8 - include/Engine/Rendering/SDL2/SDL2Renderer.h | 8 - include/Engine/Rendering/Shader.h | 8 - .../Rendering/Software/PolygonRasterizer.h | 8 - include/Engine/Rendering/Software/Scanline.h | 8 - .../Rendering/Software/SoftwareRenderer.h | 8 - include/Engine/Rendering/Texture.h | 8 - include/Engine/Rendering/TextureReference.h | 8 - include/Engine/Rendering/VertexBuffer.h | 8 - include/Engine/Rendering/ViewTexture.h | 8 - include/Engine/ResourceTypes/IModel.h | 8 - include/Engine/ResourceTypes/ISound.h | 8 - include/Engine/ResourceTypes/ISprite.h | 8 - include/Engine/ResourceTypes/Image.h | 8 - .../Engine/ResourceTypes/ImageFormats/GIF.h | 8 - .../ResourceTypes/ImageFormats/ImageFormat.h | 8 - .../Engine/ResourceTypes/ImageFormats/JPEG.h | 8 - .../Engine/ResourceTypes/ImageFormats/PNG.h | 8 - .../ResourceTypes/ModelFormats/HatchModel.h | 8 - .../ResourceTypes/ModelFormats/Importer.h | 8 - .../ResourceTypes/ModelFormats/MD3Model.h | 8 - .../ResourceTypes/ModelFormats/RSDKModel.h | 8 - .../Engine/ResourceTypes/ResourceManager.h | 8 - .../SceneFormats/HatchSceneReader.h | 8 - .../SceneFormats/RSDKSceneReader.h | 8 - .../SceneFormats/TiledMapReader.h | 8 - .../Engine/ResourceTypes/SoundFormats/OGG.h | 8 - .../ResourceTypes/SoundFormats/SoundFormat.h | 8 - .../Engine/ResourceTypes/SoundFormats/WAV.h | 8 - include/Engine/Scene.h | 8 - include/Engine/Scene/SceneInfo.h | 8 - include/Engine/Scene/SceneLayer.h | 8 - include/Engine/Scene/ScrollingIndex.h | 8 - include/Engine/Scene/ScrollingInfo.h | 8 - include/Engine/Scene/TileConfig.h | 8 - include/Engine/Scene/TileSpriteInfo.h | 8 - include/Engine/Scene/View.h | 8 - include/Engine/TextFormats/INI/INI.h | 8 - include/Engine/TextFormats/XML/XMLParser.h | 8 - include/Engine/Types/DrawGroupList.h | 8 - include/Engine/Types/Entity.h | 8 - include/Engine/Types/ObjectList.h | 8 - include/Engine/Types/ObjectRegistry.h | 8 - include/Engine/Types/Tileset.h | 8 - include/Engine/Utilities/ColorUtils.h | 8 - include/Engine/Utilities/StringUtils.h | 8 - source/Engine/Application.cpp | 137 +- source/Engine/Audio/AudioManager.cpp | 125 +- source/Engine/Audio/AudioPlayback.cpp | 36 +- source/Engine/Bytecode/Bytecode.cpp | 26 +- source/Engine/Bytecode/Compiler.cpp | 389 +++-- source/Engine/Bytecode/GarbageCollector.cpp | 35 +- source/Engine/Bytecode/ScriptEntity.cpp | 125 +- source/Engine/Bytecode/ScriptManager.cpp | 147 +- source/Engine/Bytecode/SourceFileMap.cpp | 21 +- source/Engine/Bytecode/StandardLibrary.cpp | 39 +- source/Engine/Bytecode/TypeImpl/ArrayImpl.cpp | 16 +- .../Engine/Bytecode/TypeImpl/FunctionImpl.cpp | 14 +- source/Engine/Bytecode/TypeImpl/MapImpl.cpp | 18 +- .../Engine/Bytecode/TypeImpl/StringImpl.cpp | 16 +- source/Engine/Bytecode/VMThread.cpp | 178 +-- source/Engine/Bytecode/Values.cpp | 20 +- source/Engine/Diagnostics/Clock.cpp | 18 +- source/Engine/Diagnostics/Log.cpp | 23 +- source/Engine/Diagnostics/Memory.cpp | 49 +- .../Engine/Diagnostics/PerformanceMeasure.cpp | 13 +- source/Engine/Diagnostics/RemoteDebug.cpp | 12 +- source/Engine/Extensions/Discord.cpp | 81 +- source/Engine/Filesystem/Directory.cpp | 23 +- source/Engine/Filesystem/File.cpp | 15 +- source/Engine/FontFace.cpp | 16 +- source/Engine/Graphics.cpp | 314 ++-- source/Engine/Hashing/CRC32.cpp | 18 +- source/Engine/Hashing/CombinedHash.cpp | 16 +- source/Engine/Hashing/FNV1A.cpp | 18 +- source/Engine/Hashing/MD5.cpp | 18 +- source/Engine/Hashing/Murmur.cpp | 18 +- source/Engine/IO/Compression/Huffman.cpp | 36 +- source/Engine/IO/Compression/LZ11.cpp | 56 +- source/Engine/IO/Compression/LZSS.cpp | 66 +- source/Engine/IO/Compression/RunLength.cpp | 10 +- source/Engine/IO/Compression/ZLibStream.cpp | 35 +- source/Engine/IO/FileStream.cpp | 35 +- source/Engine/IO/MemoryStream.cpp | 38 +- source/Engine/IO/NetworkStream.cpp | 32 +- source/Engine/IO/ResourceStream.cpp | 29 +- source/Engine/IO/SDLStream.cpp | 33 +- source/Engine/IO/Serializer.cpp | 96 +- source/Engine/IO/Stream.cpp | 102 +- source/Engine/Input/Controller.cpp | 61 +- source/Engine/Input/InputAction.cpp | 15 +- source/Engine/Input/InputPlayer.cpp | 129 +- source/Engine/InputManager.cpp | 201 +-- source/Engine/Math/Clipper.cpp | 17 +- source/Engine/Math/Ease.cpp | 70 +- source/Engine/Math/Geometry.cpp | 17 +- source/Engine/Math/Math.cpp | 85 +- source/Engine/Math/Matrix4x4.cpp | 47 +- source/Engine/Math/Random.cpp | 16 +- source/Engine/Math/Vector.cpp | 34 +- source/Engine/Media/Decoder.cpp | 84 +- source/Engine/Media/Decoders/AudioDecoder.cpp | 47 +- source/Engine/Media/Decoders/VideoDecoder.cpp | 38 +- source/Engine/Media/MediaPlayer.cpp | 88 +- source/Engine/Media/MediaSource.cpp | 34 +- .../Engine/Media/Utils/MediaPlayerState.cpp | 20 +- source/Engine/Media/Utils/PtrBuffer.cpp | 36 +- source/Engine/Media/Utils/RingBuffer.cpp | 33 +- source/Engine/Network/HTTP.cpp | 13 +- source/Engine/Network/WebSocketClient.cpp | 52 +- source/Engine/Rendering/D3D/D3DRenderer.cpp | 120 +- source/Engine/Rendering/FaceInfo.cpp | 25 +- source/Engine/Rendering/GL/GLRenderer.cpp | 152 +- source/Engine/Rendering/GL/GLShader.cpp | 59 +- .../Engine/Rendering/GL/GLShaderBuilder.cpp | 26 +- .../Engine/Rendering/GL/GLShaderContainer.cpp | 30 +- source/Engine/Rendering/GameTexture.cpp | 22 +- source/Engine/Rendering/Material.cpp | 35 +- .../Rendering/Metal/MetalRenderer.cpp.unused | 1418 ----------------- .../Rendering/Metal/MetalRenderer.mm.unused | 443 ----- source/Engine/Rendering/ModelRenderer.cpp | 59 +- source/Engine/Rendering/PolygonRenderer.cpp | 53 +- source/Engine/Rendering/SDL2/SDL2Renderer.cpp | 106 +- source/Engine/Rendering/Shader.cpp | 10 +- .../Rendering/Software/PolygonRasterizer.cpp | 63 +- source/Engine/Rendering/Software/Scanline.cpp | 30 +- .../Rendering/Software/SoftwareRenderer.cpp | 256 ++- source/Engine/Rendering/Texture.cpp | 39 +- source/Engine/Rendering/TextureReference.cpp | 19 +- source/Engine/Rendering/VertexBuffer.cpp | 29 +- source/Engine/Rendering/ViewTexture.cpp | 16 +- source/Engine/ResourceTypes/IModel.cpp | 78 +- source/Engine/ResourceTypes/ISound.cpp | 31 +- source/Engine/ResourceTypes/ISprite.cpp | 55 +- source/Engine/ResourceTypes/Image.cpp | 19 +- .../Engine/ResourceTypes/ImageFormats/GIF.cpp | 31 +- .../ImageFormats/ImageFormat.cpp | 20 +- .../ResourceTypes/ImageFormats/JPEG.cpp | 19 +- .../Engine/ResourceTypes/ImageFormats/PNG.cpp | 23 +- .../ResourceTypes/ModelFormats/HatchModel.cpp | 57 +- .../ResourceTypes/ModelFormats/Importer.cpp | 25 +- .../ResourceTypes/ModelFormats/MD3Model.cpp | 28 +- .../ResourceTypes/ModelFormats/RSDKModel.cpp | 13 +- .../Engine/ResourceTypes/ResourceManager.cpp | 25 +- .../SceneFormats/HatchSceneReader.cpp | 41 +- .../SceneFormats/RSDKSceneReader.cpp | 28 +- .../SceneFormats/TiledMapReader.cpp | 24 +- .../Engine/ResourceTypes/SoundFormats/OGG.cpp | 35 +- .../SoundFormats/SoundFormat.cpp | 46 +- .../Engine/ResourceTypes/SoundFormats/WAV.cpp | 19 +- source/Engine/Scene.cpp | 313 ++-- source/Engine/Scene/SceneInfo.cpp | 53 +- source/Engine/Scene/SceneLayer.cpp | 84 +- source/Engine/Scene/ScrollingIndex.cpp | 8 - source/Engine/Scene/ScrollingInfo.cpp | 10 - source/Engine/Scene/TileConfig.cpp | 15 - source/Engine/Scene/TileSpriteInfo.cpp | 9 - source/Engine/Scene/View.cpp | 48 +- source/Engine/TextFormats/INI/INI.cpp | 68 +- source/Engine/TextFormats/XML/XMLParser.cpp | 34 +- source/Engine/Types/DrawGroupList.cpp | 36 +- source/Engine/Types/Entity.cpp | 170 +- source/Engine/Types/ObjectList.cpp | 49 +- source/Engine/Types/ObjectRegistry.cpp | 34 +- source/Engine/Types/Tileset.cpp | 33 +- source/Engine/Utilities/ColorUtils.cpp | 46 +- source/Engine/Utilities/StringUtils.cpp | 47 +- 240 files changed, 2036 insertions(+), 7299 deletions(-) delete mode 100644 source/Engine/Rendering/Metal/MetalRenderer.cpp.unused delete mode 100644 source/Engine/Rendering/Metal/MetalRenderer.mm.unused delete mode 100644 source/Engine/Scene/ScrollingIndex.cpp delete mode 100644 source/Engine/Scene/ScrollingInfo.cpp delete mode 100644 source/Engine/Scene/TileConfig.cpp delete mode 100644 source/Engine/Scene/TileSpriteInfo.cpp diff --git a/include/Engine/Application.h b/include/Engine/Application.h index 63f070e1..80ff1496 100644 --- a/include/Engine/Application.h +++ b/include/Engine/Application.h @@ -1,14 +1,6 @@ #ifndef ENGINE_APPLICATION_H #define ENGINE_APPLICATION_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Audio/AudioManager.h b/include/Engine/Audio/AudioManager.h index aa34badf..3579fb6a 100644 --- a/include/Engine/Audio/AudioManager.h +++ b/include/Engine/Audio/AudioManager.h @@ -1,14 +1,6 @@ #ifndef ENGINE_AUDIO_AUDIOMANAGER_H #define ENGINE_AUDIO_AUDIOMANAGER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Audio/AudioPlayback.h b/include/Engine/Audio/AudioPlayback.h index 5228e85f..91c8038c 100644 --- a/include/Engine/Audio/AudioPlayback.h +++ b/include/Engine/Audio/AudioPlayback.h @@ -1,14 +1,6 @@ #ifndef ENGINE_AUDIO_AUDIOPLAYBACK_H #define ENGINE_AUDIO_AUDIOPLAYBACK_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Bytecode/Bytecode.h b/include/Engine/Bytecode/Bytecode.h index 5f029555..b1a7004d 100644 --- a/include/Engine/Bytecode/Bytecode.h +++ b/include/Engine/Bytecode/Bytecode.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_BYTECODE_H #define ENGINE_BYTECODE_BYTECODE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/Compiler.h b/include/Engine/Bytecode/Compiler.h index f1fbf748..a8722156 100644 --- a/include/Engine/Bytecode/Compiler.h +++ b/include/Engine/Bytecode/Compiler.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_COMPILER_H #define ENGINE_BYTECODE_COMPILER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/GarbageCollector.h b/include/Engine/Bytecode/GarbageCollector.h index 3729e8c2..d28d2b6e 100644 --- a/include/Engine/Bytecode/GarbageCollector.h +++ b/include/Engine/Bytecode/GarbageCollector.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_GARBAGECOLLECTOR_H #define ENGINE_BYTECODE_GARBAGECOLLECTOR_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/ScriptEntity.h b/include/Engine/Bytecode/ScriptEntity.h index 9c24a69c..ec4d02dc 100644 --- a/include/Engine/Bytecode/ScriptEntity.h +++ b/include/Engine/Bytecode/ScriptEntity.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_SCRIPTENTITY_H #define ENGINE_BYTECODE_SCRIPTENTITY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/ScriptManager.h b/include/Engine/Bytecode/ScriptManager.h index 1edd8217..10a622ab 100644 --- a/include/Engine/Bytecode/ScriptManager.h +++ b/include/Engine/Bytecode/ScriptManager.h @@ -1,13 +1,5 @@ #ifndef ENGINE_BYTECODE_SCRIPTMANAGER_H #define ENGINE_BYTECODE_SCRIPTMANAGER_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class ScriptEntity; #include diff --git a/include/Engine/Bytecode/SourceFileMap.h b/include/Engine/Bytecode/SourceFileMap.h index 8f74d83d..b14bc343 100644 --- a/include/Engine/Bytecode/SourceFileMap.h +++ b/include/Engine/Bytecode/SourceFileMap.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_SOURCEFILEMAP_H #define ENGINE_BYTECODE_SOURCEFILEMAP_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/StandardLibrary.h b/include/Engine/Bytecode/StandardLibrary.h index d5867f09..03c69093 100644 --- a/include/Engine/Bytecode/StandardLibrary.h +++ b/include/Engine/Bytecode/StandardLibrary.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_STANDARDLIBRARY_H #define ENGINE_BYTECODE_STANDARDLIBRARY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Bytecode/TypeImpl/ArrayImpl.h b/include/Engine/Bytecode/TypeImpl/ArrayImpl.h index f01680f3..f557be34 100644 --- a/include/Engine/Bytecode/TypeImpl/ArrayImpl.h +++ b/include/Engine/Bytecode/TypeImpl/ArrayImpl.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_TYPEIMPL_ARRAYIMPL_H #define ENGINE_BYTECODE_TYPEIMPL_ARRAYIMPL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/TypeImpl/FunctionImpl.h b/include/Engine/Bytecode/TypeImpl/FunctionImpl.h index 9eaf49d4..4c1fedb2 100644 --- a/include/Engine/Bytecode/TypeImpl/FunctionImpl.h +++ b/include/Engine/Bytecode/TypeImpl/FunctionImpl.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_TYPEIMPL_FUNCTIONIMPL_H #define ENGINE_BYTECODE_TYPEIMPL_FUNCTIONIMPL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/TypeImpl/MapImpl.h b/include/Engine/Bytecode/TypeImpl/MapImpl.h index 1f5e2388..d86228a6 100644 --- a/include/Engine/Bytecode/TypeImpl/MapImpl.h +++ b/include/Engine/Bytecode/TypeImpl/MapImpl.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_TYPEIMPL_MAPIMPL_H #define ENGINE_BYTECODE_TYPEIMPL_MAPIMPL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/TypeImpl/StringImpl.h b/include/Engine/Bytecode/TypeImpl/StringImpl.h index 4e3ec0fd..34a9ad81 100644 --- a/include/Engine/Bytecode/TypeImpl/StringImpl.h +++ b/include/Engine/Bytecode/TypeImpl/StringImpl.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_TYPEIMPL_STRINGIMPL_H #define ENGINE_BYTECODE_TYPEIMPL_STRINGIMPL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Bytecode/VMThread.h b/include/Engine/Bytecode/VMThread.h index 123a792a..1834a735 100644 --- a/include/Engine/Bytecode/VMThread.h +++ b/include/Engine/Bytecode/VMThread.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_VMTHREAD_H #define ENGINE_BYTECODE_VMTHREAD_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Bytecode/Values.h b/include/Engine/Bytecode/Values.h index fb310d3a..af283f71 100644 --- a/include/Engine/Bytecode/Values.h +++ b/include/Engine/Bytecode/Values.h @@ -1,14 +1,6 @@ #ifndef ENGINE_BYTECODE_VALUES_H #define ENGINE_BYTECODE_VALUES_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Diagnostics/Clock.h b/include/Engine/Diagnostics/Clock.h index 1f56bdd7..25e2406b 100644 --- a/include/Engine/Diagnostics/Clock.h +++ b/include/Engine/Diagnostics/Clock.h @@ -1,14 +1,6 @@ #ifndef ENGINE_DIAGNOSTICS_CLOCK_H #define ENGINE_DIAGNOSTICS_CLOCK_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Clock { diff --git a/include/Engine/Diagnostics/Log.h b/include/Engine/Diagnostics/Log.h index 6c61596e..df094ddd 100644 --- a/include/Engine/Diagnostics/Log.h +++ b/include/Engine/Diagnostics/Log.h @@ -1,14 +1,6 @@ #ifndef ENGINE_DIAGNOSTICS_LOG_H #define ENGINE_DIAGNOSTICS_LOG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class Log { public: diff --git a/include/Engine/Diagnostics/Memory.h b/include/Engine/Diagnostics/Memory.h index 17b7596d..2bb312a0 100644 --- a/include/Engine/Diagnostics/Memory.h +++ b/include/Engine/Diagnostics/Memory.h @@ -1,14 +1,6 @@ #ifndef ENGINE_DIAGNOSTICS_MEMORY_H #define ENGINE_DIAGNOSTICS_MEMORY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Memory { diff --git a/include/Engine/Diagnostics/PerformanceMeasure.h b/include/Engine/Diagnostics/PerformanceMeasure.h index f1066a63..0eb926a1 100644 --- a/include/Engine/Diagnostics/PerformanceMeasure.h +++ b/include/Engine/Diagnostics/PerformanceMeasure.h @@ -1,14 +1,6 @@ #ifndef ENGINE_DIAGNOSTICS_PERFORMANCEMEASURE_H #define ENGINE_DIAGNOSTICS_PERFORMANCEMEASURE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Diagnostics/RemoteDebug.h b/include/Engine/Diagnostics/RemoteDebug.h index b0431b91..ab312599 100644 --- a/include/Engine/Diagnostics/RemoteDebug.h +++ b/include/Engine/Diagnostics/RemoteDebug.h @@ -1,14 +1,6 @@ #ifndef ENGINE_DIAGNOSTICS_REMOTEDEBUG_H #define ENGINE_DIAGNOSTICS_REMOTEDEBUG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class RemoteDebug { public: diff --git a/include/Engine/Extensions/Discord.h b/include/Engine/Extensions/Discord.h index 9acd9bfa..20e26929 100644 --- a/include/Engine/Extensions/Discord.h +++ b/include/Engine/Extensions/Discord.h @@ -1,14 +1,6 @@ #ifndef ENGINE_EXTENSIONS_DISCORD_H #define ENGINE_EXTENSIONS_DISCORD_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Discord { diff --git a/include/Engine/Filesystem/Directory.h b/include/Engine/Filesystem/Directory.h index 7a3de0d3..15080199 100644 --- a/include/Engine/Filesystem/Directory.h +++ b/include/Engine/Filesystem/Directory.h @@ -1,14 +1,6 @@ #ifndef ENGINE_FILESYSTEM_DIRECTORY_H #define ENGINE_FILESYSTEM_DIRECTORY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Directory { diff --git a/include/Engine/Filesystem/File.h b/include/Engine/Filesystem/File.h index e8f893c9..2a6fe55b 100644 --- a/include/Engine/Filesystem/File.h +++ b/include/Engine/Filesystem/File.h @@ -1,14 +1,6 @@ #ifndef ENGINE_FILESYSTEM_FILE_H #define ENGINE_FILESYSTEM_FILE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class File { diff --git a/include/Engine/FontFace.h b/include/Engine/FontFace.h index 729877a0..621ff6ca 100644 --- a/include/Engine/FontFace.h +++ b/include/Engine/FontFace.h @@ -1,14 +1,6 @@ #ifndef ENGINE_FONTFACE_H #define ENGINE_FONTFACE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Graphics.h b/include/Engine/Graphics.h index 7ebe130f..4e25359b 100644 --- a/include/Engine/Graphics.h +++ b/include/Engine/Graphics.h @@ -1,13 +1,5 @@ #ifndef ENGINE_GRAPHICS_H #define ENGINE_GRAPHICS_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class ISprite; class IModel; diff --git a/include/Engine/Hashing/CRC32.h b/include/Engine/Hashing/CRC32.h index 0e6a8998..e852c68f 100644 --- a/include/Engine/Hashing/CRC32.h +++ b/include/Engine/Hashing/CRC32.h @@ -1,14 +1,6 @@ #ifndef ENGINE_HASHING_CRC32_H #define ENGINE_HASHING_CRC32_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class CRC32 { diff --git a/include/Engine/Hashing/CombinedHash.h b/include/Engine/Hashing/CombinedHash.h index 582f4ba7..70e73d02 100644 --- a/include/Engine/Hashing/CombinedHash.h +++ b/include/Engine/Hashing/CombinedHash.h @@ -1,14 +1,6 @@ #ifndef ENGINE_HASHING_COMBINEDHASH_H #define ENGINE_HASHING_COMBINEDHASH_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class CombinedHash { diff --git a/include/Engine/Hashing/FNV1A.h b/include/Engine/Hashing/FNV1A.h index aca23a94..3ebb594c 100644 --- a/include/Engine/Hashing/FNV1A.h +++ b/include/Engine/Hashing/FNV1A.h @@ -1,14 +1,6 @@ #ifndef ENGINE_HASHING_FNV1A_H #define ENGINE_HASHING_FNV1A_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class FNV1A { diff --git a/include/Engine/Hashing/MD5.h b/include/Engine/Hashing/MD5.h index 5bd935d5..61b23314 100644 --- a/include/Engine/Hashing/MD5.h +++ b/include/Engine/Hashing/MD5.h @@ -1,14 +1,6 @@ #ifndef ENGINE_HASHING_MD5_H #define ENGINE_HASHING_MD5_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class MD5 { diff --git a/include/Engine/Hashing/Murmur.h b/include/Engine/Hashing/Murmur.h index bcfad1f7..5cd300eb 100644 --- a/include/Engine/Hashing/Murmur.h +++ b/include/Engine/Hashing/Murmur.h @@ -1,14 +1,6 @@ #ifndef ENGINE_HASHING_MURMUR_H #define ENGINE_HASHING_MURMUR_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Murmur { diff --git a/include/Engine/IO/Compression/Huffman.h b/include/Engine/IO/Compression/Huffman.h index 58c3dc15..6a99fee6 100644 --- a/include/Engine/IO/Compression/Huffman.h +++ b/include/Engine/IO/Compression/Huffman.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_COMPRESSION_HUFFMAN_H #define ENGINE_IO_COMPRESSION_HUFFMAN_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Huffman { diff --git a/include/Engine/IO/Compression/LZ11.h b/include/Engine/IO/Compression/LZ11.h index d0dff980..710cc951 100644 --- a/include/Engine/IO/Compression/LZ11.h +++ b/include/Engine/IO/Compression/LZ11.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_COMPRESSION_LZ11_H #define ENGINE_IO_COMPRESSION_LZ11_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class LZ11 { diff --git a/include/Engine/IO/Compression/LZSS.h b/include/Engine/IO/Compression/LZSS.h index e9bb487f..9a291795 100644 --- a/include/Engine/IO/Compression/LZSS.h +++ b/include/Engine/IO/Compression/LZSS.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_COMPRESSION_LZSS_H #define ENGINE_IO_COMPRESSION_LZSS_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class LZSS { diff --git a/include/Engine/IO/Compression/RunLength.h b/include/Engine/IO/Compression/RunLength.h index b5c6d47d..cac6e61c 100644 --- a/include/Engine/IO/Compression/RunLength.h +++ b/include/Engine/IO/Compression/RunLength.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_COMPRESSION_RUNLENGTH_H #define ENGINE_IO_COMPRESSION_RUNLENGTH_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class RunLength { diff --git a/include/Engine/IO/Compression/ZLibStream.h b/include/Engine/IO/Compression/ZLibStream.h index 9571c74e..d43d9bd6 100644 --- a/include/Engine/IO/Compression/ZLibStream.h +++ b/include/Engine/IO/Compression/ZLibStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_COMPRESSION_ZLIBSTREAM_H #define ENGINE_IO_COMPRESSION_ZLIBSTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/FileStream.h b/include/Engine/IO/FileStream.h index 0d28e871..d85b5da1 100644 --- a/include/Engine/IO/FileStream.h +++ b/include/Engine/IO/FileStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_FILESTREAM_H #define ENGINE_IO_FILESTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/MemoryStream.h b/include/Engine/IO/MemoryStream.h index a8cc5503..763e0be7 100644 --- a/include/Engine/IO/MemoryStream.h +++ b/include/Engine/IO/MemoryStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_MEMORYSTREAM_H #define ENGINE_IO_MEMORYSTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/NetworkStream.h b/include/Engine/IO/NetworkStream.h index a3e55019..cbbfe218 100644 --- a/include/Engine/IO/NetworkStream.h +++ b/include/Engine/IO/NetworkStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_NETWORKSTREAM_H #define ENGINE_IO_NETWORKSTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/ResourceStream.h b/include/Engine/IO/ResourceStream.h index 307a3adc..a7bda2a7 100644 --- a/include/Engine/IO/ResourceStream.h +++ b/include/Engine/IO/ResourceStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_RESOURCESTREAM_H #define ENGINE_IO_RESOURCESTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/SDLStream.h b/include/Engine/IO/SDLStream.h index 6b2f1ae4..21be5238 100644 --- a/include/Engine/IO/SDLStream.h +++ b/include/Engine/IO/SDLStream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_SDLSTREAM_H #define ENGINE_IO_SDLSTREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/IO/Serializer.h b/include/Engine/IO/Serializer.h index c63769fc..ce008562 100644 --- a/include/Engine/IO/Serializer.h +++ b/include/Engine/IO/Serializer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_SERIALIZER_H #define ENGINE_IO_SERIALIZER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/IO/Stream.h b/include/Engine/IO/Stream.h index 41404568..b0a92b0a 100644 --- a/include/Engine/IO/Stream.h +++ b/include/Engine/IO/Stream.h @@ -1,14 +1,6 @@ #ifndef ENGINE_IO_STREAM_H #define ENGINE_IO_STREAM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Input/Controller.h b/include/Engine/Input/Controller.h index 7025a14f..0f16b1a6 100644 --- a/include/Engine/Input/Controller.h +++ b/include/Engine/Input/Controller.h @@ -1,14 +1,6 @@ #ifndef ENGINE_INPUT_CONTROLLER_H #define ENGINE_INPUT_CONTROLLER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Input/InputAction.h b/include/Engine/Input/InputAction.h index 1950d1a2..24195521 100644 --- a/include/Engine/Input/InputAction.h +++ b/include/Engine/Input/InputAction.h @@ -1,14 +1,6 @@ #ifndef ENGINE_INPUT_INPUTACTION_H #define ENGINE_INPUT_INPUTACTION_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Input/InputPlayer.h b/include/Engine/Input/InputPlayer.h index 5a8f8b4c..ef9bddd2 100644 --- a/include/Engine/Input/InputPlayer.h +++ b/include/Engine/Input/InputPlayer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_INPUT_INPUTPLAYER_H #define ENGINE_INPUT_INPUTPLAYER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/InputManager.h b/include/Engine/InputManager.h index 49659fa6..2de33b66 100644 --- a/include/Engine/InputManager.h +++ b/include/Engine/InputManager.h @@ -1,14 +1,6 @@ #ifndef ENGINE_INPUTMANAGER_H #define ENGINE_INPUTMANAGER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Math/Clipper.h b/include/Engine/Math/Clipper.h index 11f96eb1..b6e4e886 100644 --- a/include/Engine/Math/Clipper.h +++ b/include/Engine/Math/Clipper.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_CLIPPER_H #define ENGINE_MATH_CLIPPER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Math/Ease.h b/include/Engine/Math/Ease.h index 8f8a22d4..a926750b 100644 --- a/include/Engine/Math/Ease.h +++ b/include/Engine/Math/Ease.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_EASE_H #define ENGINE_MATH_EASE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Ease { diff --git a/include/Engine/Math/Geometry.h b/include/Engine/Math/Geometry.h index 9cd8de13..7ab3db53 100644 --- a/include/Engine/Math/Geometry.h +++ b/include/Engine/Math/Geometry.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_GEOMETRY_H #define ENGINE_MATH_GEOMETRY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Math/Math.h b/include/Engine/Math/Math.h index 403bbbab..7a950aae 100644 --- a/include/Engine/Math/Math.h +++ b/include/Engine/Math/Math.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_MATH_H #define ENGINE_MATH_MATH_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Math { diff --git a/include/Engine/Math/Matrix4x4.h b/include/Engine/Math/Matrix4x4.h index fac32ab6..68f73fe6 100644 --- a/include/Engine/Math/Matrix4x4.h +++ b/include/Engine/Math/Matrix4x4.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_MATRIX4X4_H #define ENGINE_MATH_MATRIX4X4_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class Matrix4x4 { public: diff --git a/include/Engine/Math/Random.h b/include/Engine/Math/Random.h index 7d50d5cf..8df55a05 100644 --- a/include/Engine/Math/Random.h +++ b/include/Engine/Math/Random.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_RANDOM_H #define ENGINE_MATH_RANDOM_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Random { diff --git a/include/Engine/Math/Vector.h b/include/Engine/Math/Vector.h index 5ef6d1a8..55a44b87 100644 --- a/include/Engine/Math/Vector.h +++ b/include/Engine/Math/Vector.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MATH_VECTOR_H #define ENGINE_MATH_VECTOR_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/Decoder.h b/include/Engine/Media/Decoder.h index f638fd9b..254d7ab7 100644 --- a/include/Engine/Media/Decoder.h +++ b/include/Engine/Media/Decoder.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_DECODER_H #define ENGINE_MEDIA_DECODER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/Decoders/AudioDecoder.h b/include/Engine/Media/Decoders/AudioDecoder.h index d7cbc4fb..d5c485f9 100644 --- a/include/Engine/Media/Decoders/AudioDecoder.h +++ b/include/Engine/Media/Decoders/AudioDecoder.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_DECODERS_AUDIODECODER_H #define ENGINE_MEDIA_DECODERS_AUDIODECODER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/Decoders/VideoDecoder.h b/include/Engine/Media/Decoders/VideoDecoder.h index 0cdb6296..d3db76a3 100644 --- a/include/Engine/Media/Decoders/VideoDecoder.h +++ b/include/Engine/Media/Decoders/VideoDecoder.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_DECODERS_VIDEODECODER_H #define ENGINE_MEDIA_DECODERS_VIDEODECODER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/MediaPlayer.h b/include/Engine/Media/MediaPlayer.h index aa486633..f5acce2e 100644 --- a/include/Engine/Media/MediaPlayer.h +++ b/include/Engine/Media/MediaPlayer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_MEDIAPLAYER_H #define ENGINE_MEDIA_MEDIAPLAYER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/MediaSource.h b/include/Engine/Media/MediaSource.h index ff70789a..5ec6ce9e 100644 --- a/include/Engine/Media/MediaSource.h +++ b/include/Engine/Media/MediaSource.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_MEDIASOURCE_H #define ENGINE_MEDIA_MEDIASOURCE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Media/Utils/MediaPlayerState.h b/include/Engine/Media/Utils/MediaPlayerState.h index 77ff6f3a..f7c059c0 100644 --- a/include/Engine/Media/Utils/MediaPlayerState.h +++ b/include/Engine/Media/Utils/MediaPlayerState.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_UTILS_MEDIAPLAYERSTATE_H #define ENGINE_MEDIA_UTILS_MEDIAPLAYERSTATE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class MediaPlayerState { diff --git a/include/Engine/Media/Utils/PtrBuffer.h b/include/Engine/Media/Utils/PtrBuffer.h index 5b1ecec2..fa96941f 100644 --- a/include/Engine/Media/Utils/PtrBuffer.h +++ b/include/Engine/Media/Utils/PtrBuffer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_UTILS_PTRBUFFER_H #define ENGINE_MEDIA_UTILS_PTRBUFFER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Media/Utils/RingBuffer.h b/include/Engine/Media/Utils/RingBuffer.h index a2356b1d..d0129aa8 100644 --- a/include/Engine/Media/Utils/RingBuffer.h +++ b/include/Engine/Media/Utils/RingBuffer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_MEDIA_UTILS_RINGBUFFER_H #define ENGINE_MEDIA_UTILS_RINGBUFFER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class RingBuffer { diff --git a/include/Engine/Network/HTTP.h b/include/Engine/Network/HTTP.h index 2c2dade1..b627912e 100644 --- a/include/Engine/Network/HTTP.h +++ b/include/Engine/Network/HTTP.h @@ -1,14 +1,6 @@ #ifndef ENGINE_NETWORK_HTTP_H #define ENGINE_NETWORK_HTTP_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Network/WebSocketClient.h b/include/Engine/Network/WebSocketClient.h index b96ccf02..658eb724 100644 --- a/include/Engine/Network/WebSocketClient.h +++ b/include/Engine/Network/WebSocketClient.h @@ -1,14 +1,6 @@ #ifndef ENGINE_NETWORK_WEBSOCKETCLIENT_H #define ENGINE_NETWORK_WEBSOCKETCLIENT_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/D3D/D3DRenderer.h b/include/Engine/Rendering/D3D/D3DRenderer.h index 8d506287..0ea9cf20 100644 --- a/include/Engine/Rendering/D3D/D3DRenderer.h +++ b/include/Engine/Rendering/D3D/D3DRenderer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_D3D_D3DRENDERER_H #define ENGINE_RENDERING_D3D_D3DRENDERER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/FaceInfo.h b/include/Engine/Rendering/FaceInfo.h index 9973276a..5bea6a49 100644 --- a/include/Engine/Rendering/FaceInfo.h +++ b/include/Engine/Rendering/FaceInfo.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_FACEINFO_H #define ENGINE_RENDERING_FACEINFO_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/GL/GLRenderer.h b/include/Engine/Rendering/GL/GLRenderer.h index e40ddde5..89dbbfe0 100644 --- a/include/Engine/Rendering/GL/GLRenderer.h +++ b/include/Engine/Rendering/GL/GLRenderer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_GL_GLRENDERER_H #define ENGINE_RENDERING_GL_GLRENDERER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/GL/GLShader.h b/include/Engine/Rendering/GL/GLShader.h index 19f8d99d..329f4700 100644 --- a/include/Engine/Rendering/GL/GLShader.h +++ b/include/Engine/Rendering/GL/GLShader.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_GL_GLSHADER_H #define ENGINE_RENDERING_GL_GLSHADER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/GL/GLShaderBuilder.h b/include/Engine/Rendering/GL/GLShaderBuilder.h index f201fa0c..0a46ba5c 100644 --- a/include/Engine/Rendering/GL/GLShaderBuilder.h +++ b/include/Engine/Rendering/GL/GLShaderBuilder.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_GL_GLSHADERBUILDER_H #define ENGINE_RENDERING_GL_GLSHADERBUILDER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Rendering/GL/GLShaderContainer.h b/include/Engine/Rendering/GL/GLShaderContainer.h index dee66008..a5b79edf 100644 --- a/include/Engine/Rendering/GL/GLShaderContainer.h +++ b/include/Engine/Rendering/GL/GLShaderContainer.h @@ -1,13 +1,5 @@ #ifndef ENGINE_RENDERING_GL_GLSHADERCONTAINER_H #define ENGINE_RENDERING_GL_GLSHADERCONTAINER_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class GLShader; class GLShader; class GLShader; diff --git a/include/Engine/Rendering/GameTexture.h b/include/Engine/Rendering/GameTexture.h index d0101fc3..587de07e 100644 --- a/include/Engine/Rendering/GameTexture.h +++ b/include/Engine/Rendering/GameTexture.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_GAMETEXTURE_H #define ENGINE_RENDERING_GAMETEXTURE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Rendering/Material.h b/include/Engine/Rendering/Material.h index b0f8c177..d9c6feb6 100644 --- a/include/Engine/Rendering/Material.h +++ b/include/Engine/Rendering/Material.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_MATERIAL_H #define ENGINE_RENDERING_MATERIAL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Rendering/ModelRenderer.h b/include/Engine/Rendering/ModelRenderer.h index 8b899ef3..a73cf6f3 100644 --- a/include/Engine/Rendering/ModelRenderer.h +++ b/include/Engine/Rendering/ModelRenderer.h @@ -1,13 +1,5 @@ #ifndef ENGINE_RENDERING_MODELRENDERER_H #define ENGINE_RENDERING_MODELRENDERER_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class Matrix4x4; #include diff --git a/include/Engine/Rendering/PolygonRenderer.h b/include/Engine/Rendering/PolygonRenderer.h index e27a4600..f017f567 100644 --- a/include/Engine/Rendering/PolygonRenderer.h +++ b/include/Engine/Rendering/PolygonRenderer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_POLYGONRENDERER_H #define ENGINE_RENDERING_POLYGONRENDERER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/SDL2/SDL2Renderer.h b/include/Engine/Rendering/SDL2/SDL2Renderer.h index 12c12c54..1640f051 100644 --- a/include/Engine/Rendering/SDL2/SDL2Renderer.h +++ b/include/Engine/Rendering/SDL2/SDL2Renderer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_SDL2_SDL2RENDERER_H #define ENGINE_RENDERING_SDL2_SDL2RENDERER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/Shader.h b/include/Engine/Rendering/Shader.h index 7a7be261..f7a6ab5f 100644 --- a/include/Engine/Rendering/Shader.h +++ b/include/Engine/Rendering/Shader.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_SHADER_H #define ENGINE_RENDERING_SHADER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class Shader { diff --git a/include/Engine/Rendering/Software/PolygonRasterizer.h b/include/Engine/Rendering/Software/PolygonRasterizer.h index 1a4ff086..263acb54 100644 --- a/include/Engine/Rendering/Software/PolygonRasterizer.h +++ b/include/Engine/Rendering/Software/PolygonRasterizer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_SOFTWARE_POLYGONRASTERIZER_H #define ENGINE_RENDERING_SOFTWARE_POLYGONRASTERIZER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/Software/Scanline.h b/include/Engine/Rendering/Software/Scanline.h index f17bb4d0..2577fefb 100644 --- a/include/Engine/Rendering/Software/Scanline.h +++ b/include/Engine/Rendering/Software/Scanline.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_SOFTWARE_SCANLINE_H #define ENGINE_RENDERING_SOFTWARE_SCANLINE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/Software/SoftwareRenderer.h b/include/Engine/Rendering/Software/SoftwareRenderer.h index 6dd1a76d..0b74667c 100644 --- a/include/Engine/Rendering/Software/SoftwareRenderer.h +++ b/include/Engine/Rendering/Software/SoftwareRenderer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_SOFTWARE_SOFTWARERENDERER_H #define ENGINE_RENDERING_SOFTWARE_SOFTWARERENDERER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/Texture.h b/include/Engine/Rendering/Texture.h index 812e71e3..c9ce37a3 100644 --- a/include/Engine/Rendering/Texture.h +++ b/include/Engine/Rendering/Texture.h @@ -1,13 +1,5 @@ #ifndef ENGINE_RENDERING_TEXTURE_H #define ENGINE_RENDERING_TEXTURE_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class Texture; #include diff --git a/include/Engine/Rendering/TextureReference.h b/include/Engine/Rendering/TextureReference.h index 30432674..f826bbb8 100644 --- a/include/Engine/Rendering/TextureReference.h +++ b/include/Engine/Rendering/TextureReference.h @@ -1,13 +1,5 @@ #ifndef ENGINE_RENDERING_TEXTUREREFERENCE_H #define ENGINE_RENDERING_TEXTUREREFERENCE_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class Texture; #include diff --git a/include/Engine/Rendering/VertexBuffer.h b/include/Engine/Rendering/VertexBuffer.h index 37469ad2..1b553b49 100644 --- a/include/Engine/Rendering/VertexBuffer.h +++ b/include/Engine/Rendering/VertexBuffer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_VERTEXBUFFER_H #define ENGINE_RENDERING_VERTEXBUFFER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Rendering/ViewTexture.h b/include/Engine/Rendering/ViewTexture.h index 90fdf197..cf3baad4 100644 --- a/include/Engine/Rendering/ViewTexture.h +++ b/include/Engine/Rendering/ViewTexture.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RENDERING_VIEWTEXTURE_H #define ENGINE_RENDERING_VIEWTEXTURE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/IModel.h b/include/Engine/ResourceTypes/IModel.h index 4cb5d5de..586649d7 100644 --- a/include/Engine/ResourceTypes/IModel.h +++ b/include/Engine/ResourceTypes/IModel.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMODEL_H #define ENGINE_RESOURCETYPES_IMODEL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ISound.h b/include/Engine/ResourceTypes/ISound.h index b235e796..c591116a 100644 --- a/include/Engine/ResourceTypes/ISound.h +++ b/include/Engine/ResourceTypes/ISound.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_ISOUND_H #define ENGINE_RESOURCETYPES_ISOUND_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ISprite.h b/include/Engine/ResourceTypes/ISprite.h index e384f2af..857fc2cc 100644 --- a/include/Engine/ResourceTypes/ISprite.h +++ b/include/Engine/ResourceTypes/ISprite.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_ISPRITE_H #define ENGINE_RESOURCETYPES_ISPRITE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/Image.h b/include/Engine/ResourceTypes/Image.h index f07a81b5..b9c2f1d8 100644 --- a/include/Engine/ResourceTypes/Image.h +++ b/include/Engine/ResourceTypes/Image.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMAGE_H #define ENGINE_RESOURCETYPES_IMAGE_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/ImageFormats/GIF.h b/include/Engine/ResourceTypes/ImageFormats/GIF.h index 5f086aae..fcf35e50 100644 --- a/include/Engine/ResourceTypes/ImageFormats/GIF.h +++ b/include/Engine/ResourceTypes/ImageFormats/GIF.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_GIF_H #define ENGINE_RESOURCETYPES_IMAGEFORMATS_GIF_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h b/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h index 0aeaa103..5866feeb 100644 --- a/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h +++ b/include/Engine/ResourceTypes/ImageFormats/ImageFormat.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_IMAGEFORMAT_H #define ENGINE_RESOURCETYPES_IMAGEFORMATS_IMAGEFORMAT_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class ImageFormat { diff --git a/include/Engine/ResourceTypes/ImageFormats/JPEG.h b/include/Engine/ResourceTypes/ImageFormats/JPEG.h index bb282089..df1010eb 100644 --- a/include/Engine/ResourceTypes/ImageFormats/JPEG.h +++ b/include/Engine/ResourceTypes/ImageFormats/JPEG.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_JPEG_H #define ENGINE_RESOURCETYPES_IMAGEFORMATS_JPEG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ImageFormats/PNG.h b/include/Engine/ResourceTypes/ImageFormats/PNG.h index 873b5a2d..24b51a7a 100644 --- a/include/Engine/ResourceTypes/ImageFormats/PNG.h +++ b/include/Engine/ResourceTypes/ImageFormats/PNG.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_IMAGEFORMATS_PNG_H #define ENGINE_RESOURCETYPES_IMAGEFORMATS_PNG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ModelFormats/HatchModel.h b/include/Engine/ResourceTypes/ModelFormats/HatchModel.h index 0de23bdf..9bd5a5ee 100644 --- a/include/Engine/ResourceTypes/ModelFormats/HatchModel.h +++ b/include/Engine/ResourceTypes/ModelFormats/HatchModel.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_MODELFORMATS_HATCHMODEL_H #define ENGINE_RESOURCETYPES_MODELFORMATS_HATCHMODEL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/ModelFormats/Importer.h b/include/Engine/ResourceTypes/ModelFormats/Importer.h index 2c8958c0..c9013643 100644 --- a/include/Engine/ResourceTypes/ModelFormats/Importer.h +++ b/include/Engine/ResourceTypes/ModelFormats/Importer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_MODELFORMATS_IMPORTER_H #define ENGINE_RESOURCETYPES_MODELFORMATS_IMPORTER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/ModelFormats/MD3Model.h b/include/Engine/ResourceTypes/ModelFormats/MD3Model.h index ae68b6f1..ff9b214a 100644 --- a/include/Engine/ResourceTypes/ModelFormats/MD3Model.h +++ b/include/Engine/ResourceTypes/ModelFormats/MD3Model.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_MODELFORMATS_MD3MODEL_H #define ENGINE_RESOURCETYPES_MODELFORMATS_MD3MODEL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h b/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h index 126b3c50..edc947e2 100644 --- a/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h +++ b/include/Engine/ResourceTypes/ModelFormats/RSDKModel.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_MODELFORMATS_RSDKMODEL_H #define ENGINE_RESOURCETYPES_MODELFORMATS_RSDKMODEL_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/ResourceManager.h b/include/Engine/ResourceTypes/ResourceManager.h index 700adcbf..97bb4ab2 100644 --- a/include/Engine/ResourceTypes/ResourceManager.h +++ b/include/Engine/ResourceTypes/ResourceManager.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_RESOURCEMANAGER_H #define ENGINE_RESOURCETYPES_RESOURCEMANAGER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h b/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h index 8ece0810..9f8fa02b 100644 --- a/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h +++ b/include/Engine/ResourceTypes/SceneFormats/HatchSceneReader.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_HATCHSCENEREADER_H #define ENGINE_RESOURCETYPES_SCENEFORMATS_HATCHSCENEREADER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h b/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h index 395e9265..3bbd35bd 100644 --- a/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h +++ b/include/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_RSDKSCENEREADER_H #define ENGINE_RESOURCETYPES_SCENEFORMATS_RSDKSCENEREADER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h b/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h index ae0cd7d1..58d400a0 100644 --- a/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h +++ b/include/Engine/ResourceTypes/SceneFormats/TiledMapReader.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SCENEFORMATS_TILEDMAPREADER_H #define ENGINE_RESOURCETYPES_SCENEFORMATS_TILEDMAPREADER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/ResourceTypes/SoundFormats/OGG.h b/include/Engine/ResourceTypes/SoundFormats/OGG.h index 710b2d18..23a61cec 100644 --- a/include/Engine/ResourceTypes/SoundFormats/OGG.h +++ b/include/Engine/ResourceTypes/SoundFormats/OGG.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_OGG_H #define ENGINE_RESOURCETYPES_SOUNDFORMATS_OGG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h b/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h index ef1e05a1..1510ac50 100644 --- a/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h +++ b/include/Engine/ResourceTypes/SoundFormats/SoundFormat.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_SOUNDFORMAT_H #define ENGINE_RESOURCETYPES_SOUNDFORMATS_SOUNDFORMAT_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/ResourceTypes/SoundFormats/WAV.h b/include/Engine/ResourceTypes/SoundFormats/WAV.h index 0fd0536f..487803a4 100644 --- a/include/Engine/ResourceTypes/SoundFormats/WAV.h +++ b/include/Engine/ResourceTypes/SoundFormats/WAV.h @@ -1,14 +1,6 @@ #ifndef ENGINE_RESOURCETYPES_SOUNDFORMATS_WAV_H #define ENGINE_RESOURCETYPES_SOUNDFORMATS_WAV_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Scene.h b/include/Engine/Scene.h index a0b35065..4532012c 100644 --- a/include/Engine/Scene.h +++ b/include/Engine/Scene.h @@ -1,13 +1,5 @@ #ifndef ENGINE_SCENE_H #define ENGINE_SCENE_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class Entity; #include diff --git a/include/Engine/Scene/SceneInfo.h b/include/Engine/Scene/SceneInfo.h index 10d7c46b..c444e558 100644 --- a/include/Engine/Scene/SceneInfo.h +++ b/include/Engine/Scene/SceneInfo.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_SCENEINFO_H #define ENGINE_SCENE_SCENEINFO_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Scene/SceneLayer.h b/include/Engine/Scene/SceneLayer.h index d4a2accd..8ba727f7 100644 --- a/include/Engine/Scene/SceneLayer.h +++ b/include/Engine/Scene/SceneLayer.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_SCENELAYER_H #define ENGINE_SCENE_SCENELAYER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Scene/ScrollingIndex.h b/include/Engine/Scene/ScrollingIndex.h index 4f1d22c3..14ae6c0e 100644 --- a/include/Engine/Scene/ScrollingIndex.h +++ b/include/Engine/Scene/ScrollingIndex.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_SCROLLINGINDEX_H #define ENGINE_SCENE_SCROLLINGINDEX_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class ScrollingIndex { public: diff --git a/include/Engine/Scene/ScrollingInfo.h b/include/Engine/Scene/ScrollingInfo.h index cfa118a9..469eff48 100644 --- a/include/Engine/Scene/ScrollingInfo.h +++ b/include/Engine/Scene/ScrollingInfo.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_SCROLLINGINFO_H #define ENGINE_SCENE_SCROLLINGINFO_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class ScrollingInfo { public: diff --git a/include/Engine/Scene/TileConfig.h b/include/Engine/Scene/TileConfig.h index c4b4f35e..b5201fdb 100644 --- a/include/Engine/Scene/TileConfig.h +++ b/include/Engine/Scene/TileConfig.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_TILECONFIG_H #define ENGINE_SCENE_TILECONFIG_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class TileConfig { public: diff --git a/include/Engine/Scene/TileSpriteInfo.h b/include/Engine/Scene/TileSpriteInfo.h index a72212fb..4ebe96c4 100644 --- a/include/Engine/Scene/TileSpriteInfo.h +++ b/include/Engine/Scene/TileSpriteInfo.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_TILESPRITEINFO_H #define ENGINE_SCENE_TILESPRITEINFO_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - class TileSpriteInfo { public: diff --git a/include/Engine/Scene/View.h b/include/Engine/Scene/View.h index 0572b123..c8e437ae 100644 --- a/include/Engine/Scene/View.h +++ b/include/Engine/Scene/View.h @@ -1,14 +1,6 @@ #ifndef ENGINE_SCENE_VIEW_H #define ENGINE_SCENE_VIEW_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/TextFormats/INI/INI.h b/include/Engine/TextFormats/INI/INI.h index b542a9d1..39370ad7 100644 --- a/include/Engine/TextFormats/INI/INI.h +++ b/include/Engine/TextFormats/INI/INI.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TEXTFORMATS_INI_INI_H #define ENGINE_TEXTFORMATS_INI_INI_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/TextFormats/XML/XMLParser.h b/include/Engine/TextFormats/XML/XMLParser.h index cdfe3ea4..eecf742c 100644 --- a/include/Engine/TextFormats/XML/XMLParser.h +++ b/include/Engine/TextFormats/XML/XMLParser.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TEXTFORMATS_XML_XMLPARSER_H #define ENGINE_TEXTFORMATS_XML_XMLPARSER_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Types/DrawGroupList.h b/include/Engine/Types/DrawGroupList.h index 7966b651..323094ed 100644 --- a/include/Engine/Types/DrawGroupList.h +++ b/include/Engine/Types/DrawGroupList.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TYPES_DRAWGROUPLIST_H #define ENGINE_TYPES_DRAWGROUPLIST_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Types/Entity.h b/include/Engine/Types/Entity.h index d496a9ac..15076623 100644 --- a/include/Engine/Types/Entity.h +++ b/include/Engine/Types/Entity.h @@ -1,13 +1,5 @@ #ifndef ENGINE_TYPES_ENTITY_H #define ENGINE_TYPES_ENTITY_H - -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - class ObjectList; class ObjectRegistry; class DrawGroupList; diff --git a/include/Engine/Types/ObjectList.h b/include/Engine/Types/ObjectList.h index e0b49d65..b253e915 100644 --- a/include/Engine/Types/ObjectList.h +++ b/include/Engine/Types/ObjectList.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TYPES_OBJECTLIST_H #define ENGINE_TYPES_OBJECTLIST_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Types/ObjectRegistry.h b/include/Engine/Types/ObjectRegistry.h index 0264c7f6..c4b5df6b 100644 --- a/include/Engine/Types/ObjectRegistry.h +++ b/include/Engine/Types/ObjectRegistry.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TYPES_OBJECTREGISTRY_H #define ENGINE_TYPES_OBJECTREGISTRY_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/include/Engine/Types/Tileset.h b/include/Engine/Types/Tileset.h index 2dbc5def..f0368ca6 100644 --- a/include/Engine/Types/Tileset.h +++ b/include/Engine/Types/Tileset.h @@ -1,14 +1,6 @@ #ifndef ENGINE_TYPES_TILESET_H #define ENGINE_TYPES_TILESET_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include #include diff --git a/include/Engine/Utilities/ColorUtils.h b/include/Engine/Utilities/ColorUtils.h index 751ffeec..33625c5b 100644 --- a/include/Engine/Utilities/ColorUtils.h +++ b/include/Engine/Utilities/ColorUtils.h @@ -1,14 +1,6 @@ #ifndef ENGINE_UTILITIES_COLORUTILS_H #define ENGINE_UTILITIES_COLORUTILS_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include class ColorUtils { diff --git a/include/Engine/Utilities/StringUtils.h b/include/Engine/Utilities/StringUtils.h index 130bcc58..219368cc 100644 --- a/include/Engine/Utilities/StringUtils.h +++ b/include/Engine/Utilities/StringUtils.h @@ -1,14 +1,6 @@ #ifndef ENGINE_UTILITIES_STRINGUTILS_H #define ENGINE_UTILITIES_STRINGUTILS_H -#define PUBLIC -#define PRIVATE -#define PROTECTED -#define STATIC -#define VIRTUAL -#define EXPOSED - - #include #include diff --git a/source/Engine/Application.cpp b/source/Engine/Application.cpp index b09c26cd..be343e8b 100644 --- a/source/Engine/Application.cpp +++ b/source/Engine/Application.cpp @@ -1,56 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Application { -public: - static vector CmdLineArgs; - - static INI* Settings; - static char SettingsFile[4096]; - - static XMLNode* GameConfig; - - static int TargetFPS; - static float CurrentFPS; - static bool Running; - static bool GameStart; - - static SDL_Window* Window; - static char WindowTitle[256]; - static int WindowWidth; - static int WindowHeight; - static int DefaultMonitor; - static Platforms Platform; - - static char EngineVersion[256]; - - static char GameTitle[256]; - static char GameTitleShort[256]; - static char GameVersion[256]; - static char GameDescription[256]; - - static int UpdatesPerFrame; - static bool Stepper; - static bool Step; - - static int MasterVolume; - static int MusicVolume; - static int SoundVolume; - - static int StartSceneNum; - - static bool DevMenuActivated; -}; -#endif - #include #include @@ -168,7 +115,7 @@ void DEBUG_DrawText(char* text, float x, float y) { } } -PUBLIC STATIC void Application::Init(int argc, char* args[]) { +void Application::Init(int argc, char* args[]) { #ifdef MSYS AllocConsole(); freopen_s((FILE **)stdin, "CONIN$", "w", stdin); @@ -297,7 +244,7 @@ PUBLIC STATIC void Application::Init(int argc, char* args[]) { Running = true; } -PUBLIC STATIC void Application::SetTargetFrameRate(int targetFPS) { +void Application::SetTargetFrameRate(int targetFPS) { if (targetFPS < 1) TargetFPS = 1; else if (targetFPS > MAX_TARGET_FRAMERATE) @@ -308,7 +255,7 @@ PUBLIC STATIC void Application::SetTargetFrameRate(int targetFPS) { FrameTimeDesired = 1000.0 / TargetFPS; } -PRIVATE STATIC void Application::MakeEngineVersion() { +void Application::MakeEngineVersion() { std::string versionText = std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR); #ifdef VERSION_PATCH @@ -331,10 +278,10 @@ PRIVATE STATIC void Application::MakeEngineVersion() { StringUtils::Copy(Application::EngineVersion, versionText.c_str(), sizeof(Application::EngineVersion)); } -PUBLIC STATIC bool Application::IsPC() { +bool Application::IsPC() { return Application::Platform == Platforms::Windows || Application::Platform == Platforms::MacOS || Application::Platform == Platforms::Linux; } -PUBLIC STATIC bool Application::IsMobile() { +bool Application::IsMobile() { return Application::Platform == Platforms::iOS || Application::Platform == Platforms::Android; } @@ -354,7 +301,7 @@ double MetricFPSCounterTime = -1; double MetricPresentTime = -1; double MetricFrameTime = 0.0; vector ListList; -PUBLIC STATIC void Application::GetPerformanceSnapshot() { +void Application::GetPerformanceSnapshot() { if (Scene::ObjectLists) { // General Performance Snapshot double types[] = { @@ -474,13 +421,13 @@ PUBLIC STATIC void Application::GetPerformanceSnapshot() { } } -PUBLIC STATIC void Application::SetWindowTitle(const char* title) { +void Application::SetWindowTitle(const char* title) { memset(Application::WindowTitle, 0, sizeof(Application::WindowTitle)); snprintf(Application::WindowTitle, sizeof(Application::WindowTitle), "%s", title); Application::UpdateWindowTitle(); } -PUBLIC STATIC void Application::UpdateWindowTitle() { +void Application::UpdateWindowTitle() { std::string titleText = std::string(Application::WindowTitle); bool paren = false; @@ -526,7 +473,7 @@ PUBLIC STATIC void Application::UpdateWindowTitle() { SDL_SetWindowTitle(Application::Window, titleText.c_str()); } -PRIVATE STATIC void Application::Restart() { +void Application::Restart() { // Reset FPS timer BenchmarkFrameCount = 0; @@ -554,26 +501,26 @@ PRIVATE STATIC void Application::Restart() { else if (vol > 100) \ vol = 100 -PUBLIC STATIC void Application::SetMasterVolume(int volume) { +void Application::SetMasterVolume(int volume) { CLAMP_VOLUME(volume); Application::MasterVolume = volume; AudioManager::MasterVolume = Application::MasterVolume / 100.0f; } -PUBLIC STATIC void Application::SetMusicVolume(int volume) { +void Application::SetMusicVolume(int volume) { CLAMP_VOLUME(volume); Application::MusicVolume = volume; AudioManager::MusicVolume = Application::MusicVolume / 100.0f; } -PUBLIC STATIC void Application::SetSoundVolume(int volume) { +void Application::SetSoundVolume(int volume) { CLAMP_VOLUME(volume); Application::SoundVolume = volume; AudioManager::SoundVolume = Application::SoundVolume / 100.0f; } -PRIVATE STATIC void Application::LoadAudioSettings() { +void Application::LoadAudioSettings() { INI* settings = Application::Settings; int masterVolume = Application::MasterVolume; @@ -601,7 +548,7 @@ PRIVATE STATIC void Application::LoadAudioSettings() { SDL_Keycode KeyBindsSDL[(int)KeyBind::Max]; -PRIVATE STATIC void Application::LoadKeyBinds() { +void Application::LoadKeyBinds() { XMLNode* node = nullptr; if (Application::GameConfig) node = XMLParser::SearchNode(Application::GameConfig->children[0], "keys"); @@ -642,18 +589,18 @@ PRIVATE STATIC void Application::LoadKeyBinds() { #undef GET_KEY } -PRIVATE STATIC void Application::LoadDevSettings() { +void Application::LoadDevSettings() { Application::Settings->GetBool("dev", "devMenu", &DevMenu); Application::Settings->GetBool("dev", "viewPerformance", &ShowFPS); Application::Settings->GetBool("dev", "donothing", &DoNothing); Application::Settings->GetInteger("dev", "fastforward", &UpdatesPerFastForward); } -PUBLIC STATIC bool Application::IsWindowResizeable() { +bool Application::IsWindowResizeable() { return !Application::IsMobile(); } -PUBLIC STATIC void Application::SetWindowSize(int window_w, int window_h) { +void Application::SetWindowSize(int window_w, int window_h) { if (!Application::IsWindowResizeable()) return; @@ -668,11 +615,11 @@ PUBLIC STATIC void Application::SetWindowSize(int window_w, int window_h) { Graphics::Resize(window_w, window_h); } -PUBLIC STATIC bool Application::GetWindowFullscreen() { +bool Application::GetWindowFullscreen() { return !!(SDL_GetWindowFlags(Application::Window) & SDL_WINDOW_FULLSCREEN_DESKTOP); } -PUBLIC STATIC void Application::SetWindowFullscreen(bool isFullscreen) { +void Application::SetWindowFullscreen(bool isFullscreen) { SDL_SetWindowFullscreen(Application::Window, isFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); int window_w, window_h; @@ -681,14 +628,14 @@ PUBLIC STATIC void Application::SetWindowFullscreen(bool isFullscreen) { Graphics::Resize(window_w, window_h); } -PUBLIC STATIC void Application::SetWindowBorderless(bool isBorderless) { +void Application::SetWindowBorderless(bool isBorderless) { SDL_SetWindowBordered(Application::Window, (SDL_bool)(!isBorderless)); } -PUBLIC STATIC int Application::GetKeyBind(int bind) { +int Application::GetKeyBind(int bind) { return KeyBinds[bind]; } -PUBLIC STATIC void Application::SetKeyBind(int bind, int key) { +void Application::SetKeyBind(int bind, int key) { KeyBinds[bind] = key; if (key == Key_UNKNOWN) KeyBindsSDL[bind] = SDLK_UNKNOWN; @@ -696,7 +643,7 @@ PUBLIC STATIC void Application::SetKeyBind(int bind, int key) { KeyBindsSDL[bind] = SDL_GetKeyFromScancode(InputManager::KeyToSDLScancode[key]); } -PRIVATE STATIC void Application::PollEvents() { +void Application::PollEvents() { SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { @@ -846,7 +793,7 @@ PRIVATE STATIC void Application::PollEvents() { } } } -PRIVATE STATIC void Application::RunFrame(void* p) { +void Application::RunFrame(void* p) { FrameTimeStart = Clock::GetTicks(); // Event loop @@ -1113,7 +1060,7 @@ PRIVATE STATIC void Application::RunFrame(void* p) { MetricFrameTime = Clock::GetTicks() - FrameTimeStart; } -PRIVATE STATIC void Application::DelayFrame() { +void Application::DelayFrame() { double frameTime = Clock::GetTicks() - FrameTimeStart; double frameDurationRemainder = FrameTimeDesired - frameTime; if (frameDurationRemainder >= 0.0) { @@ -1130,7 +1077,7 @@ PRIVATE STATIC void Application::DelayFrame() { while ((Clock::GetTicks() - FrameTimeStart) < FrameTimeDesired); } } -PUBLIC STATIC void Application::Run(int argc, char* args[]) { +void Application::Run(int argc, char* args[]) { Application::Init(argc, args); if (!Running) return; @@ -1214,7 +1161,7 @@ PUBLIC STATIC void Application::Run(int argc, char* args[]) { #endif } -PUBLIC STATIC void Application::Cleanup() { +void Application::Cleanup() { ResourceManager::Dispose(); AudioManager::Dispose(); InputManager::Dispose(); @@ -1253,7 +1200,7 @@ static void ParseGameConfigBool(XMLNode* node, const char* option, bool& val) { val = !strcmp(read, "true"); } -PRIVATE STATIC void Application::LoadGameConfig() { +void Application::LoadGameConfig() { StartingScene[0] = '\0'; Application::GameConfig = nullptr; @@ -1323,13 +1270,13 @@ PRIVATE STATIC void Application::LoadGameConfig() { XMLParser::CopyTokenToString(node->children[0]->name, StartingScene, sizeof(StartingScene)); } -PRIVATE STATIC void Application::DisposeGameConfig() { +void Application::DisposeGameConfig() { if (Application::GameConfig) XMLParser::Free(Application::GameConfig); Application::GameConfig = nullptr; } -PRIVATE STATIC string Application::ParseGameVersion(XMLNode* versionNode) { +string Application::ParseGameVersion(XMLNode* versionNode) { if (versionNode->children.size() == 1) return versionNode->children[0]->name.ToString(); @@ -1364,7 +1311,7 @@ PRIVATE STATIC string Application::ParseGameVersion(XMLNode* versionNode) { return versionText; } -PRIVATE STATIC void Application::LoadGameInfo() { +void Application::LoadGameInfo() { StringUtils::Copy(Application::GameTitle, "Hatch Game Engine", sizeof(Application::GameTitle)); StringUtils::Copy(Application::GameTitleShort, Application::GameTitle, sizeof(Application::GameTitleShort)); StringUtils::Copy(Application::GameVersion, "1.0", sizeof(Application::GameVersion)); @@ -1398,7 +1345,7 @@ PRIVATE STATIC void Application::LoadGameInfo() { } } -PUBLIC STATIC void Application::LoadSceneInfo() { +void Application::LoadSceneInfo() { if (ResourceManager::ResourceExists("Game/SceneConfig.xml")) { XMLNode* node; @@ -1442,11 +1389,11 @@ PUBLIC STATIC void Application::LoadSceneInfo() { } } -PUBLIC STATIC void Application::InitPlayerControls() { +void Application::InitPlayerControls() { InputManager::InitPlayerControls(); } -PUBLIC STATIC bool Application::LoadSettings(const char* filename) { +bool Application::LoadSettings(const char* filename) { INI* ini = INI::Load(filename); if (ini == nullptr) return false; @@ -1460,23 +1407,23 @@ PUBLIC STATIC bool Application::LoadSettings(const char* filename) { return true; } -PUBLIC STATIC void Application::ReadSettings() { +void Application::ReadSettings() { Application::LoadAudioSettings(); Application::LoadDevSettings(); Application::LoadKeyBinds(); } -PUBLIC STATIC void Application::ReloadSettings() { +void Application::ReloadSettings() { if (Application::Settings && Application::Settings->Reload()) Application::ReadSettings(); } -PUBLIC STATIC void Application::ReloadSettings(const char* filename) { +void Application::ReloadSettings(const char* filename) { if (Application::LoadSettings(filename)) Application::ReadSettings(); } -PUBLIC STATIC void Application::InitSettings(const char* filename) { +void Application::InitSettings(const char* filename) { Application::LoadSettings(filename); // NOTE: If no settings could be loaded, create settings with default values. @@ -1509,21 +1456,21 @@ PUBLIC STATIC void Application::InitSettings(const char* filename) { Application::Settings->GetInteger("display", "multisample", &Graphics::MultisamplingEnabled); Application::Settings->GetInteger("display", "defaultMonitor", &Application::DefaultMonitor); } -PUBLIC STATIC void Application::SaveSettings() { +void Application::SaveSettings() { if (Application::Settings) Application::Settings->Save(); } -PUBLIC STATIC void Application::SaveSettings(const char* filename) { +void Application::SaveSettings(const char* filename) { if (Application::Settings) Application::Settings->Save(filename); } -PUBLIC STATIC void Application::SetSettingsFilename(const char* filename) { +void Application::SetSettingsFilename(const char* filename) { StringUtils::Copy(Application::SettingsFile, filename, sizeof(Application::SettingsFile)); if (Application::Settings) Application::Settings->SetFilename(filename); } -PRIVATE STATIC int Application::HandleAppEvents(void* data, SDL_Event* event) { +int Application::HandleAppEvents(void* data, SDL_Event* event) { switch (event->type) { case SDL_APP_TERMINATING: Log::Print(Log::LOG_VERBOSE, "SDL_APP_TERMINATING"); diff --git a/source/Engine/Audio/AudioManager.cpp b/source/Engine/Audio/AudioManager.cpp index cca12469..18193742 100644 --- a/source/Engine/Audio/AudioManager.cpp +++ b/source/Engine/Audio/AudioManager.cpp @@ -1,42 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include - -class AudioManager { -public: - static SDL_AudioDeviceID Device; - static SDL_AudioSpec DeviceFormat; - static bool AudioEnabled; - - static Uint8 BytesPerSample; - static Uint8* MixBuffer; - static size_t MixBufferSize; - - static deque MusicStack; - static AudioChannel* SoundArray; - static int SoundArrayLength; - - static float MasterVolume; - static float MusicVolume; - static float SoundVolume; - - static float LowPassFilter; - - static Uint8* AudioQueue; - static size_t AudioQueueSize; - static size_t AudioQueueMaxSize; - - enum { - REQUEST_EOF = 0, - REQUEST_ERROR = -1, - REQUEST_CONVERTING = -2, - }; -}; -#endif - #include #include #include @@ -85,7 +46,7 @@ Sint16 mZy[2 * 2]; // 2 per channel float mZxF[2 * 2]; // 2 per channel float mZyF[2 * 2]; // 2 per channel -PUBLIC STATIC void AudioManager::CalculateCoeffs() { +void AudioManager::CalculateCoeffs() { double theta = 2.0 * M_PI * mNormalizedFreq; // normalized frequency has been precalculated as fc/fs double d = 0.5 * (1.0 / mQuality) * sin(theta); double beta = 0.5 * ( (1.0 - d) / (1.0 + d) ); @@ -114,7 +75,7 @@ PUBLIC STATIC void AudioManager::CalculateCoeffs() { b1 = -2.0 * gamma; b2 = 2.0 * beta; } -PUBLIC STATIC Sint16 AudioManager::ProcessSample(Sint16 inSample, int channel) { +Sint16 AudioManager::ProcessSample(Sint16 inSample, int channel) { Sint16 outSample; int idx0 = 2 * channel; int idx1 = idx0 + 1; @@ -135,7 +96,7 @@ PUBLIC STATIC Sint16 AudioManager::ProcessSample(Sint16 inSample, int channel) { return (Sint16)(inSample * (1.0 - AudioManager::LowPassFilter) + outSample * mGain * AudioManager::LowPassFilter); } -PUBLIC STATIC float AudioManager::ProcessSampleFloat(float inSample, int channel) { +float AudioManager::ProcessSampleFloat(float inSample, int channel) { float outSample; int idx0 = 2 * channel; int idx1 = idx0 + 1; @@ -152,7 +113,7 @@ PUBLIC STATIC float AudioManager::ProcessSampleFloat(float inSample, int channe return (float)(inSample * (1.0 - AudioManager::LowPassFilter) + outSample * mGain * AudioManager::LowPassFilter); } -PUBLIC STATIC void AudioManager::Init() { +void AudioManager::Init() { CalculateCoeffs(); SoundArray = (AudioChannel*)Memory::Calloc(SoundArrayLength, sizeof(AudioChannel)); @@ -215,7 +176,7 @@ PUBLIC STATIC void AudioManager::Init() { AudioQueue = (Uint8*)Memory::Calloc(8, AudioQueueMaxSize); } -PUBLIC STATIC void AudioManager::ClampParams(float& pan, float& speed, float& volume) { +void AudioManager::ClampParams(float& pan, float& speed, float& volume) { if (pan < -1.0f) pan = -1.0f; else if (pan > 1.0f) @@ -230,7 +191,7 @@ PUBLIC STATIC void AudioManager::ClampParams(float& pan, float& speed, float& volume = 0.0f; } -PRIVATE STATIC void AudioManager::UpdateChannelPlayer(AudioPlayback* playback, ISound* sound) { +void AudioManager::UpdateChannelPlayer(AudioPlayback* playback, ISound* sound) { if (!playback->SoundData) { playback->SoundData = new SoundFormat; playback->OwnsSoundData = true; @@ -247,10 +208,10 @@ PRIVATE STATIC void AudioManager::UpdateChannelPlayer(AudioPlayback* playback, playback->SoundData->SampleIndex = 0; } -PUBLIC STATIC void AudioManager::SetSound(int channel, ISound* music) { +void AudioManager::SetSound(int channel, ISound* music) { AudioManager::SetSound(channel, music, false, 0, 0.0f, 1.0f, 1.0f, nullptr); } -PUBLIC STATIC void AudioManager::SetSound(int channel, ISound* sound, bool loop, int loopPoint, float pan, float speed, float volume, void* origin) { +void AudioManager::SetSound(int channel, ISound* sound, bool loop, int loopPoint, float pan, float speed, float volume, void* origin) { AudioManager::Lock(); AudioChannel* audio = &SoundArray[channel]; @@ -286,10 +247,10 @@ PUBLIC STATIC void AudioManager::SetSound(int channel, ISound* sound, bool loo AudioManager::Unlock(); } -PUBLIC STATIC int AudioManager::PlaySound(ISound* music) { +int AudioManager::PlaySound(ISound* music) { return AudioManager::PlaySound(music, false, 0, 0.0f, 1.0f, 1.0f, nullptr); } -PUBLIC STATIC int AudioManager::PlaySound(ISound* music, bool loop, int loopPoint, float pan, float speed, float volume, void* origin) { +int AudioManager::PlaySound(ISound* music, bool loop, int loopPoint, float pan, float speed, float volume, void* origin) { for (int i = 0; i < SoundArrayLength; i++) { AudioChannel* audio = &SoundArray[i]; if (!audio->Audio || audio->Stopped) { @@ -301,10 +262,10 @@ PUBLIC STATIC int AudioManager::PlaySound(ISound* music, bool loop, int loopP return -1; } -PUBLIC STATIC void AudioManager::PushMusic(ISound* music, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished) { +void AudioManager::PushMusic(ISound* music, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished) { PushMusicAt(music, 0.0, loop, lp, pan, speed, volume, fadeInAfterFinished); } -PUBLIC STATIC void AudioManager::PushMusicAt(ISound* music, double at, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished) { +void AudioManager::PushMusicAt(ISound* music, double at, bool loop, Uint32 lp, float pan, float speed, float volume, double fadeInAfterFinished) { if (music->LoadFailed) return; AudioManager::Lock(); @@ -343,7 +304,7 @@ PUBLIC STATIC void AudioManager::PushMusicAt(ISound* music, double at, bool lo AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::RemoveMusic(ISound* music) { +void AudioManager::RemoveMusic(ISound* music) { AudioManager::Lock(); for (size_t i = 0; i < MusicStack.size(); i++) { if (MusicStack[i]->Audio == music) { @@ -353,10 +314,10 @@ PUBLIC STATIC void AudioManager::RemoveMusic(ISound* music) { } AudioManager::Unlock(); } -PUBLIC STATIC bool AudioManager::IsPlayingMusic() { +bool AudioManager::IsPlayingMusic() { return MusicStack.size() > 0; } -PUBLIC STATIC bool AudioManager::IsPlayingMusic(ISound* music) { +bool AudioManager::IsPlayingMusic(ISound* music) { for (size_t i = 0; i < MusicStack.size(); i++) { if (MusicStack[i]->Audio == music) { return true; @@ -364,7 +325,7 @@ PUBLIC STATIC bool AudioManager::IsPlayingMusic(ISound* music) { } return false; } -PUBLIC STATIC void AudioManager::ClearMusic() { +void AudioManager::ClearMusic() { AudioManager::Lock(); for (size_t i = 0; i < MusicStack.size(); i++) { delete MusicStack[i]; @@ -372,7 +333,7 @@ PUBLIC STATIC void AudioManager::ClearMusic() { MusicStack.clear(); AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::ClearSounds() { +void AudioManager::ClearSounds() { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { SoundArray[i].Stopped = true; @@ -383,7 +344,7 @@ PUBLIC STATIC void AudioManager::ClearSounds() { } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::FadeOutMusic(double seconds) { +void AudioManager::FadeOutMusic(double seconds) { AudioManager::Lock(); if (MusicStack.size() > 0) { MusicStack[0]->Fading = MusicFade_Out; @@ -392,7 +353,7 @@ PUBLIC STATIC void AudioManager::FadeOutMusic(double seconds) { } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AlterMusic(float pan, float speed, float volume) { +void AudioManager::AlterMusic(float pan, float speed, float volume) { AudioManager::Lock(); if (MusicStack.size() > 0) { AudioManager::ClampParams(pan, speed, volume); @@ -402,7 +363,7 @@ PUBLIC STATIC void AudioManager::AlterMusic(float pan, float speed, float volu } AudioManager::Unlock(); } -PUBLIC STATIC double AudioManager::GetMusicPosition(ISound* music) { +double AudioManager::GetMusicPosition(ISound* music) { AudioManager::Lock(); double position = 0.0; for (size_t i = 0; i < MusicStack.size(); i++) { @@ -415,14 +376,14 @@ PUBLIC STATIC double AudioManager::GetMusicPosition(ISound* music) { return position; } -PUBLIC STATIC void AudioManager::Lock() { +void AudioManager::Lock() { SDL_LockAudioDevice(Device); } -PUBLIC STATIC void AudioManager::Unlock() { +void AudioManager::Unlock() { SDL_UnlockAudioDevice(Device); } -PUBLIC STATIC int AudioManager::GetFreeChannel() { +int AudioManager::GetFreeChannel() { AudioManager::Lock(); int channel = -1; for (int i = 0; i < SoundArrayLength; i++) { @@ -434,7 +395,7 @@ PUBLIC STATIC int AudioManager::GetFreeChannel() { AudioManager::Unlock(); return channel; } -PUBLIC STATIC void AudioManager::AlterChannel(int channel, float pan, float speed, float volume) { +void AudioManager::AlterChannel(int channel, float pan, float speed, float volume) { AudioManager::Lock(); if (!SoundArray[channel].Stopped && !SoundArray[channel].Paused) { AudioManager::ClampParams(pan, speed, volume); @@ -444,14 +405,14 @@ PUBLIC STATIC void AudioManager::AlterChannel(int channel, float pan, float sp } AudioManager::Unlock(); } -PUBLIC STATIC bool AudioManager::AudioIsPlaying(int channel) { +bool AudioManager::AudioIsPlaying(int channel) { bool isPlaying = false; AudioManager::Lock(); isPlaying = !SoundArray[channel].Stopped && !SoundArray[channel].Paused; AudioManager::Unlock(); return isPlaying; } -PUBLIC STATIC bool AudioManager::AudioIsPlaying(ISound* audio) { +bool AudioManager::AudioIsPlaying(ISound* audio) { bool isPlaying = false; AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { @@ -462,12 +423,12 @@ PUBLIC STATIC bool AudioManager::AudioIsPlaying(ISound* audio) { AudioManager::Unlock(); return isPlaying; } -PUBLIC STATIC void AudioManager::AudioUnpause(int channel) { +void AudioManager::AudioUnpause(int channel) { AudioManager::Lock(); SoundArray[channel].Paused = false; AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioUnpause(ISound* audio) { +void AudioManager::AudioUnpause(ISound* audio) { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { if (SoundArray[i].Audio == audio) @@ -475,12 +436,12 @@ PUBLIC STATIC void AudioManager::AudioUnpause(ISound* audio) { } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioPause(int channel) { +void AudioManager::AudioPause(int channel) { AudioManager::Lock(); SoundArray[channel].Paused = true; AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioPause(ISound* audio) { +void AudioManager::AudioPause(ISound* audio) { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { if (SoundArray[i].Audio == audio) @@ -488,12 +449,12 @@ PUBLIC STATIC void AudioManager::AudioPause(ISound* audio) { } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioStop(int channel) { +void AudioManager::AudioStop(int channel) { AudioManager::Lock(); SoundArray[channel].Stopped = true; AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioStop(ISound* audio) { +void AudioManager::AudioStop(ISound* audio) { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { if (SoundArray[i].Audio == audio) @@ -501,26 +462,26 @@ PUBLIC STATIC void AudioManager::AudioStop(ISound* audio) { } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioUnpauseAll() { +void AudioManager::AudioUnpauseAll() { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) SoundArray[i].Paused = false; AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioPauseAll() { +void AudioManager::AudioPauseAll() { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) SoundArray[i].Paused = true; AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::AudioStopAll() { +void AudioManager::AudioStopAll() { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) SoundArray[i].Stopped = true; AudioManager::Unlock(); } -PUBLIC STATIC bool AudioManager::IsOriginPlaying(void* origin, ISound* audio) { +bool AudioManager::IsOriginPlaying(void* origin, ISound* audio) { bool isPlaying = false; AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { @@ -531,7 +492,7 @@ PUBLIC STATIC bool AudioManager::IsOriginPlaying(void* origin, ISound* audio) AudioManager::Unlock(); return isPlaying; } -PUBLIC STATIC void AudioManager::StopOriginSound(void* origin, ISound* audio) { +void AudioManager::StopOriginSound(void* origin, ISound* audio) { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { if (SoundArray[i].Audio == audio && SoundArray[i].Origin == origin) @@ -539,7 +500,7 @@ PUBLIC STATIC void AudioManager::StopOriginSound(void* origin, ISound* audio) } AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::StopAllOriginSounds(void* origin) { +void AudioManager::StopAllOriginSounds(void* origin) { AudioManager::Lock(); for (int i = 0; i < SoundArrayLength; i++) { if (SoundArray[i].Origin == origin) @@ -548,7 +509,7 @@ PUBLIC STATIC void AudioManager::StopAllOriginSounds(void* origin) { AudioManager::Unlock(); } -PUBLIC STATIC void AudioManager::MixAudioLR(Uint8* dest, Uint8* src, size_t len, float volumeL, float volumeR) { +void AudioManager::MixAudioLR(Uint8* dest, Uint8* src, size_t len, float volumeL, float volumeR) { #define DEFINE_STREAM_PTR(type) type* src##type; type* dest##type #define PAN_STREAM_PTR(type) \ src##type = (type*)(src); \ @@ -579,7 +540,7 @@ PUBLIC STATIC void AudioManager::MixAudioLR(Uint8* dest, Uint8* src, size_t le #undef PAN_STREAM_PTR } -PRIVATE STATIC bool AudioManager::HandleFading(AudioChannel* audio) { +bool AudioManager::HandleFading(AudioChannel* audio) { if (audio->Fading == MusicFade_Out) { audio->FadeTimer -= (double)DeviceFormat.samples / DeviceFormat.freq; if (audio->FadeTimer < 0.0) { @@ -599,7 +560,7 @@ PRIVATE STATIC bool AudioManager::HandleFading(AudioChannel* audio) { } return false; } -PUBLIC STATIC bool AudioManager::AudioPlayMix(AudioChannel* audio, Uint8* stream, int len, float volume) { +bool AudioManager::AudioPlayMix(AudioChannel* audio, Uint8* stream, int len, float volume) { if (AudioManager::HandleFading(audio)) return true; @@ -692,7 +653,7 @@ PUBLIC STATIC bool AudioManager::AudioPlayMix(AudioChannel* audio, Uint8* stre return false; } -PUBLIC STATIC void AudioManager::AudioCallback(void* data, Uint8* stream, int len) { +void AudioManager::AudioCallback(void* data, Uint8* stream, int len) { memset(stream, 0x00, len); if (AudioManager::AudioQueueSize >= (size_t)len) { @@ -749,7 +710,7 @@ PUBLIC STATIC void AudioManager::AudioCallback(void* data, Uint8* stream, int } } -PUBLIC STATIC void AudioManager::Dispose() { +void AudioManager::Dispose() { Memory::Free(SoundArray); Memory::Free(AudioQueue); Memory::Free(MixBuffer); diff --git a/source/Engine/Audio/AudioPlayback.cpp b/source/Engine/Audio/AudioPlayback.cpp index c5df774d..d8fddab0 100644 --- a/source/Engine/Audio/AudioPlayback.cpp +++ b/source/Engine/Audio/AudioPlayback.cpp @@ -1,29 +1,7 @@ -#if INTERFACE -#include -#include - -#include - -class AudioPlayback { -public: - Uint8* Buffer = NULL; - Uint8* UnconvertedSampleBuffer = NULL; - Uint32 BufferedSamples = 0; - SDL_AudioSpec Format; - size_t BytesPerSample = 0; - size_t RequiredSamples = 0; - size_t DeviceBytesPerSample = 0; - SDL_AudioStream* ConversionStream = NULL; - SoundFormat* SoundData = NULL; - bool OwnsSoundData = false; - Sint32 LoopIndex = -1; -}; -#endif - #include #include -PUBLIC AudioPlayback::AudioPlayback(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample) { +AudioPlayback::AudioPlayback(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample) { Format = format; RequiredSamples = requiredSamples; BytesPerSample = audioBytesPerSample; @@ -37,7 +15,7 @@ PUBLIC AudioPlayback::AudioPlayback(SDL_AudioSpec format, size_t requiredSa CreateConversionStream(format); } -PUBLIC void AudioPlayback::Change(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample) { +void AudioPlayback::Change(SDL_AudioSpec format, size_t requiredSamples, size_t audioBytesPerSample, size_t deviceBytesPerSample) { bool formatChanged = format.format != Format.format || format.channels != Format.channels || format.freq != Format.freq; size_t bufSize = requiredSamples * deviceBytesPerSample; @@ -60,7 +38,7 @@ PUBLIC void AudioPlayback::Change(SDL_AudioSpec format, size_t requiredSamples, } } -PRIVATE void AudioPlayback::CreateConversionStream(SDL_AudioSpec format) { +void AudioPlayback::CreateConversionStream(SDL_AudioSpec format) { ConversionStream = SDL_NewAudioStream(Format.format, Format.channels, Format.freq, AudioManager::DeviceFormat.format, AudioManager::DeviceFormat.channels, AudioManager::DeviceFormat.freq); if (ConversionStream == NULL) { Log::Print(Log::LOG_ERROR, "Conversion stream failed to create: %s", SDL_GetError()); @@ -75,7 +53,7 @@ PRIVATE void AudioPlayback::CreateConversionStream(SDL_AudioSpec format) { } } -PUBLIC void AudioPlayback::Dispose() { +void AudioPlayback::Dispose() { if (Buffer) { Memory::Free(Buffer); Buffer = NULL; @@ -98,7 +76,7 @@ PUBLIC void AudioPlayback::Dispose() { } } -PUBLIC int AudioPlayback::RequestSamples(int samples, bool loop, int sample_to_loop_to) { +int AudioPlayback::RequestSamples(int samples, bool loop, int sample_to_loop_to) { if (!SoundData) return AudioManager::REQUEST_ERROR; @@ -164,13 +142,13 @@ PUBLIC int AudioPlayback::RequestSamples(int samples, bool loop, int sample_to_l return received_bytes; } -PUBLIC void AudioPlayback::Seek(int samples) { +void AudioPlayback::Seek(int samples) { if (!SoundData) return; SoundData->SeekSample(samples); } -PUBLIC AudioPlayback::~AudioPlayback() { +AudioPlayback::~AudioPlayback() { Dispose(); } diff --git a/source/Engine/Bytecode/Bytecode.cpp b/source/Engine/Bytecode/Bytecode.cpp index aadfcb44..dcd81e10 100644 --- a/source/Engine/Bytecode/Bytecode.cpp +++ b/source/Engine/Bytecode/Bytecode.cpp @@ -1,21 +1,3 @@ -#if INTERFACE -#include -#include - -class Bytecode { -public: - static const char* Magic; - static Uint32 LatestVersion; - static vector FunctionNames; - - vector Functions; - - Uint8 Version; - bool HasDebugInfo = false; - const char* SourceFilename = nullptr; -}; -#endif - #include #include #include @@ -26,15 +8,15 @@ const char* Bytecode::Magic = "HTVM"; Uint32 Bytecode::LatestVersion = BYTECODE_VERSION; vector Bytecode::FunctionNames{ "", "main" }; -PUBLIC Bytecode::Bytecode() { +Bytecode::Bytecode() { Version = LatestVersion; } -PUBLIC Bytecode::~Bytecode() { +Bytecode::~Bytecode() { Memory::Free((void*)SourceFilename); } -PUBLIC bool Bytecode::Read(BytecodeContainer bytecode, HashMap* tokens) { +bool Bytecode::Read(BytecodeContainer bytecode, HashMap* tokens) { MemoryStream* stream = MemoryStream::New(bytecode.Data, bytecode.Size); if (!stream) return false; @@ -143,7 +125,7 @@ PUBLIC bool Bytecode::Read(BytecodeContainer bytecode, HashMap* to return true; } -PUBLIC void Bytecode::Write(Stream* stream, const char* sourceFilename, HashMap* tokenMap) { +void Bytecode::Write(Stream* stream, const char* sourceFilename, HashMap* tokenMap) { int hasSourceFilename = (sourceFilename != nullptr) ? 1 : 0; int hasDebugInfo = HasDebugInfo ? 1 : 0; diff --git a/source/Engine/Bytecode/Compiler.cpp b/source/Engine/Bytecode/Compiler.cpp index 2c4f3cb4..740866be 100644 --- a/source/Engine/Bytecode/Compiler.cpp +++ b/source/Engine/Bytecode/Compiler.cpp @@ -1,32 +1,3 @@ -#if INTERFACE -#include -#include - -class Compiler { -public: - static Parser parser; - static Scanner scanner; - static ParseRule* Rules; - static vector Functions; - static vector ModuleLocals; - static HashMap* TokenMap; - static bool ShowWarnings; - static bool WriteDebugInfo; - static bool WriteSourceFilename; - - class Compiler* Enclosing = nullptr; - ObjFunction* Function = nullptr; - int Type = 0; - string ClassName; - Local Locals[0x100]; - int LocalCount = 0; - int ScopeDepth = 0; - vector ClassHashList; - vector ClassExtendedList; - vector* UnusedVariables = nullptr; -}; -#endif - #include #include #include @@ -173,7 +144,7 @@ enum FunctionType { TYPE_METHOD, }; -PUBLIC Token Compiler::MakeToken(int type) { +Token Compiler::MakeToken(int type) { Token token; token.Type = type; token.Start = scanner.Start; @@ -183,7 +154,7 @@ PUBLIC Token Compiler::MakeToken(int type) { return token; } -PUBLIC Token Compiler::MakeTokenRaw(int type, const char* message) { +Token Compiler::MakeTokenRaw(int type, const char* message) { Token token; token.Type = type; token.Start = (char*)message; @@ -193,7 +164,7 @@ PUBLIC Token Compiler::MakeTokenRaw(int type, const char* message) { return token; } -PUBLIC Token Compiler::ErrorToken(const char* message) { +Token Compiler::ErrorToken(const char* message) { Token token; token.Type = TOKEN_ERROR; token.Start = (char*)message; @@ -204,49 +175,49 @@ PUBLIC Token Compiler::ErrorToken(const char* message) { return token; } -PUBLIC bool Compiler::IsEOF() { +bool Compiler::IsEOF() { return *scanner.Current == 0; } -PUBLIC bool Compiler::IsDigit(char c) { +bool Compiler::IsDigit(char c) { return c >= '0' && c <= '9'; } -PUBLIC bool Compiler::IsHexDigit(char c) { +bool Compiler::IsHexDigit(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } -PUBLIC bool Compiler::IsAlpha(char c) { +bool Compiler::IsAlpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } -PUBLIC bool Compiler::IsIdentifierStart(char c) { +bool Compiler::IsIdentifierStart(char c) { return IsAlpha(c) || c == '$' || c == '_'; } -PUBLIC bool Compiler::IsIdentifierBody(char c) { +bool Compiler::IsIdentifierBody(char c) { return IsIdentifierStart(c) || IsDigit(c); } -PUBLIC bool Compiler::MatchChar(char expected) { +bool Compiler::MatchChar(char expected) { if (IsEOF()) return false; if (*scanner.Current != expected) return false; scanner.Current++; return true; } -PUBLIC char Compiler::AdvanceChar() { +char Compiler::AdvanceChar() { return *scanner.Current++; // scanner.Current++; // return *(scanner.Current - 1); } -PUBLIC char Compiler::PrevChar() { +char Compiler::PrevChar() { return *(scanner.Current - 1); } -PUBLIC char Compiler::PeekChar() { +char Compiler::PeekChar() { return *scanner.Current; } -PUBLIC char Compiler::PeekNextChar() { +char Compiler::PeekNextChar() { if (IsEOF()) return 0; return *(scanner.Current + 1); } -PUBLIC VIRTUAL void Compiler::SkipWhitespace() { +void Compiler::SkipWhitespace() { while (true) { char c = PeekChar(); switch (c) { @@ -302,14 +273,14 @@ PUBLIC VIRTUAL void Compiler::SkipWhitespace() { } // Token functions -PUBLIC int Compiler::CheckKeyword(int start, int length, const char* rest, int type) { +int Compiler::CheckKeyword(int start, int length, const char* rest, int type) { if (scanner.Current - scanner.Start == start + length && (!rest || memcmp(scanner.Start + start, rest, length) == 0)) return type; return TOKEN_IDENTIFIER; } -PUBLIC VIRTUAL int Compiler::GetKeywordType() { +int Compiler::GetKeywordType() { switch (*scanner.Start) { case 'a': if (scanner.Current - scanner.Start > 1) { @@ -459,7 +430,7 @@ PUBLIC VIRTUAL int Compiler::GetKeywordType() { return TOKEN_IDENTIFIER; } -PUBLIC Token Compiler::StringToken() { +Token Compiler::StringToken() { while (PeekChar() != '"' && !IsEOF()) { bool lineBreak = false; switch (PeekChar()) { @@ -487,7 +458,7 @@ PUBLIC Token Compiler::StringToken() { AdvanceChar(); return MakeToken(TOKEN_STRING); } -PUBLIC Token Compiler::NumberToken() { +Token Compiler::NumberToken() { if (*scanner.Start == '0' && (PeekChar() == 'x' || PeekChar() == 'X')) { AdvanceChar(); // x while (IsHexDigit(PeekChar())) @@ -511,13 +482,13 @@ PUBLIC Token Compiler::NumberToken() { return MakeToken(TOKEN_NUMBER); } -PUBLIC Token Compiler::IdentifierToken() { +Token Compiler::IdentifierToken() { while (IsIdentifierBody(PeekChar())) AdvanceChar(); return MakeToken(GetKeywordType()); } -PUBLIC VIRTUAL Token Compiler::ScanToken() { +Token Compiler::ScanToken() { SkipWhitespace(); scanner.Start = scanner.Current; @@ -563,7 +534,7 @@ PUBLIC VIRTUAL Token Compiler::ScanToken() { return ErrorToken("Unexpected character."); } -PUBLIC void Compiler::AdvanceToken() { +void Compiler::AdvanceToken() { parser.Previous = parser.Current; while (true) { @@ -574,14 +545,14 @@ PUBLIC void Compiler::AdvanceToken() { ErrorAtCurrent(parser.Current.Start); } } -PUBLIC Token Compiler::NextToken() { +Token Compiler::NextToken() { AdvanceToken(); return parser.Previous; } -PUBLIC Token Compiler::PeekToken() { +Token Compiler::PeekToken() { return parser.Current; } -PUBLIC Token Compiler::PeekNextToken() { +Token Compiler::PeekNextToken() { Parser previousParser = parser; Scanner previousScanner = scanner; Token next; @@ -594,15 +565,15 @@ PUBLIC Token Compiler::PeekNextToken() { return next; } -PUBLIC Token Compiler::PrevToken() { +Token Compiler::PrevToken() { return parser.Previous; } -PUBLIC bool Compiler::MatchToken(int expectedType) { +bool Compiler::MatchToken(int expectedType) { if (!CheckToken(expectedType)) return false; AdvanceToken(); return true; } -PUBLIC bool Compiler::MatchAssignmentToken() { +bool Compiler::MatchAssignmentToken() { switch (parser.Current.Type) { case TOKEN_ASSIGNMENT: case TOKEN_ASSIGNMENT_MULTIPLY: @@ -628,10 +599,10 @@ PUBLIC bool Compiler::MatchAssignmentToken() { } return false; } -PUBLIC bool Compiler::CheckToken(int expectedType) { +bool Compiler::CheckToken(int expectedType) { return parser.Current.Type == expectedType; } -PUBLIC void Compiler::ConsumeToken(int type, const char* message) { +void Compiler::ConsumeToken(int type, const char* message) { if (parser.Current.Type == type) { AdvanceToken(); return; @@ -640,7 +611,7 @@ PUBLIC void Compiler::ConsumeToken(int type, const char* message) { ErrorAtCurrent(message); } -PUBLIC void Compiler::SynchronizeToken() { +void Compiler::SynchronizeToken() { parser.PanicMode = false; while (PeekToken().Type != TOKEN_EOF) { @@ -671,7 +642,7 @@ PUBLIC void Compiler::SynchronizeToken() { } // Error handling -PUBLIC bool Compiler::ReportError(int line, bool fatal, const char* string, ...) { +bool Compiler::ReportError(int line, bool fatal, const char* string, ...) { if (!fatal && !Compiler::ShowWarnings) return true; @@ -690,7 +661,7 @@ PUBLIC bool Compiler::ReportError(int line, bool fatal, const char* str return !fatal; } -PUBLIC bool Compiler::ReportErrorPos(int line, int pos, bool fatal, const char* string, ...) { +bool Compiler::ReportErrorPos(int line, int pos, bool fatal, const char* string, ...) { if (!fatal && !Compiler::ShowWarnings) return true; @@ -742,7 +713,7 @@ PUBLIC bool Compiler::ReportErrorPos(int line, int pos, bool fatal, con return false; } -PUBLIC void Compiler::ErrorAt(Token* token, const char* message, bool fatal) { +void Compiler::ErrorAt(Token* token, const char* message, bool fatal) { if (fatal) { if (parser.PanicMode) return; @@ -759,16 +730,16 @@ PUBLIC void Compiler::ErrorAt(Token* token, const char* message, bool f if (fatal) parser.HadError = true; } -PUBLIC void Compiler::Error(const char* message) { +void Compiler::Error(const char* message) { ErrorAt(&parser.Previous, message, true); } -PUBLIC void Compiler::ErrorAtCurrent(const char* message) { +void Compiler::ErrorAtCurrent(const char* message) { ErrorAt(&parser.Current, message, true); } -PUBLIC void Compiler::Warning(const char* message) { +void Compiler::Warning(const char* message) { ErrorAt(&parser.Current, message, false); } -PUBLIC void Compiler::WarningInFunction(const char* format, ...) { +void Compiler::WarningInFunction(const char* format, ...) { if (!Compiler::ShowWarnings) return; @@ -803,19 +774,19 @@ PUBLIC void Compiler::WarningInFunction(const char* format, ...) { free(textBuffer); } -PUBLIC void Compiler::ParseVariable(const char* errorMessage) { +void Compiler::ParseVariable(const char* errorMessage) { ConsumeToken(TOKEN_IDENTIFIER, errorMessage); DeclareVariable(&parser.Previous); } -PUBLIC bool Compiler::IdentifiersEqual(Token* a, Token* b) { +bool Compiler::IdentifiersEqual(Token* a, Token* b) { if (a->Length != b->Length) return false; return memcmp(a->Start, b->Start, a->Length) == 0; } -PUBLIC void Compiler::MarkInitialized() { +void Compiler::MarkInitialized() { if (ScopeDepth == 0) return; Locals[LocalCount - 1].Depth = ScopeDepth; } -PUBLIC void Compiler::DefineVariableToken(Token global) { +void Compiler::DefineVariableToken(Token global) { if (ScopeDepth > 0) { MarkInitialized(); return; @@ -823,7 +794,7 @@ PUBLIC void Compiler::DefineVariableToken(Token global) { EmitByte(OP_DEFINE_GLOBAL); EmitStringHash(global); } -PUBLIC void Compiler::DeclareVariable(Token* name) { +void Compiler::DeclareVariable(Token* name) { if (ScopeDepth == 0) return; for (int i = LocalCount - 1; i >= 0; i--) { @@ -838,15 +809,15 @@ PUBLIC void Compiler::DeclareVariable(Token* name) { AddLocal(*name); } -PUBLIC int Compiler::ParseModuleVariable(const char* errorMessage) { +int Compiler::ParseModuleVariable(const char* errorMessage) { ConsumeToken(TOKEN_IDENTIFIER, errorMessage); return DeclareModuleVariable(&parser.Previous); } -PUBLIC void Compiler::DefineModuleVariable(int local) { +void Compiler::DefineModuleVariable(int local) { EmitByte(OP_DEFINE_MODULE_LOCAL); Compiler::ModuleLocals[local].Depth = 0; } -PUBLIC int Compiler::DeclareModuleVariable(Token* name) { +int Compiler::DeclareModuleVariable(Token* name) { for (int i = Compiler::ModuleLocals.size() - 1; i >= 0; i--) { Local& local = Compiler::ModuleLocals[i]; @@ -856,7 +827,7 @@ PUBLIC int Compiler::DeclareModuleVariable(Token* name) { return AddModuleLocal(*name); } -PRIVATE void Compiler::WarnVariablesUnused() { +void Compiler::WarnVariablesUnused() { if (!Compiler::ShowWarnings) return; @@ -878,7 +849,7 @@ PRIVATE void Compiler::WarnVariablesUnused() { WarningInFunction("%s", message.c_str()); } -PUBLIC void Compiler::EmitSetOperation(Uint8 setOp, int arg, Token name) { +void Compiler::EmitSetOperation(Uint8 setOp, int arg, Token name) { switch (setOp) { case OP_SET_GLOBAL: case OP_SET_PROPERTY: @@ -899,7 +870,7 @@ PUBLIC void Compiler::EmitSetOperation(Uint8 setOp, int arg, Token name) { break; } } -PUBLIC void Compiler::EmitGetOperation(Uint8 getOp, int arg, Token name) { +void Compiler::EmitGetOperation(Uint8 getOp, int arg, Token name) { switch (getOp) { case OP_GET_GLOBAL: case OP_GET_PROPERTY: @@ -919,7 +890,7 @@ PUBLIC void Compiler::EmitGetOperation(Uint8 getOp, int arg, Token name) { break; } } -PUBLIC void Compiler::EmitAssignmentToken(Token assignmentToken) { +void Compiler::EmitAssignmentToken(Token assignmentToken) { switch (assignmentToken.Type) { case TOKEN_ASSIGNMENT_PLUS: EmitByte(OP_ADD); @@ -962,23 +933,23 @@ PUBLIC void Compiler::EmitAssignmentToken(Token assignmentToken) { break; } } -PUBLIC void Compiler::EmitCopy(Uint8 count) { +void Compiler::EmitCopy(Uint8 count) { EmitByte(OP_COPY); EmitByte(count); } -PUBLIC void Compiler::EmitCall(const char *name, int argCount, bool isSuper) { +void Compiler::EmitCall(const char *name, int argCount, bool isSuper) { EmitBytes(OP_INVOKE, argCount); EmitStringHash(name); EmitByte(isSuper ? 1 : 0); } -PUBLIC void Compiler::EmitCall(Token name, int argCount, bool isSuper) { +void Compiler::EmitCall(Token name, int argCount, bool isSuper) { EmitBytes(OP_INVOKE, argCount); EmitStringHash(name); EmitByte(isSuper ? 1 : 0); } -PUBLIC void Compiler::NamedVariable(Token name, bool canAssign) { +void Compiler::NamedVariable(Token name, bool canAssign) { Uint8 getOp, setOp; int arg = ResolveLocal(&name); @@ -1028,14 +999,14 @@ PUBLIC void Compiler::NamedVariable(Token name, bool canAssign) { EmitGetOperation(getOp, arg, name); } } -PUBLIC void Compiler::ScopeBegin() { +void Compiler::ScopeBegin() { ScopeDepth++; } -PUBLIC void Compiler::ScopeEnd() { +void Compiler::ScopeEnd() { ScopeDepth--; ClearToScope(ScopeDepth); } -PUBLIC void Compiler::ClearToScope(int depth) { +void Compiler::ClearToScope(int depth) { int popCount = 0; while (LocalCount > 0 && Locals[LocalCount - 1].Depth > depth) { if (!Locals[LocalCount - 1].Resolved) @@ -1047,7 +1018,7 @@ PUBLIC void Compiler::ClearToScope(int depth) { } PopMultiple(popCount); } -PUBLIC void Compiler::PopToScope(int depth) { +void Compiler::PopToScope(int depth) { int lcl = LocalCount; int popCount = 0; while (lcl > 0 && Locals[lcl - 1].Depth > depth) { @@ -1056,7 +1027,7 @@ PUBLIC void Compiler::PopToScope(int depth) { } PopMultiple(popCount); } -PUBLIC void Compiler::PopMultiple(int count) { +void Compiler::PopMultiple(int count) { if (count == 1) { EmitByte(OP_POP); return; @@ -1070,7 +1041,7 @@ PUBLIC void Compiler::PopMultiple(int count) { count -= max; } } -PUBLIC int Compiler::AddLocal(Token name) { +int Compiler::AddLocal(Token name) { if (LocalCount == 0xFF) { Error("Too many local variables in function."); return -1; @@ -1081,7 +1052,7 @@ PUBLIC int Compiler::AddLocal(Token name) { local->Resolved = false; return LocalCount - 1; } -PUBLIC int Compiler::AddLocal(const char* name, size_t len) { +int Compiler::AddLocal(const char* name, size_t len) { if (LocalCount == 0xFF) { Error("Too many local variables in function."); return -1; @@ -1092,24 +1063,24 @@ PUBLIC int Compiler::AddLocal(const char* name, size_t len) { RenameLocal(local, name, len); return LocalCount - 1; } -PUBLIC int Compiler::AddHiddenLocal(const char* name, size_t len) { +int Compiler::AddHiddenLocal(const char* name, size_t len) { int local = AddLocal(name, len); Locals[local].Resolved = true; MarkInitialized(); return local; } -PUBLIC void Compiler::RenameLocal(Local* local, const char* name, size_t len) { +void Compiler::RenameLocal(Local* local, const char* name, size_t len) { local->Name.Start = (char*)name; local->Name.Length = len; } -PUBLIC void Compiler::RenameLocal(Local* local, const char* name) { +void Compiler::RenameLocal(Local* local, const char* name) { local->Name.Start = (char*)name; local->Name.Length = strlen(name); } -PUBLIC void Compiler::RenameLocal(Local* local, Token name) { +void Compiler::RenameLocal(Local* local, Token name) { local->Name = name; } -PUBLIC int Compiler::ResolveLocal(Token* name) { +int Compiler::ResolveLocal(Token* name) { for (int i = LocalCount - 1; i >= 0; i--) { Local* local = &Locals[i]; if (IdentifiersEqual(name, &local->Name)) { @@ -1122,7 +1093,7 @@ PUBLIC int Compiler::ResolveLocal(Token* name) { } return -1; } -PUBLIC int Compiler::AddModuleLocal(Token name) { +int Compiler::AddModuleLocal(Token name) { if (Compiler::ModuleLocals.size() == 0xFFFF) { Error("Too many locals in module."); return -1; @@ -1134,7 +1105,7 @@ PUBLIC int Compiler::AddModuleLocal(Token name) { Compiler::ModuleLocals.push_back(local); return ((int)Compiler::ModuleLocals.size()) - 1; } -PUBLIC int Compiler::ResolveModuleLocal(Token* name) { +int Compiler::ResolveModuleLocal(Token* name) { for (int i = Compiler::ModuleLocals.size() - 1; i >= 0; i--) { Local& local = Compiler::ModuleLocals[i]; if (IdentifiersEqual(name, &local.Name)) { @@ -1147,7 +1118,7 @@ PUBLIC int Compiler::ResolveModuleLocal(Token* name) { } return -1; } -PUBLIC Uint8 Compiler::GetArgumentList() { +Uint8 Compiler::GetArgumentList() { Uint8 argumentCount = 0; if (!CheckToken(TOKEN_RIGHT_PAREN)) { do { @@ -1165,17 +1136,17 @@ PUBLIC Uint8 Compiler::GetArgumentList() { } Token InstanceToken = Token { 0, NULL, 0, 0, 0 }; -PUBLIC void Compiler::GetThis(bool canAssign) { +void Compiler::GetThis(bool canAssign) { InstanceToken = parser.Previous; GetVariable(false); } -PUBLIC void Compiler::GetSuper(bool canAssign) { +void Compiler::GetSuper(bool canAssign) { InstanceToken = parser.Previous; if (!CheckToken(TOKEN_DOT)) Error("Expect '.' after 'super'."); EmitBytes(OP_GET_LOCAL, 0); } -PUBLIC void Compiler::GetDot(bool canAssign) { +void Compiler::GetDot(bool canAssign) { bool isSuper = InstanceToken.Type == TOKEN_SUPER; InstanceToken.Type = -1; @@ -1227,7 +1198,7 @@ PUBLIC void Compiler::GetDot(bool canAssign) { EmitGetOperation(OP_GET_PROPERTY, -1, nameToken); } } -PUBLIC void Compiler::GetElement(bool canAssign) { +void Compiler::GetElement(bool canAssign) { Token blank; memset(&blank, 0, sizeof(blank)); GetExpression(); @@ -1271,11 +1242,11 @@ PUBLIC void Compiler::GetElement(bool canAssign) { // Reading expressions bool negateConstant = false; -PUBLIC void Compiler::GetGrouping(bool canAssign) { +void Compiler::GetGrouping(bool canAssign) { GetExpression(); ConsumeToken(TOKEN_RIGHT_PAREN, "Expected \")\" after expression."); } -PUBLIC void Compiler::GetLiteral(bool canAssign) { +void Compiler::GetLiteral(bool canAssign) { switch (parser.Previous.Type) { case TOKEN_NULL: EmitByte(OP_NULL); break; case TOKEN_TRUE: EmitByte(OP_TRUE); break; @@ -1284,7 +1255,7 @@ PUBLIC void Compiler::GetLiteral(bool canAssign) { return; // Unreachable. } } -PUBLIC void Compiler::GetInteger(bool canAssign) { +void Compiler::GetInteger(bool canAssign) { int value = 0; char* start = parser.Previous.Start; if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X')) @@ -1298,7 +1269,7 @@ PUBLIC void Compiler::GetInteger(bool canAssign) { EmitConstant(INTEGER_VAL(value)); } -PUBLIC void Compiler::GetDecimal(bool canAssign) { +void Compiler::GetDecimal(bool canAssign) { float value = 0; value = (float)atof(parser.Previous.Start); @@ -1308,7 +1279,7 @@ PUBLIC void Compiler::GetDecimal(bool canAssign) { EmitConstant(DECIMAL_VAL(value)); } -PUBLIC ObjString* Compiler::MakeString(Token token) { +ObjString* Compiler::MakeString(Token token) { ObjString* string = CopyString(token.Start + 1, token.Length - 2); // Escape the string @@ -1347,11 +1318,11 @@ PUBLIC ObjString* Compiler::MakeString(Token token) { return string; } -PUBLIC void Compiler::GetString(bool canAssign) { +void Compiler::GetString(bool canAssign) { ObjString* string = Compiler::MakeString(parser.Previous); EmitConstant(OBJECT_VAL(string)); } -PUBLIC void Compiler::GetArray(bool canAssign) { +void Compiler::GetArray(bool canAssign) { Uint32 count = 0; while (!MatchToken(TOKEN_RIGHT_SQUARE_BRACE)) { @@ -1367,7 +1338,7 @@ PUBLIC void Compiler::GetArray(bool canAssign) { EmitByte(OP_NEW_ARRAY); EmitUint32(count); } -PUBLIC void Compiler::GetMap(bool canAssign) { +void Compiler::GetMap(bool canAssign) { Uint32 count = 0; while (!MatchToken(TOKEN_RIGHT_BRACE)) { @@ -1387,7 +1358,7 @@ PUBLIC void Compiler::GetMap(bool canAssign) { EmitByte(OP_NEW_MAP); EmitUint32(count); } -PUBLIC bool Compiler::IsConstant() { +bool Compiler::IsConstant() { switch (PeekToken().Type) { case TOKEN_NULL: case TOKEN_TRUE: @@ -1414,7 +1385,7 @@ PUBLIC bool Compiler::IsConstant() { return false; } } -PUBLIC void Compiler::GetConstant(bool canAssign) { +void Compiler::GetConstant(bool canAssign) { switch (NextToken().Type) { case TOKEN_NULL: case TOKEN_TRUE: @@ -1450,7 +1421,7 @@ PUBLIC void Compiler::GetConstant(bool canAssign) { break; } } -PUBLIC int Compiler::GetConstantValue() { +int Compiler::GetConstantValue() { int position, constant_index; position = CodePointer(); GetConstant(false); @@ -1458,10 +1429,10 @@ PUBLIC int Compiler::GetConstantValue() { CurrentChunk()->Count = position; return constant_index; } -PUBLIC void Compiler::GetVariable(bool canAssign) { +void Compiler::GetVariable(bool canAssign) { NamedVariable(parser.Previous, canAssign); } -PUBLIC void Compiler::GetLogicalAND(bool canAssign) { +void Compiler::GetLogicalAND(bool canAssign) { int endJump = EmitJump(OP_JUMP_IF_FALSE); EmitByte(OP_POP); @@ -1469,7 +1440,7 @@ PUBLIC void Compiler::GetLogicalAND(bool canAssign) { PatchJump(endJump); } -PUBLIC void Compiler::GetLogicalOR(bool canAssign) { +void Compiler::GetLogicalOR(bool canAssign) { int elseJump = EmitJump(OP_JUMP_IF_FALSE); int endJump = EmitJump(OP_JUMP); @@ -1479,7 +1450,7 @@ PUBLIC void Compiler::GetLogicalOR(bool canAssign) { ParsePrecedence(PREC_OR); PatchJump(endJump); } -PUBLIC void Compiler::GetConditional(bool canAssign) { +void Compiler::GetConditional(bool canAssign) { int thenJump = EmitJump(OP_JUMP_IF_FALSE); EmitByte(OP_POP); ParsePrecedence(PREC_TERNARY); @@ -1492,7 +1463,7 @@ PUBLIC void Compiler::GetConditional(bool canAssign) { ParsePrecedence(PREC_TERNARY); PatchJump(elseJump); } -PUBLIC void Compiler::GetUnary(bool canAssign) { +void Compiler::GetUnary(bool canAssign) { int operatorType = parser.Previous.Type; ParsePrecedence(PREC_UNARY); @@ -1510,7 +1481,7 @@ PUBLIC void Compiler::GetUnary(bool canAssign) { return; // Unreachable. } } -PUBLIC void Compiler::GetNew(bool canAssign) { +void Compiler::GetNew(bool canAssign) { ConsumeToken(TOKEN_IDENTIFIER, "Expect class name."); NamedVariable(parser.Previous, false); @@ -1519,7 +1490,7 @@ PUBLIC void Compiler::GetNew(bool canAssign) { argCount = GetArgumentList(); EmitBytes(OP_NEW, argCount); } -PUBLIC void Compiler::GetBinary(bool canAssign) { +void Compiler::GetBinary(bool canAssign) { Token operato = parser.Previous; int operatorType = operato.Type; @@ -1554,20 +1525,20 @@ PUBLIC void Compiler::GetBinary(bool canAssign) { return; // Unreachable. } } -PUBLIC void Compiler::GetHas(bool canAssign) { +void Compiler::GetHas(bool canAssign) { ConsumeToken(TOKEN_IDENTIFIER, "Expect property name."); EmitByte(OP_HAS_PROPERTY); EmitStringHash(parser.Previous); } -PUBLIC void Compiler::GetSuffix(bool canAssign) { +void Compiler::GetSuffix(bool canAssign) { } -PUBLIC void Compiler::GetCall(bool canAssign) { +void Compiler::GetCall(bool canAssign) { Uint8 argCount = GetArgumentList(); EmitByte(OP_CALL); EmitByte(argCount); } -PUBLIC void Compiler::GetExpression() { +void Compiler::GetExpression() { ParsePrecedence(PREC_ASSIGNMENT); } // Reading statements @@ -1585,17 +1556,17 @@ stack*> SwitchJumpListStack; stack BreakScopeStack; stack ContinueScopeStack; stack SwitchScopeStack; -PUBLIC void Compiler::GetPrintStatement() { +void Compiler::GetPrintStatement() { GetExpression(); ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after value."); EmitByte(OP_PRINT); } -PUBLIC void Compiler::GetExpressionStatement() { +void Compiler::GetExpressionStatement() { GetExpression(); EmitByte(OP_POP); ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after expression."); } -PUBLIC void Compiler::GetContinueStatement() { +void Compiler::GetContinueStatement() { if (ContinueJumpListStack.size() == 0) { Error("Can't continue outside of loop."); } @@ -1607,7 +1578,7 @@ PUBLIC void Compiler::GetContinueStatement() { ConsumeToken(TOKEN_SEMICOLON, "Expect ';' after continue."); } -PUBLIC void Compiler::GetDoWhileStatement() { +void Compiler::GetDoWhileStatement() { // Set the start of the loop to before the condition int loopStart = CodePointer(); @@ -1648,7 +1619,7 @@ PUBLIC void Compiler::GetDoWhileStatement() { // Pop jump list off break stack, patch all breaks to this code point EndBreakJumpList(); } -PUBLIC void Compiler::GetReturnStatement() { +void Compiler::GetReturnStatement() { if (Type == TYPE_TOP_LEVEL) { Error("Cannot return from top-level code."); } @@ -1666,7 +1637,7 @@ PUBLIC void Compiler::GetReturnStatement() { EmitByte(OP_RETURN); } } -PUBLIC void Compiler::GetRepeatStatement() { +void Compiler::GetRepeatStatement() { ConsumeToken(TOKEN_LEFT_PAREN, "Expect '(' after 'repeat'."); GetExpression(); ConsumeToken(TOKEN_RIGHT_PAREN, "Expect ')' after condition."); @@ -1689,7 +1660,7 @@ PUBLIC void Compiler::GetRepeatStatement() { EndBreakJumpList(); } -PUBLIC void Compiler::GetSwitchStatement() { +void Compiler::GetSwitchStatement() { Chunk* chunk = CurrentChunk(); StartBreakJumpList(); @@ -1795,7 +1766,7 @@ PUBLIC void Compiler::GetSwitchStatement() { // Pop jump list off break stack, patch all breaks to this code point EndBreakJumpList(); } -PUBLIC void Compiler::GetCaseStatement() { +void Compiler::GetCaseStatement() { if (SwitchJumpListStack.size() == 0) { Error("Cannot use case label outside of switch statement."); } @@ -1830,7 +1801,7 @@ PUBLIC void Compiler::GetCaseStatement() { SwitchJumpListStack.top()->push_back(case_info); } -PUBLIC void Compiler::GetDefaultStatement() { +void Compiler::GetDefaultStatement() { if (SwitchJumpListStack.size() == 0) { Error("Cannot use default label outside of switch statement."); } @@ -1843,7 +1814,7 @@ PUBLIC void Compiler::GetDefaultStatement() { SwitchJumpListStack.top()->push_back(case_info); } -PUBLIC void Compiler::GetWhileStatement() { +void Compiler::GetWhileStatement() { // Set the start of the loop to before the condition int loopStart = CodePointer(); @@ -1882,7 +1853,7 @@ PUBLIC void Compiler::GetWhileStatement() { // Pop jump list off break stack, patch all breaks to this code point EndBreakJumpList(); } -PUBLIC void Compiler::GetBreakStatement() { +void Compiler::GetBreakStatement() { if (BreakJumpListStack.size() == 0) { Error("Cannot break outside of loop or switch statement."); } @@ -1894,14 +1865,14 @@ PUBLIC void Compiler::GetBreakStatement() { ConsumeToken(TOKEN_SEMICOLON, "Expect ';' after break."); } -PUBLIC void Compiler::GetBlockStatement() { +void Compiler::GetBlockStatement() { while (!CheckToken(TOKEN_RIGHT_BRACE) && !CheckToken(TOKEN_EOF)) { GetDeclaration(); } ConsumeToken(TOKEN_RIGHT_BRACE, "Expected \"}\" after block."); } -PUBLIC void Compiler::GetWithStatement() { +void Compiler::GetWithStatement() { enum { WITH_STATE_INIT, WITH_STATE_ITERATE, @@ -2015,7 +1986,7 @@ PUBLIC void Compiler::GetWithStatement() { // End scope (will pop "other") ScopeEnd(); } -PUBLIC void Compiler::GetForStatement() { +void Compiler::GetForStatement() { // Start new scope ScopeBegin(); @@ -2085,7 +2056,7 @@ PUBLIC void Compiler::GetForStatement() { // End new scope ScopeEnd(); } -PUBLIC void Compiler::GetForEachStatement() { +void Compiler::GetForEachStatement() { // Start new scope ScopeBegin(); @@ -2171,7 +2142,7 @@ PUBLIC void Compiler::GetForEachStatement() { // End new scope ScopeEnd(); } -PUBLIC void Compiler::GetIfStatement() { +void Compiler::GetIfStatement() { ConsumeToken(TOKEN_LEFT_PAREN, "Expect '(' after 'if'."); GetExpression(); ConsumeToken(TOKEN_RIGHT_PAREN, "Expect ')' after condition."); @@ -2189,7 +2160,7 @@ PUBLIC void Compiler::GetIfStatement() { PatchJump(elseJump); } -PUBLIC void Compiler::GetStatement() { +void Compiler::GetStatement() { if (MatchToken(TOKEN_PRINT)) { GetPrintStatement(); } @@ -2242,7 +2213,7 @@ PUBLIC void Compiler::GetStatement() { } } // Reading declarations -PUBLIC int Compiler::GetFunction(int type, string className) { +int Compiler::GetFunction(int type, string className) { int index = (int)Compiler::Functions.size(); Compiler* compiler = new Compiler; @@ -2287,10 +2258,10 @@ PUBLIC int Compiler::GetFunction(int type, string className) { return index; } -PUBLIC int Compiler::GetFunction(int type) { +int Compiler::GetFunction(int type) { return GetFunction(type, ""); } -PUBLIC void Compiler::GetMethod(Token className) { +void Compiler::GetMethod(Token className) { ConsumeToken(TOKEN_IDENTIFIER, "Expect method name."); Token constantToken = parser.Previous; @@ -2305,7 +2276,7 @@ PUBLIC void Compiler::GetMethod(Token className) { EmitByte(index); EmitStringHash(constantToken); } -PUBLIC void Compiler::GetVariableDeclaration() { +void Compiler::GetVariableDeclaration() { if (SwitchScopeStack.size() != 0) { if (SwitchScopeStack.top() == ScopeDepth) Error("Cannot initialize variable inside switch statement."); @@ -2329,7 +2300,7 @@ PUBLIC void Compiler::GetVariableDeclaration() { ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after variable declaration."); } -PUBLIC void Compiler::GetModuleVariableDeclaration() { +void Compiler::GetModuleVariableDeclaration() { ConsumeToken(TOKEN_VAR, "Expected \"var\" after \"local\" declaration."); if (ScopeDepth > 0) { @@ -2352,7 +2323,7 @@ PUBLIC void Compiler::GetModuleVariableDeclaration() { ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after variable declaration."); } -PUBLIC void Compiler::GetPropertyDeclaration(Token propertyName) { +void Compiler::GetPropertyDeclaration(Token propertyName) { do { ParseVariable("Expected property name."); @@ -2375,7 +2346,7 @@ PUBLIC void Compiler::GetPropertyDeclaration(Token propertyName) { ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after property declaration."); } -PUBLIC void Compiler::GetClassDeclaration() { +void Compiler::GetClassDeclaration() { ConsumeToken(TOKEN_IDENTIFIER, "Expect class name."); Token className = parser.Previous; @@ -2424,7 +2395,7 @@ PUBLIC void Compiler::GetClassDeclaration() { ConsumeToken(TOKEN_RIGHT_BRACE, "Expect '}' after class body."); } -PUBLIC void Compiler::GetEnumDeclaration() { +void Compiler::GetEnumDeclaration() { Token enumName; bool isNamed = false; @@ -2487,7 +2458,7 @@ PUBLIC void Compiler::GetEnumDeclaration() { ConsumeToken(TOKEN_RIGHT_BRACE, "Expect '}' after enum body."); } -PUBLIC void Compiler::GetImportDeclaration() { +void Compiler::GetImportDeclaration() { bool importModules = MatchToken(TOKEN_FROM); do { @@ -2503,7 +2474,7 @@ PUBLIC void Compiler::GetImportDeclaration() { ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after \"import\" declaration."); } -PUBLIC void Compiler::GetUsingDeclaration() { +void Compiler::GetUsingDeclaration() { ConsumeToken(TOKEN_NAMESPACE, "Expected \"namespace\" after \"using\" declaration."); if (ScopeDepth > 0) { @@ -2520,7 +2491,7 @@ PUBLIC void Compiler::GetUsingDeclaration() { ConsumeToken(TOKEN_SEMICOLON, "Expected \";\" after \"using\" declaration."); } -PUBLIC void Compiler::GetEventDeclaration() { +void Compiler::GetEventDeclaration() { ConsumeToken(TOKEN_IDENTIFIER, "Expected event name."); Token constantToken = parser.Previous; @@ -2542,7 +2513,7 @@ PUBLIC void Compiler::GetEventDeclaration() { EmitStringHash(constantToken); // } } -PUBLIC void Compiler::GetDeclaration() { +void Compiler::GetDeclaration() { if (MatchToken(TOKEN_CLASS)) GetClassDeclaration(); else if (MatchToken(TOKEN_ENUM)) @@ -2563,7 +2534,7 @@ PUBLIC void Compiler::GetDeclaration() { if (parser.PanicMode) SynchronizeToken(); } -PUBLIC STATIC void Compiler::MakeRules() { +void Compiler::MakeRules() { Rules = (ParseRule*)Memory::TrackedCalloc("Compiler::Rules", TOKEN_EOF + 1, sizeof(ParseRule)); // Single-character tokens. Rules[TOKEN_LEFT_PAREN] = ParseRule { &Compiler::GetGrouping, &Compiler::GetCall, NULL, PREC_CALL }; @@ -2627,11 +2598,11 @@ PUBLIC STATIC void Compiler::MakeRules() { Rules[TOKEN_DECIMAL] = ParseRule { &Compiler::GetDecimal, NULL, NULL, PREC_NONE }; Rules[TOKEN_IDENTIFIER] = ParseRule { &Compiler::GetVariable, NULL, NULL, PREC_NONE }; } -PUBLIC ParseRule* Compiler::GetRule(int type) { +ParseRule* Compiler::GetRule(int type) { return &Compiler::Rules[(int)type]; } -PUBLIC void Compiler::ParsePrecedence(Precedence precedence) { +void Compiler::ParsePrecedence(Precedence precedence) { AdvanceToken(); ParseFn prefixRule = GetRule(parser.Previous.Type)->Prefix; if (prefixRule == NULL) { @@ -2654,43 +2625,43 @@ PUBLIC void Compiler::ParsePrecedence(Precedence precedence) { GetExpression(); } } -PUBLIC Uint32 Compiler::GetHash(char* string) { +Uint32 Compiler::GetHash(char* string) { return Murmur::EncryptString(string); } -PUBLIC Uint32 Compiler::GetHash(Token token) { +Uint32 Compiler::GetHash(Token token) { return Murmur::EncryptData(token.Start, token.Length); } -PUBLIC Chunk* Compiler::CurrentChunk() { +Chunk* Compiler::CurrentChunk() { return &Function->Chunk; } -PUBLIC int Compiler::CodePointer() { +int Compiler::CodePointer() { return CurrentChunk()->Count; } -PUBLIC void Compiler::EmitByte(Uint8 byte) { +void Compiler::EmitByte(Uint8 byte) { CurrentChunk()->Write(byte, (int)((parser.Previous.Pos & 0xFFFF) << 16 | (parser.Previous.Line & 0xFFFF))); } -PUBLIC void Compiler::EmitBytes(Uint8 byte1, Uint8 byte2) { +void Compiler::EmitBytes(Uint8 byte1, Uint8 byte2) { EmitByte(byte1); EmitByte(byte2); } -PUBLIC void Compiler::EmitUint16(Uint16 value) { +void Compiler::EmitUint16(Uint16 value) { EmitByte(value & 0xFF); EmitByte(value >> 8 & 0xFF); } -PUBLIC void Compiler::EmitUint32(Uint32 value) { +void Compiler::EmitUint32(Uint32 value) { EmitByte(value & 0xFF); EmitByte(value >> 8 & 0xFF); EmitByte(value >> 16 & 0xFF); EmitByte(value >> 24 & 0xFF); } -PUBLIC int Compiler::GetConstantIndex(VMValue value) { +int Compiler::GetConstantIndex(VMValue value) { int index = FindConstant(value); if (index < 0) index = MakeConstant(value); return index; } -PUBLIC int Compiler::EmitConstant(VMValue value) { +int Compiler::EmitConstant(VMValue value) { int index = GetConstantIndex(value); EmitByte(OP_CONSTANT); @@ -2698,7 +2669,7 @@ PUBLIC int Compiler::EmitConstant(VMValue value) { return index; } -PUBLIC void Compiler::EmitLoop(int loopStart) { +void Compiler::EmitLoop(int loopStart) { EmitByte(OP_JUMP_BACK); int offset = CurrentChunk()->Count - loopStart + 2; @@ -2707,7 +2678,7 @@ PUBLIC void Compiler::EmitLoop(int loopStart) { EmitByte(offset & 0xFF); EmitByte((offset >> 8) & 0xFF); } -PUBLIC int Compiler::GetJump(int offset) { +int Compiler::GetJump(int offset) { int jump = CurrentChunk()->Count - (offset + 2); if (jump > UINT16_MAX) { Error("Too much code to jump over."); @@ -2715,26 +2686,26 @@ PUBLIC int Compiler::GetJump(int offset) { return jump; } -PUBLIC int Compiler::GetPosition() { +int Compiler::GetPosition() { return CurrentChunk()->Count; } -PUBLIC int Compiler::EmitJump(Uint8 instruction) { +int Compiler::EmitJump(Uint8 instruction) { return EmitJump(instruction, 0xFFFF); } -PUBLIC int Compiler::EmitJump(Uint8 instruction, int jump) { +int Compiler::EmitJump(Uint8 instruction, int jump) { EmitByte(instruction); EmitUint16(jump); return CurrentChunk()->Count - 2; } -PUBLIC void Compiler::PatchJump(int offset, int jump) { +void Compiler::PatchJump(int offset, int jump) { CurrentChunk()->Code[offset] = jump & 0xFF; CurrentChunk()->Code[offset + 1] = (jump >> 8) & 0xFF; } -PUBLIC void Compiler::PatchJump(int offset) { +void Compiler::PatchJump(int offset) { int jump = GetJump(offset); PatchJump(offset, jump); } -PUBLIC void Compiler::EmitStringHash(const char* string) { +void Compiler::EmitStringHash(const char* string) { Uint32 hash = GetHash((char*)string); if (!TokenMap->Exists(hash)) { Token tk; @@ -2744,12 +2715,12 @@ PUBLIC void Compiler::EmitStringHash(const char* string) { } EmitUint32(hash); } -PUBLIC void Compiler::EmitStringHash(Token token) { +void Compiler::EmitStringHash(Token token) { if (!TokenMap->Exists(GetHash(token))) TokenMap->Put(GetHash(token), token); EmitUint32(GetHash(token)); } -PUBLIC void Compiler::EmitReturn() { +void Compiler::EmitReturn() { if (Type == TYPE_CONSTRUCTOR) { EmitBytes(OP_GET_LOCAL, 0); // return the new instance built from the constructor } @@ -2760,11 +2731,11 @@ PUBLIC void Compiler::EmitReturn() { } // Advanced Jumping -PUBLIC void Compiler::StartBreakJumpList() { +void Compiler::StartBreakJumpList() { BreakJumpListStack.push(new vector()); BreakScopeStack.push(ScopeDepth); } -PUBLIC void Compiler::EndBreakJumpList() { +void Compiler::EndBreakJumpList() { vector* top = BreakJumpListStack.top(); for (size_t i = 0; i < top->size(); i++) { int offset = (*top)[i]; @@ -2774,11 +2745,11 @@ PUBLIC void Compiler::EndBreakJumpList() { BreakJumpListStack.pop(); BreakScopeStack.pop(); } -PUBLIC void Compiler::StartContinueJumpList() { +void Compiler::StartContinueJumpList() { ContinueJumpListStack.push(new vector()); ContinueScopeStack.push(ScopeDepth); } -PUBLIC void Compiler::EndContinueJumpList() { +void Compiler::EndContinueJumpList() { vector* top = ContinueJumpListStack.top(); for (size_t i = 0; i < top->size(); i++) { int offset = (*top)[i]; @@ -2788,11 +2759,11 @@ PUBLIC void Compiler::EndContinueJumpList() { ContinueJumpListStack.pop(); ContinueScopeStack.pop(); } -PUBLIC void Compiler::StartSwitchJumpList() { +void Compiler::StartSwitchJumpList() { SwitchJumpListStack.push(new vector()); SwitchScopeStack.push(ScopeDepth + 1); } -PUBLIC void Compiler::EndSwitchJumpList() { +void Compiler::EndSwitchJumpList() { vector* top = SwitchJumpListStack.top(); for (size_t i = 0; i < top->size(); i++) { if (!(*top)[i].IsDefault) { @@ -2805,14 +2776,14 @@ PUBLIC void Compiler::EndSwitchJumpList() { SwitchScopeStack.pop(); } -PUBLIC int Compiler::FindConstant(VMValue value) { +int Compiler::FindConstant(VMValue value) { for (size_t i = 0; i < CurrentChunk()->Constants->size(); i++) { if (ValuesEqual(value, (*CurrentChunk()->Constants)[i])) return (int)i; } return -1; } -PUBLIC int Compiler::MakeConstant(VMValue value) { +int Compiler::MakeConstant(VMValue value) { int constant = CurrentChunk()->AddConstant(value); // if (constant > UINT8_MAX) { // Error("Too many constants in one chunk."); @@ -2821,7 +2792,7 @@ PUBLIC int Compiler::MakeConstant(VMValue value) { return constant; } -PUBLIC bool Compiler::HasThis() { +bool Compiler::HasThis() { switch (Type) { case TYPE_CONSTRUCTOR: case TYPE_METHOD: @@ -2830,18 +2801,18 @@ PUBLIC bool Compiler::HasThis() { return false; } } -PUBLIC void Compiler::SetReceiverName(const char *name) { +void Compiler::SetReceiverName(const char *name) { Local* local = &Locals[0]; local->Name.Start = (char*)name; local->Name.Length = strlen(name); } -PUBLIC void Compiler::SetReceiverName(Token name) { +void Compiler::SetReceiverName(Token name) { Local* local = &Locals[0]; local->Name = name; } // Debugging functions -PUBLIC STATIC int Compiler::HashInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::HashInstruction(const char* name, Chunk* chunk, int offset) { uint32_t hash = *(uint32_t*)&chunk->Code[offset + 1]; printf("%-16s #%08X", name, hash); if (TokenMap->Exists(hash)) { @@ -2851,22 +2822,22 @@ PUBLIC STATIC int Compiler::HashInstruction(const char* name, Chunk* chunk, i printf("\n"); return offset + 5; } -PUBLIC STATIC int Compiler::ConstantInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::ConstantInstruction(const char* name, Chunk* chunk, int offset) { int constant = *(int*)&chunk->Code[offset + 1]; printf("%-16s %9d '", name, constant); Values::PrintValue(NULL, (*chunk->Constants)[constant]); printf("'\n"); return offset + 5; } -PUBLIC STATIC int Compiler::SimpleInstruction(const char* name, int offset) { +int Compiler::SimpleInstruction(const char* name, int offset) { printf("%s\n", name); return offset + 1; } -PUBLIC STATIC int Compiler::ByteInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::ByteInstruction(const char* name, Chunk* chunk, int offset) { printf("%-16s %9d\n", name, chunk->Code[offset + 1]); return offset + 2; } -PUBLIC STATIC int Compiler::LocalInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::LocalInstruction(const char* name, Chunk* chunk, int offset) { uint8_t slot = chunk->Code[offset + 1]; if (slot > 0) printf("%-16s %9d\n", name, slot); @@ -2874,7 +2845,7 @@ PUBLIC STATIC int Compiler::LocalInstruction(const char* name, Chunk* chunk, printf("%-16s %9d 'this'\n", name, slot); return offset + 2; } -PUBLIC STATIC int Compiler::MethodInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::MethodInstruction(const char* name, Chunk* chunk, int offset) { uint8_t slot = chunk->Code[offset + 1]; uint32_t hash = *(uint32_t*)&chunk->Code[offset + 2]; printf("%-13s %2d", name, slot); @@ -2887,22 +2858,22 @@ PUBLIC STATIC int Compiler::MethodInstruction(const char* name, Chunk* chunk, printf("\n"); return offset + 6; } -PUBLIC STATIC int Compiler::InvokeInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::InvokeInstruction(const char* name, Chunk* chunk, int offset) { return Compiler::MethodInstruction(name, chunk, offset) + 1; } -PUBLIC STATIC int Compiler::JumpInstruction(const char* name, int sign, Chunk* chunk, int offset) { +int Compiler::JumpInstruction(const char* name, int sign, Chunk* chunk, int offset) { uint16_t jump = (uint16_t)(chunk->Code[offset + 1]); jump |= chunk->Code[offset + 2] << 8; printf("%-16s %9d -> %d\n", name, offset, offset + 3 + sign * jump); return offset + 3; } -PUBLIC STATIC int Compiler::ClassInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::ClassInstruction(const char* name, Chunk* chunk, int offset) { return Compiler::HashInstruction(name, chunk, offset) + 1; } -PUBLIC STATIC int Compiler::EnumInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::EnumInstruction(const char* name, Chunk* chunk, int offset) { return Compiler::HashInstruction(name, chunk, offset); } -PUBLIC STATIC int Compiler::WithInstruction(const char* name, Chunk* chunk, int offset) { +int Compiler::WithInstruction(const char* name, Chunk* chunk, int offset) { uint8_t slot = chunk->Code[offset + 1]; if (slot == 0) { printf("%-16s %9d\n", name, slot); @@ -2913,7 +2884,7 @@ PUBLIC STATIC int Compiler::WithInstruction(const char* name, Chunk* chunk, i printf("%-16s %9d -> %d\n", name, slot, jump); return offset + 4; } -PUBLIC STATIC int Compiler::DebugInstruction(Chunk* chunk, int offset) { +int Compiler::DebugInstruction(Chunk* chunk, int offset) { printf("%04d ", offset); if (offset > 0 && (chunk->Lines[offset] & 0xFFFF) == (chunk->Lines[offset - 1] & 0xFFFF)) { printf(" | "); @@ -3069,7 +3040,7 @@ PUBLIC STATIC int Compiler::DebugInstruction(Chunk* chunk, int offset) { return chunk->Count + 1; } } -PUBLIC STATIC void Compiler::DebugChunk(Chunk* chunk, const char* name, int minArity, int maxArity) { +void Compiler::DebugChunk(Chunk* chunk, const char* name, int minArity, int maxArity) { int optArgCount = maxArity - minArity; if (optArgCount) printf("== %s (argCount: %d, optArgCount: %d) ==\n", name, maxArity, optArgCount); @@ -3089,19 +3060,19 @@ PUBLIC STATIC void Compiler::DebugChunk(Chunk* chunk, const char* name, int mi } // Compiling -PUBLIC STATIC void Compiler::Init() { +void Compiler::Init() { Compiler::MakeRules(); Compiler::ShowWarnings = false; Compiler::WriteDebugInfo = true; Compiler::WriteSourceFilename = true; } -PUBLIC STATIC void Compiler::PrepareCompiling() { +void Compiler::PrepareCompiling() { if (Compiler::TokenMap == NULL) { Compiler::TokenMap = new HashMap(NULL, 8); } } -PUBLIC void Compiler::Initialize(Compiler* enclosing, int scope, int type) { +void Compiler::Initialize(Compiler* enclosing, int scope, int type) { Type = type; LocalCount = 0; ScopeDepth = scope; @@ -3134,7 +3105,7 @@ PUBLIC void Compiler::Initialize(Compiler* enclosing, int scope, int ty SetReceiverName(""); } } -PRIVATE void Compiler::WriteBytecode(Stream* stream, const char* filename) { +void Compiler::WriteBytecode(Stream* stream, const char* filename) { Bytecode* bytecode = new Bytecode(); for (size_t i = 0; i < Compiler::Functions.size(); i++) @@ -3148,7 +3119,7 @@ PRIVATE void Compiler::WriteBytecode(Stream* stream, const char* filenam if (TokenMap) TokenMap->Clear(); } -PUBLIC bool Compiler::Compile(const char* filename, const char* source, const char* output) { +bool Compiler::Compile(const char* filename, const char* source, const char* output) { scanner.Line = 1; scanner.Start = (char*)source; scanner.Current = (char*)source; @@ -3195,7 +3166,7 @@ PUBLIC bool Compiler::Compile(const char* filename, const char* source, return !parser.HadError; } -PUBLIC void Compiler::Finish() { +void Compiler::Finish() { if (UnusedVariables) { WarnVariablesUnused(); delete UnusedVariables; @@ -3204,10 +3175,10 @@ PUBLIC void Compiler::Finish() { EmitReturn(); } -PUBLIC VIRTUAL Compiler::~Compiler() { +Compiler::~Compiler() { } -PUBLIC STATIC void Compiler::FinishCompiling() { +void Compiler::FinishCompiling() { Compiler::Functions.clear(); Compiler::ModuleLocals.clear(); @@ -3216,6 +3187,6 @@ PUBLIC STATIC void Compiler::FinishCompiling() { TokenMap = NULL; } } -PUBLIC STATIC void Compiler::Dispose() { +void Compiler::Dispose() { Memory::Free(Rules); } diff --git a/source/Engine/Bytecode/GarbageCollector.cpp b/source/Engine/Bytecode/GarbageCollector.cpp index 7dd5f01c..2c5e2056 100644 --- a/source/Engine/Bytecode/GarbageCollector.cpp +++ b/source/Engine/Bytecode/GarbageCollector.cpp @@ -1,22 +1,3 @@ -#if INTERFACE -#include -#include - -class GarbageCollector { -public: - static vector GrayList; - static Obj* RootObject; - - static size_t NextGC; - static size_t GarbageSize; - static double MaxTimeAlotted; - - static bool Print; - static bool FilterSweepEnabled; - static int FilterSweepType; -}; -#endif - #include #include @@ -39,12 +20,12 @@ bool GarbageCollector::Print = false; bool GarbageCollector::FilterSweepEnabled = false; int GarbageCollector::FilterSweepType = 0; -PUBLIC STATIC void GarbageCollector::Init() { +void GarbageCollector::Init() { GarbageCollector::RootObject = NULL; GarbageCollector::NextGC = 0x100000; } -PUBLIC STATIC void GarbageCollector::Collect() { +void GarbageCollector::Collect() { GrayList.clear(); double grayElapsed = Clock::GetTicks(); @@ -158,7 +139,7 @@ PUBLIC STATIC void GarbageCollector::Collect() { GarbageCollector::NextGC = GarbageCollector::GarbageSize + (1024 * 1024); } -PRIVATE STATIC void GarbageCollector::FreeValue(VMValue value) { +void GarbageCollector::FreeValue(VMValue value) { if (!IS_OBJECT(value)) return; // If this object is an instance associated with an entity, @@ -172,11 +153,11 @@ PRIVATE STATIC void GarbageCollector::FreeValue(VMValue value) { ScriptManager::FreeValue(value); } -PRIVATE STATIC void GarbageCollector::GrayValue(VMValue value) { +void GarbageCollector::GrayValue(VMValue value) { if (!IS_OBJECT(value)) return; GrayObject(AS_OBJECT(value)); } -PRIVATE STATIC void GarbageCollector::GrayObject(void* obj) { +void GarbageCollector::GrayObject(void* obj) { if (obj == NULL) return; Obj* object = (Obj*)obj; @@ -186,15 +167,15 @@ PRIVATE STATIC void GarbageCollector::GrayObject(void* obj) { GrayList.push_back(object); } -PRIVATE STATIC void GarbageCollector::GrayHashMapItem(Uint32, VMValue value) { +void GarbageCollector::GrayHashMapItem(Uint32, VMValue value) { GrayValue(value); } -PRIVATE STATIC void GarbageCollector::GrayHashMap(void* pointer) { +void GarbageCollector::GrayHashMap(void* pointer) { if (!pointer) return; ((HashMap*)pointer)->ForAll(GrayHashMapItem); } -PRIVATE STATIC void GarbageCollector::BlackenObject(Obj* object) { +void GarbageCollector::BlackenObject(Obj* object) { GrayObject(object->Class); switch (object->Type) { diff --git a/source/Engine/Bytecode/ScriptEntity.cpp b/source/Engine/Bytecode/ScriptEntity.cpp index fffc6613..4eab3bb4 100644 --- a/source/Engine/Bytecode/ScriptEntity.cpp +++ b/source/Engine/Bytecode/ScriptEntity.cpp @@ -1,16 +1,3 @@ -#if INTERFACE -#include -#include - -class ScriptEntity : public Entity { -public: - static bool DisableAutoAnimate; - - ObjInstance* Instance = NULL; - HashMap* Properties; -}; -#endif - #include #include #include @@ -41,7 +28,7 @@ Uint32 Hash_HitboxTop = 0; Uint32 Hash_HitboxRight = 0; Uint32 Hash_HitboxBottom = 0; -PUBLIC void ScriptEntity::Link(ObjInstance* instance) { +void ScriptEntity::Link(ObjInstance* instance) { Instance = instance; Instance->EntityPtr = this; Properties = new HashMap(NULL, 4); @@ -74,7 +61,7 @@ PUBLIC void ScriptEntity::Link(ObjInstance* instance) { LinkFields(); } -PUBLIC void ScriptEntity::LinkFields() { +void ScriptEntity::LinkFields() { /*** * \field X * \type Decimal @@ -704,7 +691,7 @@ PUBLIC void ScriptEntity::LinkFields() { #undef LINK_DEC #undef LINK_BOOL -PRIVATE bool ScriptEntity::GetCallableValue(Uint32 hash, VMValue& value) { +bool ScriptEntity::GetCallableValue(Uint32 hash, VMValue& value) { // First look for a field which may shadow a method. VMValue result; if (Instance->Fields->GetIfExists(hash, &result)) { @@ -725,14 +712,14 @@ PRIVATE bool ScriptEntity::GetCallableValue(Uint32 hash, VMValue& value) { return false; } -PRIVATE ObjFunction* ScriptEntity::GetCallableFunction(Uint32 hash) { +ObjFunction* ScriptEntity::GetCallableFunction(Uint32 hash) { ObjClass* klass = Instance->Object.Class; VMValue result; if (klass->Methods->GetIfExists(hash, &result)) return AS_FUNCTION(result); return NULL; } -PUBLIC bool ScriptEntity::RunFunction(Uint32 hash) { +bool ScriptEntity::RunFunction(Uint32 hash) { if (!Instance) return false; @@ -754,7 +741,7 @@ PUBLIC bool ScriptEntity::RunFunction(Uint32 hash) { return true; } -PUBLIC bool ScriptEntity::RunCreateFunction(VMValue flag) { +bool ScriptEntity::RunCreateFunction(VMValue flag) { // NOTE: // If the function doesn't exist, this is not an error VM side, // treat whatever we call from C++ as a virtual-like function. @@ -780,7 +767,7 @@ PUBLIC bool ScriptEntity::RunCreateFunction(VMValue flag) { return false; } -PUBLIC bool ScriptEntity::RunInitializer() { +bool ScriptEntity::RunInitializer() { if (!HasInitializer(Instance->Object.Class)) return true; @@ -797,7 +784,7 @@ PUBLIC bool ScriptEntity::RunInitializer() { return true; } -PUBLIC bool ScriptEntity::ChangeClass(const char* className) { +bool ScriptEntity::ChangeClass(const char* className) { if (!ScriptManager::ClassExists(className)) return false; @@ -825,7 +812,7 @@ PUBLIC bool ScriptEntity::ChangeClass(const char* className) { return true; } -PUBLIC void ScriptEntity::Copy(ScriptEntity* other, bool copyClass) { +void ScriptEntity::Copy(ScriptEntity* other, bool copyClass) { CopyFields(other); if (copyClass) @@ -842,13 +829,13 @@ PUBLIC void ScriptEntity::Copy(ScriptEntity* other, bool copyClass) { }); } -PUBLIC void ScriptEntity::CopyFields(ScriptEntity* other) { +void ScriptEntity::CopyFields(ScriptEntity* other) { Entity::CopyFields(other); CopyVMFields(other); } -PUBLIC void ScriptEntity::CopyVMFields(ScriptEntity* other) { +void ScriptEntity::CopyVMFields(ScriptEntity* other) { Table* srcFields = Instance->Fields; Table* destFields = other->Instance->Fields; @@ -865,7 +852,7 @@ PUBLIC void ScriptEntity::CopyVMFields(ScriptEntity* other) { } // Events called from C++ -PUBLIC void ScriptEntity::Initialize() { +void ScriptEntity::Initialize() { if (!Instance) return; // Set defaults @@ -933,7 +920,7 @@ PUBLIC void ScriptEntity::Initialize() { RunInitializer(); } -PUBLIC void ScriptEntity::Create(VMValue flag) { +void ScriptEntity::Create(VMValue flag) { if (!Instance) return; Created = true; @@ -943,27 +930,27 @@ PUBLIC void ScriptEntity::Create(VMValue flag) { SetAnimation(0, 0); } } -PUBLIC void ScriptEntity::Create() { +void ScriptEntity::Create() { Create(INTEGER_VAL(0)); } -PUBLIC void ScriptEntity::PostCreate() { +void ScriptEntity::PostCreate() { if (!Instance) return; PostCreated = true; RunFunction(Hash_PostCreate); } -PUBLIC void ScriptEntity::UpdateEarly() { +void ScriptEntity::UpdateEarly() { if (!Active) return; RunFunction(Hash_UpdateEarly); } -PUBLIC void ScriptEntity::Update() { +void ScriptEntity::Update() { if (!Active) return; RunFunction(Hash_Update); } -PUBLIC void ScriptEntity::UpdateLate() { +void ScriptEntity::UpdateLate() { if (!Active) return; RunFunction(Hash_UpdateLate); @@ -973,40 +960,40 @@ PUBLIC void ScriptEntity::UpdateLate() { if (AutoPhysics) ApplyMotion(); } -PUBLIC void ScriptEntity::RenderEarly() { +void ScriptEntity::RenderEarly() { if (!Active) return; RunFunction(Hash_RenderEarly); } -PUBLIC void ScriptEntity::Render(int CamX, int CamY) { +void ScriptEntity::Render(int CamX, int CamY) { if (!Active) return; if (RunFunction(Hash_Render)) { // Default render } } -PUBLIC void ScriptEntity::RenderLate() { +void ScriptEntity::RenderLate() { if (!Active) return; RunFunction(Hash_RenderLate); } -PUBLIC void ScriptEntity::OnAnimationFinish() { +void ScriptEntity::OnAnimationFinish() { RunFunction(Hash_OnAnimationFinish); } -PUBLIC void ScriptEntity::OnSceneLoad() { +void ScriptEntity::OnSceneLoad() { if (!Active) return; RunFunction(Hash_OnSceneLoad); } -PUBLIC void ScriptEntity::OnSceneRestart() { +void ScriptEntity::OnSceneRestart() { if (!Active) return; RunFunction(Hash_OnSceneRestart); } -PUBLIC void ScriptEntity::GameStart() { +void ScriptEntity::GameStart() { RunFunction(Hash_GameStart); } -PUBLIC void ScriptEntity::Remove() { +void ScriptEntity::Remove() { if (Removed) return; if (!Instance) return; @@ -1015,7 +1002,7 @@ PUBLIC void ScriptEntity::Remove() { Active = false; Removed = true; } -PUBLIC void ScriptEntity::Dispose() { +void ScriptEntity::Dispose() { Entity::Dispose(); if (Properties) { delete Properties; @@ -1053,7 +1040,7 @@ bool TestEntityCollision(Entity* other, Entity* self) { return self->CollideWithObject(other); } -PUBLIC STATIC bool ScriptEntity::VM_Getter(Obj* object, Uint32 hash, VMValue* result, Uint32 threadID) { +bool ScriptEntity::VM_Getter(Obj* object, Uint32 hash, VMValue* result, Uint32 threadID) { Entity* self = GetScriptEntity(object); if (self == nullptr) return false; @@ -1081,7 +1068,7 @@ PUBLIC STATIC bool ScriptEntity::VM_Getter(Obj* object, Uint32 hash, VMValue* re return false; } -PUBLIC STATIC bool ScriptEntity::VM_Setter(Obj* object, Uint32 hash, VMValue value, Uint32 threadID) { +bool ScriptEntity::VM_Setter(Obj* object, Uint32 hash, VMValue value, Uint32 threadID) { Entity* self = GetScriptEntity(object); if (self == nullptr) return false; @@ -1116,7 +1103,7 @@ PUBLIC STATIC bool ScriptEntity::VM_Setter(Obj* object, Uint32 hash, VMValue val * \param frame (Integer): The frame index. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_SetAnimation(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_SetAnimation(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); Entity* self = GET_ENTITY(0); int animation = GET_ARG(1, GetInteger); @@ -1150,7 +1137,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_SetAnimation(int argCount, VMValue* args, * \param frame (Integer): The frame index. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_ResetAnimation(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_ResetAnimation(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); Entity* self = GET_ENTITY(0); int animation = GET_ARG(1, GetInteger); @@ -1183,7 +1170,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_ResetAnimation(int argCount, VMValue* arg * \desc Animates the entity. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_Animate(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_Animate(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); Entity* self = GET_ENTITY(0); if (self) @@ -1197,7 +1184,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_Animate(int argCount, VMValue* args, Uint * \return Returns an Integer value. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_GetIDWithinClass(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_GetIDWithinClass(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); Entity* self = GET_ENTITY(0); if (!self || !self->List) @@ -1223,7 +1210,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_GetIDWithinClass(int argCount, VMValue* a * \param registry (String): The registry name. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_AddToRegistry(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_AddToRegistry(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); Entity* self = GET_ENTITY(0); char* registry = GET_ARG(1, GetString); @@ -1251,7 +1238,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_AddToRegistry(int argCount, VMValue* args * \return Returns a Boolean value. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_IsInRegistry(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_IsInRegistry(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); Entity* self = GET_ENTITY(0); char* registry = GET_ARG(1, GetString); @@ -1269,7 +1256,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_IsInRegistry(int argCount, VMValue* args, * \param registry (String): The registry name. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_RemoveFromRegistry(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_RemoveFromRegistry(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); Entity* self = GET_ENTITY(0); char* registry = GET_ARG(1, GetString); @@ -1288,7 +1275,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_RemoveFromRegistry(int argCount, VMValue* * \desc Applies gravity and velocities to the entity. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_ApplyMotion(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_ApplyMotion(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); Entity* self = GET_ENTITY(0); if (IsValidEntity(self)) @@ -1306,7 +1293,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_ApplyMotion(int argCount, VMValue* args, * \return Returns true if the specified positions and ranges are within the specified view, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_InView(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_InView(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 6); // Entity* self = (Entity*)AS_INSTANCE(args[0])->EntityPtr; int view = GET_ARG(1, GetInteger); @@ -1330,7 +1317,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_InView(int argCount, VMValue* args, Uint3 * \return Returns the entity that was collided with, or null if it did not collide with any entity. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_CollidedWithObject(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_CollidedWithObject(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); @@ -1377,7 +1364,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_CollidedWithObject(int argCount, VMValue* * \param hitbox (Integer): The hitbox ID. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_GetHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_GetHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 5); ScriptEntity* self = GET_ENTITY(0); ISprite* sprite = GET_ARG(1, GetSprite); @@ -1419,7 +1406,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_GetHitboxFromSprite(int argCount, VMValue * \return Returns an array containing the hitbox top, left, right and bottom sides in that order. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_ReturnHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_ReturnHitboxFromSprite(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 5); ScriptEntity* self = GET_ENTITY(0); ISprite* sprite = GET_ARG(1, GetSprite); @@ -1462,7 +1449,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_ReturnHitboxFromSprite(int argCount, VMVa * \return Returns true if the entity collided, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_CollideWithObject(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_CollideWithObject(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); ScriptEntity* other = GET_ENTITY(1); @@ -1477,7 +1464,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_CollideWithObject(int argCount, VMValue* * \return Returns true if the entity collided, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_SolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_SolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); ScriptEntity* self = GET_ENTITY(0); ScriptEntity* other = GET_ENTITY(1); @@ -1493,7 +1480,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_SolidCollideWithObject(int argCount, VMVa * \return Returns true if the entity collided, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_TopSolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_TopSolidCollideWithObject(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); ScriptEntity* self = GET_ENTITY(0); ScriptEntity* other = GET_ENTITY(1); @@ -1503,7 +1490,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_TopSolidCollideWithObject(int argCount, V return INTEGER_VAL(self->TopSolidCollideWithObject(other, flag)); } -PUBLIC STATIC VMValue ScriptEntity::VM_ApplyPhysics(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_ApplyPhysics(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); ScriptEntity* self = GET_ENTITY(0); if (IsValidEntity(self)) @@ -1518,7 +1505,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_ApplyPhysics(int argCount, VMValue* args, * \return Returns true if the property exists, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_PropertyExists(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_PropertyExists(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); char* property = GET_ARG(1, GetString); @@ -1533,7 +1520,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_PropertyExists(int argCount, VMValue* arg * \return Returns the property if it exists, and null if the property does not exist. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_PropertyGet(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_PropertyGet(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); char* property = GET_ARG(1, GetString); @@ -1549,7 +1536,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_PropertyGet(int argCount, VMValue* args, * \param visible (Boolean): Whether the entity will be visible or not on the specified view. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_SetViewVisibility(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_SetViewVisibility(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); ScriptEntity* self = GET_ENTITY(0); int viewIndex = GET_ARG(1, GetInteger); @@ -1570,7 +1557,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_SetViewVisibility(int argCount, VMValue* * \param visible (Boolean): Whether the entity will always be visible or not on the specified view. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_SetViewOverride(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_SetViewOverride(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 3); ScriptEntity* self = GET_ENTITY(0); int viewIndex = GET_ARG(1, GetInteger); @@ -1591,7 +1578,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_SetViewOverride(int argCount, VMValue* ar * \param drawGroup (Integer): The draw group. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_AddToDrawGroup(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_AddToDrawGroup(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); if (!IsValidEntity(self)) @@ -1612,7 +1599,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_AddToDrawGroup(int argCount, VMValue* arg * \return Returns true if the entity is in the specified draw group, false if otherwise. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_IsInDrawGroup(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_IsInDrawGroup(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); if (!IsValidEntity(self)) @@ -1630,7 +1617,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_IsInDrawGroup(int argCount, VMValue* args * \param drawGroup (Integer): The draw group. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_RemoveFromDrawGroup(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_RemoveFromDrawGroup(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); if (!IsValidEntity(self)) @@ -1653,7 +1640,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_RemoveFromDrawGroup(int argCount, VMValue * \return Returns the channel index where the sound began to play, or -1 if no channel was available. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_PlaySound(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_PlaySound(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckAtLeastArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); ISound* audio = GET_ARG(1, GetSound); @@ -1678,7 +1665,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_PlaySound(int argCount, VMValue* args, Ui * \return Returns the channel index where the sound began to play, or -1 if no channel was available. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_LoopSound(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_LoopSound(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckAtLeastArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); ISound* audio = GET_ARG(1, GetSound); @@ -1699,7 +1686,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_LoopSound(int argCount, VMValue* args, Ui * \param sound (Integer): The sound index to interrupt. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_StopSound(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_StopSound(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ScriptEntity* self = GET_ENTITY(0); ISound* audio = GET_ARG(1, GetSound); @@ -1712,7 +1699,7 @@ PUBLIC STATIC VMValue ScriptEntity::VM_StopSound(int argCount, VMValue* args, Ui * \desc Stops all sounds the entity is playing. * \ns Instance */ -PUBLIC STATIC VMValue ScriptEntity::VM_StopAllSounds(int argCount, VMValue* args, Uint32 threadID) { +VMValue ScriptEntity::VM_StopAllSounds(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); ScriptEntity* self = GET_ENTITY(0); if (IsValidEntity(self)) diff --git a/source/Engine/Bytecode/ScriptManager.cpp b/source/Engine/Bytecode/ScriptManager.cpp index 1bb7ef96..933de5ae 100644 --- a/source/Engine/Bytecode/ScriptManager.cpp +++ b/source/Engine/Bytecode/ScriptManager.cpp @@ -1,40 +1,3 @@ -#if INTERFACE -need_t ScriptEntity; - -#include -#include -#include -#include -#include -#include -#include - -#include - -class ScriptManager { -public: - static bool LoadAllClasses; - - static HashMap* Globals; - static HashMap* Constants; - - static std::set FreedGlobals; - - static VMThread Threads[8]; - static Uint32 ThreadCount; - - static vector ModuleList; - - static HashMap* Sources; - static HashMap* Classes; - static HashMap* Tokens; - static vector AllNamespaces; - static vector ClassImplList; - - static SDL_mutex* GlobalLock; -}; -#endif - #include #include #include @@ -79,7 +42,7 @@ static Uint32 VMBranchLimit = 0; // #define DEBUG_STRESS_GC -PUBLIC STATIC void ScriptManager::RequestGarbageCollection() { +void ScriptManager::RequestGarbageCollection() { #ifndef DEBUG_STRESS_GC if (GarbageCollector::GarbageSize > GarbageCollector::NextGC) #endif @@ -92,7 +55,7 @@ PUBLIC STATIC void ScriptManager::RequestGarbageCollection() { Log::Print(Log::LOG_INFO, "%04X: Freed garbage from %u to %u (%d), next GC at %d", Scene::Frame, (Uint32)startSize, (Uint32)GarbageCollector::GarbageSize, GarbageCollector::GarbageSize - startSize, GarbageCollector::NextGC); } } -PUBLIC STATIC void ScriptManager::ForceGarbageCollection() { +void ScriptManager::ForceGarbageCollection() { if (ScriptManager::Lock()) { if (ScriptManager::ThreadCount > 1) { ScriptManager::Unlock(); @@ -105,12 +68,12 @@ PUBLIC STATIC void ScriptManager::ForceGarbageCollection() { } } -PUBLIC STATIC void ScriptManager::ResetStack() { +void ScriptManager::ResetStack() { Threads[0].ResetStack(); } // #region Life Cycle -PUBLIC STATIC void ScriptManager::Init() { +void ScriptManager::Init() { if (Globals == NULL) Globals = new HashMap(NULL, 8); if (Constants == NULL) @@ -153,7 +116,7 @@ PUBLIC STATIC void ScriptManager::Init() { ThreadCount = 1; } #ifdef VM_DEBUG -PRIVATE STATIC Uint32 ScriptManager::GetBranchLimit() { +Uint32 ScriptManager::GetBranchLimit() { int branchLimit = 0; if (Application::Settings->GetInteger("dev", "branchLimit", &branchLimit) == true) { @@ -172,12 +135,12 @@ PRIVATE STATIC Uint32 ScriptManager::GetBranchLimit() { return (Uint32)branchLimit; } #endif -PUBLIC STATIC void ScriptManager::DisposeGlobalValueTable(HashMap* globals) { +void ScriptManager::DisposeGlobalValueTable(HashMap* globals) { globals->ForAll(FreeGlobalValue); globals->Clear(); delete globals; } -PUBLIC STATIC void ScriptManager::Dispose() { +void ScriptManager::Dispose() { // NOTE: Remove GC-able values from these tables so they may be cleaned up. if (Globals) Globals->ForAll(RemoveNonGlobalableValue); @@ -233,7 +196,7 @@ PUBLIC STATIC void ScriptManager::Dispose() { SDL_DestroyMutex(GlobalLock); } -PRIVATE STATIC void ScriptManager::RemoveNonGlobalableValue(Uint32 hash, VMValue value) { +void ScriptManager::RemoveNonGlobalableValue(Uint32 hash, VMValue value) { if (IS_OBJECT(value)) { switch (OBJECT_TYPE(value)) { case OBJ_CLASS: @@ -250,7 +213,7 @@ PRIVATE STATIC void ScriptManager::RemoveNonGlobalableValue(Uint32 hash, VMVa } } } -PRIVATE STATIC void ScriptManager::FreeNativeValue(Uint32 hash, VMValue value) { +void ScriptManager::FreeNativeValue(Uint32 hash, VMValue value) { if (IS_OBJECT(value)) { switch (OBJECT_TYPE(value)) { case OBJ_NATIVE: @@ -262,7 +225,7 @@ PRIVATE STATIC void ScriptManager::FreeNativeValue(Uint32 hash, VMValue value } } } -PRIVATE STATIC void ScriptManager::FreeFunction(ObjFunction* function) { +void ScriptManager::FreeFunction(ObjFunction* function) { /* printf("OBJ_FUNCTION: %p (%s)\n", function, function->Name ? @@ -281,7 +244,7 @@ PRIVATE STATIC void ScriptManager::FreeFunction(ObjFunction* function) { FREE_OBJ(function, ObjFunction); } -PRIVATE STATIC void ScriptManager::FreeModule(ObjModule* module) { +void ScriptManager::FreeModule(ObjModule* module) { if (module->SourceFilename != NULL) FreeValue(OBJECT_VAL(module->SourceFilename)); @@ -296,7 +259,7 @@ PRIVATE STATIC void ScriptManager::FreeModule(ObjModule* module) { FREE_OBJ(module, ObjModule); } -PRIVATE STATIC void ScriptManager::FreeClass(ObjClass* klass) { +void ScriptManager::FreeClass(ObjClass* klass) { // Subfunctions are already freed as a byproduct of the ModuleList, // so just do natives. klass->Methods->ForAll(FreeNativeValue); @@ -311,7 +274,7 @@ PRIVATE STATIC void ScriptManager::FreeClass(ObjClass* klass) { FREE_OBJ(klass, ObjClass); } -PRIVATE STATIC void ScriptManager::FreeEnumeration(ObjEnum* enumeration) { +void ScriptManager::FreeEnumeration(ObjEnum* enumeration) { // An enumeration does not own its values, so it's not allowed // to free them. delete enumeration->Fields; @@ -321,7 +284,7 @@ PRIVATE STATIC void ScriptManager::FreeEnumeration(ObjEnum* enumeration) { FREE_OBJ(enumeration, ObjEnum); } -PRIVATE STATIC void ScriptManager::FreeNamespace(ObjNamespace* ns) { +void ScriptManager::FreeNamespace(ObjNamespace* ns) { // A namespace does not own its values, so it's not allowed // to free them. delete ns->Fields; @@ -331,14 +294,14 @@ PRIVATE STATIC void ScriptManager::FreeNamespace(ObjNamespace* ns) { FREE_OBJ(ns, ObjNamespace); } -PUBLIC STATIC void ScriptManager::FreeString(ObjString* string) { +void ScriptManager::FreeString(ObjString* string) { if (string->Chars != NULL) Memory::Free(string->Chars); string->Chars = NULL; FREE_OBJ(string, ObjString); } -PUBLIC STATIC void ScriptManager::FreeGlobalValue(Uint32 hash, VMValue value) { +void ScriptManager::FreeGlobalValue(Uint32 hash, VMValue value) { if (IS_OBJECT(value)) { Obj* object = AS_OBJECT(value); if (FreedGlobals.find(object) != FreedGlobals.end()) @@ -380,7 +343,7 @@ PUBLIC STATIC void ScriptManager::FreeGlobalValue(Uint32 hash, VMValue value) } } } -PRIVATE STATIC void ScriptManager::FreeModules() { +void ScriptManager::FreeModules() { Log::Print(Log::LOG_VERBOSE, "Freeing %d modules...", ModuleList.size()); for (size_t i = 0; i < ModuleList.size(); i++) { FreeModule(ModuleList[i]); @@ -391,7 +354,7 @@ PRIVATE STATIC void ScriptManager::FreeModules() { // #endregion // #region ValueFuncs -PUBLIC STATIC VMValue ScriptManager::CastValueAsString(VMValue v, bool prettyPrint) { +VMValue ScriptManager::CastValueAsString(VMValue v, bool prettyPrint) { if (IS_STRING(v)) return v; @@ -405,10 +368,10 @@ PUBLIC STATIC VMValue ScriptManager::CastValueAsString(VMValue v, bool prettyPri free(buffer); return v; } -PUBLIC STATIC VMValue ScriptManager::CastValueAsString(VMValue v) { +VMValue ScriptManager::CastValueAsString(VMValue v) { return CastValueAsString(v, false); } -PUBLIC STATIC VMValue ScriptManager::CastValueAsInteger(VMValue v) { +VMValue ScriptManager::CastValueAsInteger(VMValue v) { float a; switch (v.Type) { case VAL_DECIMAL: @@ -425,7 +388,7 @@ PUBLIC STATIC VMValue ScriptManager::CastValueAsInteger(VMValue v) { } return NULL_VAL; } -PUBLIC STATIC VMValue ScriptManager::CastValueAsDecimal(VMValue v) { +VMValue ScriptManager::CastValueAsDecimal(VMValue v) { int a; switch (v.Type) { case VAL_DECIMAL: @@ -442,7 +405,7 @@ PUBLIC STATIC VMValue ScriptManager::CastValueAsDecimal(VMValue v) { } return NULL_VAL; } -PUBLIC STATIC VMValue ScriptManager::Concatenate(VMValue va, VMValue vb) { +VMValue ScriptManager::Concatenate(VMValue va, VMValue vb) { ObjString* a = AS_STRING(va); ObjString* b = AS_STRING(vb); @@ -455,7 +418,7 @@ PUBLIC STATIC VMValue ScriptManager::Concatenate(VMValue va, VMValue vb) { return OBJECT_VAL(result); } -PUBLIC STATIC bool ScriptManager::ValuesSortaEqual(VMValue a, VMValue b) { +bool ScriptManager::ValuesSortaEqual(VMValue a, VMValue b) { if ((a.Type == VAL_DECIMAL && b.Type == VAL_INTEGER) || (a.Type == VAL_INTEGER && b.Type == VAL_DECIMAL)) { float a_d = AS_DECIMAL(CastValueAsDecimal(a)); @@ -477,7 +440,7 @@ PUBLIC STATIC bool ScriptManager::ValuesSortaEqual(VMValue a, VMValue b) { return ScriptManager::ValuesEqual(a, b); } -PUBLIC STATIC bool ScriptManager::ValuesEqual(VMValue a, VMValue b) { +bool ScriptManager::ValuesEqual(VMValue a, VMValue b) { if (a.Type == VAL_LINKED_INTEGER) goto SKIP_CHECK; if (a.Type == VAL_LINKED_DECIMAL) goto SKIP_CHECK; if (b.Type == VAL_LINKED_INTEGER) goto SKIP_CHECK; @@ -500,7 +463,7 @@ PUBLIC STATIC bool ScriptManager::ValuesEqual(VMValue a, VMValue b) { } return false; } -PUBLIC STATIC bool ScriptManager::ValueFalsey(VMValue a) { +bool ScriptManager::ValueFalsey(VMValue a) { if (a.Type == VAL_NULL) return true; switch (a.Type) { @@ -513,7 +476,7 @@ PUBLIC STATIC bool ScriptManager::ValueFalsey(VMValue a) { return false; } -PUBLIC STATIC VMValue ScriptManager::DelinkValue(VMValue val) { +VMValue ScriptManager::DelinkValue(VMValue val) { if (IS_LINKED_DECIMAL(val)) return DECIMAL_VAL(AS_DECIMAL(val)); if (IS_LINKED_INTEGER(val)) @@ -522,7 +485,7 @@ PUBLIC STATIC VMValue ScriptManager::DelinkValue(VMValue val) { return val; } -PUBLIC STATIC bool ScriptManager::DoIntegerConversion(VMValue& value, Uint32 threadID) { +bool ScriptManager::DoIntegerConversion(VMValue& value, Uint32 threadID) { VMValue result = ScriptManager::CastValueAsInteger(value); if (IS_NULL(result)) { // Conversion failed @@ -532,7 +495,7 @@ PUBLIC STATIC bool ScriptManager::DoIntegerConversion(VMValue& value, Uint32 thr value = result; return true; } -PUBLIC STATIC bool ScriptManager::DoDecimalConversion(VMValue& value, Uint32 threadID) { +bool ScriptManager::DoDecimalConversion(VMValue& value, Uint32 threadID) { VMValue result = ScriptManager::CastValueAsDecimal(value); if (IS_NULL(result)) { // Conversion failed @@ -543,7 +506,7 @@ PUBLIC STATIC bool ScriptManager::DoDecimalConversion(VMValue& value, Uint32 thr return true; } -PUBLIC STATIC void ScriptManager::FreeValue(VMValue value) { +void ScriptManager::FreeValue(VMValue value) { if (IS_OBJECT(value)) { Obj* objectPointer = AS_OBJECT(value); switch (OBJECT_TYPE(value)) { @@ -611,18 +574,18 @@ PUBLIC STATIC void ScriptManager::FreeValue(VMValue value) { // #endregion // #region GlobalFuncs -PUBLIC STATIC bool ScriptManager::Lock() { +bool ScriptManager::Lock() { if (ScriptManager::ThreadCount == 1) return true; return SDL_LockMutex(GlobalLock) == 0; } -PUBLIC STATIC void ScriptManager::Unlock() { +void ScriptManager::Unlock() { if (ScriptManager::ThreadCount > 1) SDL_UnlockMutex(GlobalLock); } -PUBLIC STATIC void ScriptManager::DefineMethod(VMThread* thread, ObjFunction* function, Uint32 hash) { +void ScriptManager::DefineMethod(VMThread* thread, ObjFunction* function, Uint32 hash) { VMValue methodValue = OBJECT_VAL(function); ObjClass* klass = AS_CLASS(thread->Peek(0)); @@ -635,7 +598,7 @@ PUBLIC STATIC void ScriptManager::DefineMethod(VMThread* thread, ObjFunction* thread->Pop(); } -PUBLIC STATIC void ScriptManager::DefineNative(ObjClass* klass, const char* name, NativeFn function) { +void ScriptManager::DefineNative(ObjClass* klass, const char* name, NativeFn function) { if (function == NULL) return; if (klass == NULL) return; if (name == NULL) return; @@ -643,7 +606,7 @@ PUBLIC STATIC void ScriptManager::DefineNative(ObjClass* klass, const char* n if (!klass->Methods->Exists(name)) klass->Methods->Put(name, OBJECT_VAL(NewNative(function))); } -PUBLIC STATIC void ScriptManager::GlobalLinkInteger(ObjClass* klass, const char* name, int* value) { +void ScriptManager::GlobalLinkInteger(ObjClass* klass, const char* name, int* value) { if (name == NULL) return; if (klass == NULL) { @@ -653,7 +616,7 @@ PUBLIC STATIC void ScriptManager::GlobalLinkInteger(ObjClass* klass, const ch klass->Methods->Put(name, INTEGER_LINK_VAL(value)); } } -PUBLIC STATIC void ScriptManager::GlobalLinkDecimal(ObjClass* klass, const char* name, float* value) { +void ScriptManager::GlobalLinkDecimal(ObjClass* klass, const char* name, float* value) { if (name == NULL) return; if (klass == NULL) { @@ -663,21 +626,21 @@ PUBLIC STATIC void ScriptManager::GlobalLinkDecimal(ObjClass* klass, const ch klass->Methods->Put(name, DECIMAL_LINK_VAL(value)); } } -PUBLIC STATIC void ScriptManager::GlobalConstInteger(ObjClass* klass, const char* name, int value) { +void ScriptManager::GlobalConstInteger(ObjClass* klass, const char* name, int value) { if (name == NULL) return; if (klass == NULL) Constants->Put(name, INTEGER_VAL(value)); else klass->Methods->Put(name, INTEGER_VAL(value)); } -PUBLIC STATIC void ScriptManager::GlobalConstDecimal(ObjClass* klass, const char* name, float value) { +void ScriptManager::GlobalConstDecimal(ObjClass* klass, const char* name, float value) { if (name == NULL) return; if (klass == NULL) Constants->Put(name, DECIMAL_VAL(value)); else klass->Methods->Put(name, DECIMAL_VAL(value)); } -PUBLIC STATIC ObjClass* ScriptManager::GetClassParent(ObjClass* klass) { +ObjClass* ScriptManager::GetClassParent(ObjClass* klass) { if (!klass->Parent && klass->ParentHash) { VMValue parent; if (ScriptManager::Globals->GetIfExists(klass->ParentHash, &parent) && IS_CLASS(parent)) @@ -685,7 +648,7 @@ PUBLIC STATIC ObjClass* ScriptManager::GetClassParent(ObjClass* klass) { } return klass->Parent; } -PUBLIC STATIC VMValue ScriptManager::GetClassMethod(ObjClass* klass, Uint32 hash) { +VMValue ScriptManager::GetClassMethod(ObjClass* klass, Uint32 hash) { VMValue method; if (klass->Methods->GetIfExists(hash, &method)) { return method; @@ -698,10 +661,10 @@ PUBLIC STATIC VMValue ScriptManager::GetClassMethod(ObjClass* klass, Uint32 hash return NULL_VAL; } -PUBLIC STATIC void ScriptManager::LinkStandardLibrary() { +void ScriptManager::LinkStandardLibrary() { StandardLibrary::Link(); } -PUBLIC STATIC void ScriptManager::LinkExtensions() { +void ScriptManager::LinkExtensions() { } // #endregion @@ -717,7 +680,7 @@ PUBLIC STATIC void ScriptManager::LinkExtensions() { #endif // #region ObjectFuncs -PUBLIC STATIC bool ScriptManager::RunBytecode(BytecodeContainer bytecodeContainer, Uint32 filenameHash) { +bool ScriptManager::RunBytecode(BytecodeContainer bytecodeContainer, Uint32 filenameHash) { Bytecode* bytecode = new Bytecode(); if (!bytecode->Read(bytecodeContainer, Tokens)) { delete bytecode; @@ -750,7 +713,7 @@ PUBLIC STATIC bool ScriptManager::RunBytecode(BytecodeContainer bytecodeConta return true; } -PUBLIC STATIC bool ScriptManager::CallFunction(char* functionName) { +bool ScriptManager::CallFunction(char* functionName) { if (!Globals->Exists(functionName)) return false; @@ -762,7 +725,7 @@ PUBLIC STATIC bool ScriptManager::CallFunction(char* functionName) { Threads[0].RunEntityFunction(function, 0); return true; } -PUBLIC STATIC Entity* ScriptManager::SpawnObject(const char* objectName) { +Entity* ScriptManager::SpawnObject(const char* objectName) { ObjClass* klass = GetObjectClass(objectName); if (!klass) { Log::Print(Log::LOG_ERROR, "Could not find class of %s!", objectName); @@ -776,14 +739,14 @@ PUBLIC STATIC Entity* ScriptManager::SpawnObject(const char* objectName) { return object; } -PUBLIC STATIC Uint32 ScriptManager::MakeFilenameHash(char *filename) { +Uint32 ScriptManager::MakeFilenameHash(char *filename) { size_t length = strlen(filename); char* dot = strrchr(filename, '.'); if (dot) length = dot - filename; return CombinedHash::EncryptData((const void*)filename, length); } -PUBLIC STATIC BytecodeContainer ScriptManager::GetBytecodeFromFilenameHash(Uint32 filenameHash) { +BytecodeContainer ScriptManager::GetBytecodeFromFilenameHash(Uint32 filenameHash) { if (Sources->Exists(filenameHash)) return Sources->Get(filenameHash); @@ -813,20 +776,20 @@ PUBLIC STATIC BytecodeContainer ScriptManager::GetBytecodeFromFilenameHash(Uint3 return bytecode; } -PUBLIC STATIC bool ScriptManager::ClassExists(const char* objectName) { +bool ScriptManager::ClassExists(const char* objectName) { return SourceFileMap::ClassMap->Exists(objectName); } -PUBLIC STATIC bool ScriptManager::LoadScript(char* filename) { +bool ScriptManager::LoadScript(char* filename) { if (!filename || !*filename) return false; Uint32 hash = MakeFilenameHash(filename); return LoadScript(hash); } -PUBLIC STATIC bool ScriptManager::LoadScript(const char* filename) { +bool ScriptManager::LoadScript(const char* filename) { return LoadScript((char*)filename); } -PUBLIC STATIC bool ScriptManager::LoadScript(Uint32 hash) { +bool ScriptManager::LoadScript(Uint32 hash) { if (!Sources->Exists(hash)) { BytecodeContainer bytecode = ScriptManager::GetBytecodeFromFilenameHash(hash); if (!bytecode.Data) @@ -837,7 +800,7 @@ PUBLIC STATIC bool ScriptManager::LoadScript(Uint32 hash) { return true; } -PUBLIC STATIC bool ScriptManager::LoadObjectClass(const char* objectName, bool addNativeFunctions) { +bool ScriptManager::LoadObjectClass(const char* objectName, bool addNativeFunctions) { if (!objectName || !*objectName) return false; @@ -886,7 +849,7 @@ PUBLIC STATIC bool ScriptManager::LoadObjectClass(const char* objectName, boo return true; } -PUBLIC STATIC void ScriptManager::AddNativeObjectFunctions(ObjClass* klass) { +void ScriptManager::AddNativeObjectFunctions(ObjClass* klass) { #define DEF_NATIVE(name) ScriptManager::DefineNative(klass, #name, ScriptEntity::VM_##name) DEF_NATIVE(InView); DEF_NATIVE(Animate); @@ -916,7 +879,7 @@ PUBLIC STATIC void ScriptManager::AddNativeObjectFunctions(ObjClass* klass) { DEF_NATIVE(StopAllSounds); #undef DEF_NATIVE } -PUBLIC STATIC ObjClass* ScriptManager::GetObjectClass(const char* className) { +ObjClass* ScriptManager::GetObjectClass(const char* className) { VMValue value = Globals->Get(className); if (IS_CLASS(value)) @@ -924,10 +887,10 @@ PUBLIC STATIC ObjClass* ScriptManager::GetObjectClass(const char* className) { return nullptr; } -PUBLIC STATIC Entity* ScriptManager::ObjectSpawnFunction(ObjectList* list) { +Entity* ScriptManager::ObjectSpawnFunction(ObjectList* list) { return ScriptManager::SpawnObject(list->ObjectName); } -PUBLIC STATIC void ScriptManager::LoadClasses() { +void ScriptManager::LoadClasses() { SourceFileMap::ClassMap->ForAll([](Uint32, vector* filenameHashList) -> void { for (size_t fn = 0; fn < filenameHashList->size(); fn++) { Uint32 filenameHash = (*filenameHashList)[fn]; diff --git a/source/Engine/Bytecode/SourceFileMap.cpp b/source/Engine/Bytecode/SourceFileMap.cpp index 68d4e8ab..39a91086 100644 --- a/source/Engine/Bytecode/SourceFileMap.cpp +++ b/source/Engine/Bytecode/SourceFileMap.cpp @@ -1,18 +1,3 @@ -#if INTERFACE -#include -#include -class SourceFileMap { -public: - static bool Initialized; - static HashMap* Checksums; - static HashMap*>* ClassMap; - static Uint32 DirectoryChecksum; - static Uint32 Magic; - - static bool DoLogging; -}; -#endif - #include #include @@ -33,7 +18,7 @@ Uint32 SourceFileMap::Magic = *(Uint32*)"HMAP"; bool SourceFileMap::DoLogging = false; -PUBLIC STATIC void SourceFileMap::CheckInit() { +void SourceFileMap::CheckInit() { if (SourceFileMap::Initialized) return; if (SourceFileMap::Checksums == NULL) { @@ -100,7 +85,7 @@ PUBLIC STATIC void SourceFileMap::CheckInit() { SourceFileMap::Initialized = true; } -PUBLIC STATIC void SourceFileMap::CheckForUpdate() { +void SourceFileMap::CheckForUpdate() { SourceFileMap::CheckInit(); #ifndef NO_SCRIPT_COMPILING @@ -276,7 +261,7 @@ PUBLIC STATIC void SourceFileMap::CheckForUpdate() { #endif } -PUBLIC STATIC void SourceFileMap::Dispose() { +void SourceFileMap::Dispose() { if (SourceFileMap::Checksums) { delete SourceFileMap::Checksums; } diff --git a/source/Engine/Bytecode/StandardLibrary.cpp b/source/Engine/Bytecode/StandardLibrary.cpp index a9b6968b..6b5c1061 100644 --- a/source/Engine/Bytecode/StandardLibrary.cpp +++ b/source/Engine/Bytecode/StandardLibrary.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class StandardLibrary { -public: - -}; -#endif - #include #include @@ -356,45 +345,45 @@ namespace LOCAL { // NOTE: // Integers specifically need to be whole integers. // Floats can be just any countable real number. -PUBLIC STATIC int StandardLibrary::GetInteger(VMValue* args, int index, Uint32 threadID) { +int StandardLibrary::GetInteger(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetInteger(args, index, threadID); } -PUBLIC STATIC float StandardLibrary::GetDecimal(VMValue* args, int index, Uint32 threadID) { +float StandardLibrary::GetDecimal(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetDecimal(args, index, threadID); } -PUBLIC STATIC char* StandardLibrary::GetString(VMValue* args, int index, Uint32 threadID) { +char* StandardLibrary::GetString(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetString(args, index, threadID); } -PUBLIC STATIC ObjString* StandardLibrary::GetVMString(VMValue* args, int index, Uint32 threadID) { +ObjString* StandardLibrary::GetVMString(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetVMString(args, index, threadID); } -PUBLIC STATIC ObjArray* StandardLibrary::GetArray(VMValue* args, int index, Uint32 threadID) { +ObjArray* StandardLibrary::GetArray(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetArray(args, index, threadID); } -PUBLIC STATIC ObjMap* StandardLibrary::GetMap(VMValue* args, int index, Uint32 threadID) { +ObjMap* StandardLibrary::GetMap(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetMap(args, index, threadID); } -PUBLIC STATIC ISprite* StandardLibrary::GetSprite(VMValue* args, int index, Uint32 threadID) { +ISprite* StandardLibrary::GetSprite(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetSprite(args, index, threadID); } -PUBLIC STATIC ISound* StandardLibrary::GetSound(VMValue* args, int index, Uint32 threadID) { +ISound* StandardLibrary::GetSound(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetSound(args, index, threadID); } -PUBLIC STATIC ObjInstance* StandardLibrary::GetInstance(VMValue* args, int index, Uint32 threadID) { +ObjInstance* StandardLibrary::GetInstance(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetInstance(args, index, threadID); } -PUBLIC STATIC ObjFunction* StandardLibrary::GetFunction(VMValue* args, int index, Uint32 threadID) { +ObjFunction* StandardLibrary::GetFunction(VMValue* args, int index, Uint32 threadID) { return LOCAL::GetFunction(args, index, threadID); } -PUBLIC STATIC void StandardLibrary::CheckArgCount(int argCount, int expects) { +void StandardLibrary::CheckArgCount(int argCount, int expects) { Uint32 threadID = 0; if (argCount != expects) { if (THROW_ERROR("Expected %d arguments but got %d.", expects, argCount) == ERROR_RES_CONTINUE) ScriptManager::Threads[threadID].ReturnFromNative(); } } -PUBLIC STATIC void StandardLibrary::CheckAtLeastArgCount(int argCount, int expects) { +void StandardLibrary::CheckAtLeastArgCount(int argCount, int expects) { Uint32 threadID = 0; if (argCount < expects) { if (THROW_ERROR("Expected at least %d arguments but got %d.", expects, argCount) == ERROR_RES_CONTINUE) @@ -16423,7 +16412,7 @@ ObjNamespace* InitNamespace(const char* nsName) { return ns; } -PUBLIC STATIC void StandardLibrary::Link() { +void StandardLibrary::Link() { ObjClass* klass; for (int i = 0; i < 0x100; i++) { @@ -19355,6 +19344,6 @@ PUBLIC STATIC void StandardLibrary::Link() { #undef DEF_ENUM_CLASS #undef DEF_ENUM_NAMED } -PUBLIC STATIC void StandardLibrary::Dispose() { +void StandardLibrary::Dispose() { } diff --git a/source/Engine/Bytecode/TypeImpl/ArrayImpl.cpp b/source/Engine/Bytecode/TypeImpl/ArrayImpl.cpp index dce38d6a..f16f0c18 100644 --- a/source/Engine/Bytecode/TypeImpl/ArrayImpl.cpp +++ b/source/Engine/Bytecode/TypeImpl/ArrayImpl.cpp @@ -1,20 +1,10 @@ -#if INTERFACE -#include -#include - -class ArrayImpl { -public: - static ObjClass *Class; -}; -#endif - #include #include #include ObjClass* ArrayImpl::Class = nullptr; -PUBLIC STATIC void ArrayImpl::Init() { +void ArrayImpl::Init() { const char *name = "$$ArrayImpl"; Class = NewClass(Murmur::EncryptString(name)); @@ -28,7 +18,7 @@ PUBLIC STATIC void ArrayImpl::Init() { #define GET_ARG(argIndex, argFunction) (StandardLibrary::argFunction(args, argIndex, threadID)) -PUBLIC STATIC VMValue ArrayImpl::VM_Iterate(int argCount, VMValue* args, Uint32 threadID) { +VMValue ArrayImpl::VM_Iterate(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ObjArray* array = GET_ARG(0, GetArray); @@ -44,7 +34,7 @@ PUBLIC STATIC VMValue ArrayImpl::VM_Iterate(int argCount, VMValue* args, Uint32 return NULL_VAL; } -PUBLIC STATIC VMValue ArrayImpl::VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID) { +VMValue ArrayImpl::VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ObjArray* array = GET_ARG(0, GetArray); diff --git a/source/Engine/Bytecode/TypeImpl/FunctionImpl.cpp b/source/Engine/Bytecode/TypeImpl/FunctionImpl.cpp index 7550f495..01842710 100644 --- a/source/Engine/Bytecode/TypeImpl/FunctionImpl.cpp +++ b/source/Engine/Bytecode/TypeImpl/FunctionImpl.cpp @@ -1,20 +1,10 @@ -#if INTERFACE -#include -#include - -class FunctionImpl { -public: - static ObjClass *Class; -}; -#endif - #include #include #include ObjClass* FunctionImpl::Class = nullptr; -PUBLIC STATIC void FunctionImpl::Init() { +void FunctionImpl::Init() { const char *name = "$$FunctionImpl"; Class = NewClass(Murmur::EncryptString(name)); @@ -27,7 +17,7 @@ PUBLIC STATIC void FunctionImpl::Init() { #define GET_ARG(argIndex, argFunction) (StandardLibrary::argFunction(args, argIndex, threadID)) -PUBLIC STATIC VMValue FunctionImpl::VM_Bind(int argCount, VMValue* args, Uint32 threadID) { +VMValue FunctionImpl::VM_Bind(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ObjFunction* function = GET_ARG(0, GetFunction); diff --git a/source/Engine/Bytecode/TypeImpl/MapImpl.cpp b/source/Engine/Bytecode/TypeImpl/MapImpl.cpp index de686198..98357d42 100644 --- a/source/Engine/Bytecode/TypeImpl/MapImpl.cpp +++ b/source/Engine/Bytecode/TypeImpl/MapImpl.cpp @@ -1,20 +1,10 @@ -#if INTERFACE -#include -#include - -class MapImpl { -public: - static ObjClass *Class; -}; -#endif - #include #include #include ObjClass* MapImpl::Class = nullptr; -PUBLIC STATIC void MapImpl::Init() { +void MapImpl::Init() { const char *name = "$$MapImpl"; Class = NewClass(Murmur::EncryptString(name)); @@ -29,7 +19,7 @@ PUBLIC STATIC void MapImpl::Init() { #define GET_ARG(argIndex, argFunction) (StandardLibrary::argFunction(args, argIndex, threadID)) -PUBLIC STATIC VMValue MapImpl::VM_GetKeys(int argCount, VMValue* args, Uint32 threadID) { +VMValue MapImpl::VM_GetKeys(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 1); ObjMap* map = GET_ARG(0, GetMap); @@ -43,7 +33,7 @@ PUBLIC STATIC VMValue MapImpl::VM_GetKeys(int argCount, VMValue* args, Uint32 th return OBJECT_VAL(array); } -PUBLIC STATIC VMValue MapImpl::VM_Iterate(int argCount, VMValue* args, Uint32 threadID) { +VMValue MapImpl::VM_Iterate(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ObjMap* map = GET_ARG(0, GetMap); @@ -60,7 +50,7 @@ PUBLIC STATIC VMValue MapImpl::VM_Iterate(int argCount, VMValue* args, Uint32 th return NULL_VAL; } -PUBLIC STATIC VMValue MapImpl::VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID) { +VMValue MapImpl::VM_IteratorValue(int argCount, VMValue* args, Uint32 threadID) { StandardLibrary::CheckArgCount(argCount, 2); ObjMap* map = GET_ARG(0, GetMap); diff --git a/source/Engine/Bytecode/TypeImpl/StringImpl.cpp b/source/Engine/Bytecode/TypeImpl/StringImpl.cpp index 83114f4f..82875c8d 100644 --- a/source/Engine/Bytecode/TypeImpl/StringImpl.cpp +++ b/source/Engine/Bytecode/TypeImpl/StringImpl.cpp @@ -1,20 +1,10 @@ -#if INTERFACE -#include -#include - -class StringImpl { -public: - static ObjClass *Class; -}; -#endif - #include #include #include ObjClass* StringImpl::Class = nullptr; -PUBLIC STATIC void StringImpl::Init() { +void StringImpl::Init() { const char *name = "$$StringImpl"; Class = NewClass(Murmur::EncryptString(name)); @@ -29,7 +19,7 @@ PUBLIC STATIC void StringImpl::Init() { #define THROW_ERROR(...) ScriptManager::Threads[threadID].ThrowRuntimeError(false, __VA_ARGS__) -PUBLIC STATIC bool StringImpl::VM_ElementGet(Obj* object, VMValue at, VMValue* result, Uint32 threadID) { +bool StringImpl::VM_ElementGet(Obj* object, VMValue at, VMValue* result, Uint32 threadID) { ObjString* string = (ObjString*)object; if (!IS_INTEGER(at)) { @@ -55,7 +45,7 @@ PUBLIC STATIC bool StringImpl::VM_ElementGet(Obj* object, VMValue at, VMValue* r return true; } #if 0 -PUBLIC STATIC bool StringImpl::VM_ElementSet(Obj* object, VMValue at, VMValue value, Uint32 threadID) { +bool StringImpl::VM_ElementSet(Obj* object, VMValue at, VMValue value, Uint32 threadID) { ObjString* string = (ObjString*)object; if (!IS_INTEGER(at)) { diff --git a/source/Engine/Bytecode/VMThread.cpp b/source/Engine/Bytecode/VMThread.cpp index 92c79c18..c3b6b0c4 100644 --- a/source/Engine/Bytecode/VMThread.cpp +++ b/source/Engine/Bytecode/VMThread.cpp @@ -1,39 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class VMThread { -public: - VMValue Stack[STACK_SIZE_MAX]; - VMValue* StackTop = Stack; - VMValue RegisterValue; - - CallFrame Frames[FRAMES_MAX]; - Uint32 FrameCount; - Uint32 ReturnFrame; - - VMValue FunctionToInvoke; - VMValue InterpretResult; - - enum ThreadState { - CREATED = 0, - RUNNING = 1, - WAITING = 2, - CLOSED = 3, - }; - - char Name[THREAD_NAME_MAX]; - Uint32 ID; - - bool DebugInfo; - Uint32 BranchLimit; - - static bool InstructionIgnoreMap[0x100]; - static std::jmp_buf JumpBuffer; -}; -#endif - #include #include #include @@ -108,7 +72,7 @@ std::jmp_buf VMThread::JumpBuffer; return ERROR_RES_CONTINUE; \ } -PRIVATE string VMThread::GetFunctionName(ObjFunction* function) { +string VMThread::GetFunctionName(ObjFunction* function) { std::string functionName(GetToken(function->NameHash)); if (functionName == "main") @@ -123,7 +87,7 @@ PRIVATE string VMThread::GetFunctionName(ObjFunction* function) { return functionName; } -PUBLIC STATIC char* VMThread::GetToken(Uint32 hash) { +char* VMThread::GetToken(Uint32 hash) { static char GetTokenBuffer[256]; if (__Tokens__ && __Tokens__->Exists(hash)) @@ -132,7 +96,7 @@ PUBLIC STATIC char* VMThread::GetToken(Uint32 hash) { snprintf(GetTokenBuffer, 15, "%X", hash); return GetTokenBuffer; } -PUBLIC STATIC char* VMThread::GetVariableOrMethodName(Uint32 hash) { +char* VMThread::GetVariableOrMethodName(Uint32 hash) { static char GetTokenBuffer[256]; if (__Tokens__ && __Tokens__->Exists(hash)) { @@ -144,7 +108,7 @@ PUBLIC STATIC char* VMThread::GetVariableOrMethodName(Uint32 hash) { return GetTokenBuffer; } -PRIVATE void VMThread::PrintStackTrace(PrintBuffer* buffer, const char* errorString) { +void VMThread::PrintStackTrace(PrintBuffer* buffer, const char* errorString) { int line; char* source; @@ -194,7 +158,7 @@ PRIVATE void VMThread::PrintStackTrace(PrintBuffer* buffer, const char* error buffer_printf(buffer, "\n"); } } -PUBLIC void VMThread::MakeErrorMessage(PrintBuffer* buffer, const char* errorString) { +void VMThread::MakeErrorMessage(PrintBuffer* buffer, const char* errorString) { if (FrameCount > 0) PrintStackTrace(buffer, errorString); else if (IS_OBJECT(FunctionToInvoke)) { @@ -227,7 +191,7 @@ PUBLIC void VMThread::MakeErrorMessage(PrintBuffer* buffer, const char* error buffer_printf(buffer, "%s\n", errorString); } } -PUBLIC int VMThread::ThrowRuntimeError(bool fatal, const char* errorMessage, ...) { +int VMThread::ThrowRuntimeError(bool fatal, const char* errorMessage, ...) { bool showMessageBox = true; if (VMThread::InstructionIgnoreMap[000000000]) { showMessageBox = false; @@ -241,7 +205,7 @@ PUBLIC int VMThread::ThrowRuntimeError(bool fatal, const char* errorMessage, return ERROR_RES_CONTINUE; } -PUBLIC void VMThread::PrintStack() { +void VMThread::PrintStack() { int i = 0; printf("Stack:\n"); for (VMValue* v = StackTop - 1; v >= Stack; v--) { @@ -251,13 +215,13 @@ PUBLIC void VMThread::PrintStack() { i--; } } -PUBLIC void VMThread::ReturnFromNative() throw() { +void VMThread::ReturnFromNative() throw() { } // #endregion // #region Stack stuff -PUBLIC void VMThread::Push(VMValue value) { +void VMThread::Push(VMValue value) { if (StackSize() == STACK_SIZE_MAX) { if (ThrowRuntimeError(true, "Stack overflow! \nStack Top: %p \nStack: %p\nCount: %d", StackTop, Stack, StackSize()) == ERROR_RES_CONTINUE) return; @@ -265,7 +229,7 @@ PUBLIC void VMThread::Push(VMValue value) { *(StackTop++) = value; } -PUBLIC VMValue VMThread::Pop() { +VMValue VMThread::Pop() { if (StackTop == Stack) { if (ThrowRuntimeError(true, "Stack underflow!") == ERROR_RES_CONTINUE) return *StackTop; @@ -274,17 +238,17 @@ PUBLIC VMValue VMThread::Pop() { StackTop--; return *StackTop; } -PUBLIC void VMThread::Pop(unsigned amount) { +void VMThread::Pop(unsigned amount) { while (amount-- > 0) Pop(); } -PUBLIC VMValue VMThread::Peek(int offset) { +VMValue VMThread::Peek(int offset) { return *(StackTop - offset - 1); } -PUBLIC Uint32 VMThread::StackSize() { +Uint32 VMThread::StackSize() { return (Uint32)(StackTop - Stack); } -PUBLIC void VMThread::ResetStack() { +void VMThread::ResetStack() { // bool debugInstruction = ID == 1; // if (debugInstruction) printf("reset stack\n"); @@ -302,25 +266,25 @@ enum ThreadReturnCodes { }; // NOTE: These should be inlined -PUBLIC Uint8 VMThread::ReadByte(CallFrame* frame) { +Uint8 VMThread::ReadByte(CallFrame* frame) { frame->IP += sizeof(Uint8); return *(Uint8*)(frame->IP - sizeof(Uint8)); } -PUBLIC Uint16 VMThread::ReadUInt16(CallFrame* frame) { +Uint16 VMThread::ReadUInt16(CallFrame* frame) { frame->IP += sizeof(Uint16); return *(Uint16*)(frame->IP - sizeof(Uint16)); } -PUBLIC Uint32 VMThread::ReadUInt32(CallFrame* frame) { +Uint32 VMThread::ReadUInt32(CallFrame* frame) { frame->IP += sizeof(Uint32); return *(Uint32*)(frame->IP - sizeof(Uint32)); } -PUBLIC Sint16 VMThread::ReadSInt16(CallFrame* frame) { +Sint16 VMThread::ReadSInt16(CallFrame* frame) { return (Sint16)ReadUInt16(frame); } -PUBLIC Sint32 VMThread::ReadSInt32(CallFrame* frame) { +Sint32 VMThread::ReadSInt32(CallFrame* frame) { return (Sint32)ReadUInt32(frame); } -PUBLIC VMValue VMThread::ReadConstant(CallFrame* frame) { +VMValue VMThread::ReadConstant(CallFrame* frame) { return (*frame->Function->Chunk.Constants)[ReadUInt32(frame)]; } @@ -335,7 +299,7 @@ PUBLIC VMValue VMThread::ReadConstant(CallFrame* frame) { } #ifdef VM_DEBUG -PUBLIC bool VMThread::ShowBranchLimitMessage(const char* errorMessage, ...) { +bool VMThread::ShowBranchLimitMessage(const char* errorMessage, ...) { va_list args; char errorString[2048]; va_start(args, errorMessage); @@ -395,18 +359,18 @@ PUBLIC bool VMThread::ShowBranchLimitMessage(const char* errorMessage, ...) { return true; } -PRIVATE bool VMThread::CheckBranchLimit(CallFrame* frame) { +bool VMThread::CheckBranchLimit(CallFrame* frame) { if (BranchLimit && ++frame->BranchCount >= BranchLimit) { return ShowBranchLimitMessage("Hit branch limit!"); } return true; } -PRIVATE bool VMThread::DoJump(CallFrame* frame, int offset) { +bool VMThread::DoJump(CallFrame* frame, int offset) { frame->IP += offset; return CheckBranchLimit(frame); } -PRIVATE bool VMThread::DoJumpBack(CallFrame* frame, int offset) { +bool VMThread::DoJumpBack(CallFrame* frame, int offset) { frame->IP -= offset; return CheckBranchLimit(frame); } @@ -434,7 +398,7 @@ PRIVATE bool VMThread::DoJumpBack(CallFrame* frame, int offset) { #define JUMP_BACK(offset) { frame->IP -= offset; } #endif -PUBLIC int VMThread::RunInstruction() { +int VMThread::RunInstruction() { // NOTE: MSVC cannot take advantage of the dispatch table. #ifdef USING_VM_DISPATCH_TABLE #define VM_ADD_DISPATCH(op) &&START_ ## op @@ -1877,7 +1841,7 @@ PUBLIC int VMThread::RunInstruction() { return INTERPRET_OK; } -PUBLIC void VMThread::RunInstructionSet() { +void VMThread::RunInstructionSet() { while (true) { // if (!ScriptManager::Lock()) break; @@ -1893,7 +1857,7 @@ PUBLIC void VMThread::RunInstructionSet() { } // #endregion -PUBLIC void VMThread::RunValue(VMValue value, int argCount) { +void VMThread::RunValue(VMValue value, int argCount) { int lastReturnFrame = ReturnFrame; ReturnFrame = FrameCount; @@ -1901,7 +1865,7 @@ PUBLIC void VMThread::RunValue(VMValue value, int argCount) { RunInstructionSet(); ReturnFrame = lastReturnFrame; } -PUBLIC void VMThread::RunFunction(ObjFunction* func, int argCount) { +void VMThread::RunFunction(ObjFunction* func, int argCount) { VMValue* lastStackTop = StackTop; int lastReturnFrame = ReturnFrame; @@ -1913,7 +1877,7 @@ PUBLIC void VMThread::RunFunction(ObjFunction* func, int argCount) { ReturnFrame = lastReturnFrame; StackTop = lastStackTop; } -PUBLIC void VMThread::InvokeForEntity(VMValue value, int argCount) { +void VMThread::InvokeForEntity(VMValue value, int argCount) { VMValue* lastStackTop = StackTop; int lastReturnFrame = ReturnFrame; @@ -1935,7 +1899,7 @@ PUBLIC void VMThread::InvokeForEntity(VMValue value, int argCount) { ReturnFrame = lastReturnFrame; StackTop = lastStackTop; } -PUBLIC VMValue VMThread::RunEntityFunction(ObjFunction* function, int argCount) { +VMValue VMThread::RunEntityFunction(ObjFunction* function, int argCount) { VMValue* lastStackTop = StackTop; int lastReturnFrame = ReturnFrame; @@ -1951,7 +1915,7 @@ PUBLIC VMValue VMThread::RunEntityFunction(ObjFunction* function, int argCount) return InterpretResult; } -PUBLIC void VMThread::CallInitializer(VMValue value) { +void VMThread::CallInitializer(VMValue value) { FunctionToInvoke = value; ObjFunction* initializer = AS_FUNCTION(value); @@ -1973,7 +1937,7 @@ PUBLIC void VMThread::CallInitializer(VMValue value) { FunctionToInvoke = NULL_VAL; } -PRIVATE bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter) { +bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter) { if (ScriptManager::Lock()) { VMValue value; @@ -2012,13 +1976,13 @@ PRIVATE bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash, ScriptManager::Unlock(); return false; } -PRIVATE bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields) { +bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields) { return GetProperty(object, klass, hash, true, klass->PropertyGet); } -PRIVATE bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash) { +bool VMThread::GetProperty(Obj* object, ObjClass* klass, Uint32 hash) { return GetProperty(object, klass, hash, true); } -PRIVATE bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter) { +bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields, ValueGetFn getter) { if (ScriptManager::Lock()) { if (checkFields && klass->Fields->Exists(hash)) { // Fields have priority over methods @@ -2044,13 +2008,13 @@ PRIVATE bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash, ScriptManager::Unlock(); return false; } -PRIVATE bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields) { +bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash, bool checkFields) { return HasProperty(object, klass, checkFields, klass->PropertyGet); } -PRIVATE bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash) { +bool VMThread::HasProperty(Obj* object, ObjClass* klass, Uint32 hash) { return HasProperty(object, klass, true); } -PRIVATE bool VMThread::SetProperty(Table* fields, Uint32 hash, VMValue field, VMValue value) { +bool VMThread::SetProperty(Table* fields, Uint32 hash, VMValue field, VMValue value) { switch (field.Type) { case VAL_LINKED_INTEGER: if (!ScriptManager::DoIntegerConversion(value, this->ID)) @@ -2067,18 +2031,18 @@ PRIVATE bool VMThread::SetProperty(Table* fields, Uint32 hash, VMValue field, } return true; } -PRIVATE bool VMThread::BindMethod(VMValue receiver, VMValue method) { +bool VMThread::BindMethod(VMValue receiver, VMValue method) { ObjBoundMethod* bound = NewBoundMethod(receiver, AS_FUNCTION(method)); Push(OBJECT_VAL(bound)); return true; } -PRIVATE bool VMThread::CallBoundMethod(ObjBoundMethod* bound, int argCount) { +bool VMThread::CallBoundMethod(ObjBoundMethod* bound, int argCount) { // Replace the bound method with the receiver so it's in the // right slot when the method is called. StackTop[-argCount - 1] = bound->Receiver; return Call(bound->Method, argCount); } -PRIVATE bool VMThread::CallValue(VMValue callee, int argCount) { +bool VMThread::CallValue(VMValue callee, int argCount) { bool result = false; if (ScriptManager::Lock() && IS_OBJECT(callee)) { switch (OBJECT_TYPE(callee)) { @@ -2114,7 +2078,7 @@ PRIVATE bool VMThread::CallValue(VMValue callee, int argCount) { ScriptManager::Unlock(); return result; } -PRIVATE bool VMThread::CallForObject(VMValue callee, int argCount) { +bool VMThread::CallForObject(VMValue callee, int argCount) { if (ScriptManager::Lock()) { // Special case for native functions if (OBJECT_TYPE(callee) == OBJ_NATIVE) { @@ -2143,7 +2107,7 @@ PRIVATE bool VMThread::CallForObject(VMValue callee, int argCount) { } return false; } -PRIVATE bool VMThread::InstantiateClass(VMValue callee, int argCount) { +bool VMThread::InstantiateClass(VMValue callee, int argCount) { if (ScriptManager::Lock()) { bool result = false; if (!IS_OBJECT(callee) || OBJECT_TYPE(callee) != OBJ_CLASS) { @@ -2172,7 +2136,7 @@ PRIVATE bool VMThread::InstantiateClass(VMValue callee, int argCount) { return false; } -PUBLIC bool VMThread::Call(ObjFunction* function, int argCount) { +bool VMThread::Call(ObjFunction* function, int argCount) { if (function->MinArity < function->Arity) { if (argCount < function->MinArity) { ThrowRuntimeError(false, "Expected at least %d arguments to function call, got %d.", function->MinArity, argCount); @@ -2213,7 +2177,7 @@ PUBLIC bool VMThread::Call(ObjFunction* function, int argCount) { return true; } -PUBLIC bool VMThread::InvokeFromClass(ObjClass* klass, Uint32 hash, int argCount) { +bool VMThread::InvokeFromClass(ObjClass* klass, Uint32 hash, int argCount) { if (ScriptManager::Lock()) { VMValue method; if (klass->Methods->GetIfExists(hash, &method)) { @@ -2232,7 +2196,7 @@ PUBLIC bool VMThread::InvokeFromClass(ObjClass* klass, Uint32 hash, int argCo } return false; } -PUBLIC bool VMThread::InvokeForInstance(Uint32 hash, int argCount, bool isSuper) { +bool VMThread::InvokeForInstance(Uint32 hash, int argCount, bool isSuper) { ObjInstance* instance = AS_INSTANCE(Peek(argCount)); ObjClass* klass = instance->Object.Class; @@ -2258,7 +2222,7 @@ PUBLIC bool VMThread::InvokeForInstance(Uint32 hash, int argCount, bool isSup } return InvokeFromClass(klass, hash, argCount); } -PRIVATE bool VMThread::DoClassExtension(VMValue value, VMValue originalValue, bool clearSrc) { +bool VMThread::DoClassExtension(VMValue value, VMValue originalValue, bool clearSrc) { ObjClass* src = AS_CLASS(value); ObjClass* dst = AS_CLASS(originalValue); @@ -2276,7 +2240,7 @@ PRIVATE bool VMThread::DoClassExtension(VMValue value, VMValue originalValue, return true; } -PUBLIC bool VMThread::Import(VMValue value) { +bool VMThread::Import(VMValue value) { bool result = false; if (ScriptManager::Lock()) { if (!IS_OBJECT(value) || OBJECT_TYPE(value) != OBJ_STRING) { @@ -2298,7 +2262,7 @@ PUBLIC bool VMThread::Import(VMValue value) { ScriptManager::Unlock(); return result; } -PUBLIC bool VMThread::ImportModule(VMValue value) { +bool VMThread::ImportModule(VMValue value) { bool result = false; if (ScriptManager::Lock()) { if (!IS_OBJECT(value) || OBJECT_TYPE(value) != OBJ_STRING) { @@ -2327,7 +2291,7 @@ PUBLIC bool VMThread::ImportModule(VMValue value) { // If one of the operators is a decimal, they both become one -PUBLIC VMValue VMThread::Values_Multiply() { +VMValue VMThread::Values_Multiply() { VMValue b = Peek(0); VMValue a = Peek(1); @@ -2346,7 +2310,7 @@ PUBLIC VMValue VMThread::Values_Multiply() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d * b_d); } -PUBLIC VMValue VMThread::Values_Division() { +VMValue VMThread::Values_Division() { VMValue b = Pop(); VMValue a = Pop(); @@ -2370,7 +2334,7 @@ PUBLIC VMValue VMThread::Values_Division() { } return INTEGER_VAL(a_d / b_d); } -PUBLIC VMValue VMThread::Values_Modulo() { +VMValue VMThread::Values_Modulo() { VMValue b = Pop(); VMValue a = Pop(); @@ -2386,7 +2350,7 @@ PUBLIC VMValue VMThread::Values_Modulo() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d % b_d); } -PUBLIC VMValue VMThread::Values_Plus() { +VMValue VMThread::Values_Plus() { VMValue b = Peek(0); VMValue a = Peek(1); if (IS_STRING(a) || IS_STRING(b)) { @@ -2417,7 +2381,7 @@ PUBLIC VMValue VMThread::Values_Plus() { Pop(); return INTEGER_VAL(a_d + b_d); } -PUBLIC VMValue VMThread::Values_Minus() { +VMValue VMThread::Values_Minus() { VMValue b = Peek(0); VMValue a = Peek(1); @@ -2436,7 +2400,7 @@ PUBLIC VMValue VMThread::Values_Minus() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d - b_d); } -PUBLIC VMValue VMThread::Values_BitwiseLeft() { +VMValue VMThread::Values_BitwiseLeft() { VMValue b = Pop(); VMValue a = Pop(); @@ -2452,7 +2416,7 @@ PUBLIC VMValue VMThread::Values_BitwiseLeft() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d << b_d); } -PUBLIC VMValue VMThread::Values_BitwiseRight() { +VMValue VMThread::Values_BitwiseRight() { VMValue b = Pop(); VMValue a = Pop(); @@ -2468,7 +2432,7 @@ PUBLIC VMValue VMThread::Values_BitwiseRight() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d >> b_d); } -PUBLIC VMValue VMThread::Values_BitwiseAnd() { +VMValue VMThread::Values_BitwiseAnd() { VMValue b = Pop(); VMValue a = Pop(); @@ -2484,7 +2448,7 @@ PUBLIC VMValue VMThread::Values_BitwiseAnd() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d & b_d); } -PUBLIC VMValue VMThread::Values_BitwiseXor() { +VMValue VMThread::Values_BitwiseXor() { VMValue b = Pop(); VMValue a = Pop(); @@ -2500,7 +2464,7 @@ PUBLIC VMValue VMThread::Values_BitwiseXor() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d ^ b_d); } -PUBLIC VMValue VMThread::Values_BitwiseOr() { +VMValue VMThread::Values_BitwiseOr() { VMValue b = Pop(); VMValue a = Pop(); @@ -2516,7 +2480,7 @@ PUBLIC VMValue VMThread::Values_BitwiseOr() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d | b_d); } -PUBLIC VMValue VMThread::Values_LogicalAND() { +VMValue VMThread::Values_LogicalAND() { VMValue b = Pop(); VMValue a = Pop(); @@ -2533,7 +2497,7 @@ PUBLIC VMValue VMThread::Values_LogicalAND() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d && b_d); } -PUBLIC VMValue VMThread::Values_LogicalOR() { +VMValue VMThread::Values_LogicalOR() { VMValue b = Pop(); VMValue a = Pop(); @@ -2550,7 +2514,7 @@ PUBLIC VMValue VMThread::Values_LogicalOR() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d || b_d); } -PUBLIC VMValue VMThread::Values_LessThan() { +VMValue VMThread::Values_LessThan() { VMValue b = Pop(); VMValue a = Pop(); @@ -2566,7 +2530,7 @@ PUBLIC VMValue VMThread::Values_LessThan() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d < b_d); } -PUBLIC VMValue VMThread::Values_GreaterThan() { +VMValue VMThread::Values_GreaterThan() { VMValue b = Pop(); VMValue a = Pop(); @@ -2582,7 +2546,7 @@ PUBLIC VMValue VMThread::Values_GreaterThan() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d > b_d); } -PUBLIC VMValue VMThread::Values_LessThanOrEqual() { +VMValue VMThread::Values_LessThanOrEqual() { VMValue b = Pop(); VMValue a = Pop(); @@ -2598,7 +2562,7 @@ PUBLIC VMValue VMThread::Values_LessThanOrEqual() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d <= b_d); } -PUBLIC VMValue VMThread::Values_GreaterThanOrEqual() { +VMValue VMThread::Values_GreaterThanOrEqual() { VMValue b = Pop(); VMValue a = Pop(); @@ -2614,7 +2578,7 @@ PUBLIC VMValue VMThread::Values_GreaterThanOrEqual() { int b_d = AS_INTEGER(b); return INTEGER_VAL(a_d >= b_d); } -PUBLIC VMValue VMThread::Values_Increment() { +VMValue VMThread::Values_Increment() { VMValue a = Pop(); CHECK_IS_NUM(a, "increment", INTEGER_VAL(0)); @@ -2626,7 +2590,7 @@ PUBLIC VMValue VMThread::Values_Increment() { int a_d = AS_INTEGER(a); return INTEGER_VAL(++a_d); } -PUBLIC VMValue VMThread::Values_Decrement() { +VMValue VMThread::Values_Decrement() { VMValue a = Pop(); CHECK_IS_NUM(a, "decrement", INTEGER_VAL(0)); @@ -2638,7 +2602,7 @@ PUBLIC VMValue VMThread::Values_Decrement() { int a_d = AS_INTEGER(a); return INTEGER_VAL(--a_d); } -PUBLIC VMValue VMThread::Values_Negate() { +VMValue VMThread::Values_Negate() { VMValue a = Pop(); CHECK_IS_NUM(a, "negate", INTEGER_VAL(0)); @@ -2648,7 +2612,7 @@ PUBLIC VMValue VMThread::Values_Negate() { } return INTEGER_VAL(-AS_INTEGER(a)); } -PUBLIC VMValue VMThread::Values_LogicalNOT() { +VMValue VMThread::Values_LogicalNOT() { VMValue a = Pop(); // HACK: Yikes. @@ -2667,14 +2631,14 @@ PUBLIC VMValue VMThread::Values_LogicalNOT() { return INTEGER_VAL(false); } -PUBLIC VMValue VMThread::Values_BitwiseNOT() { +VMValue VMThread::Values_BitwiseNOT() { VMValue a = Pop(); if (a.Type == VAL_DECIMAL) { return DECIMAL_VAL((float)(~(int)AS_DECIMAL(a))); } return INTEGER_VAL(~AS_INTEGER(a)); } -PUBLIC VMValue VMThread::Value_TypeOf() { +VMValue VMThread::Value_TypeOf() { const char *valueType = "unknown"; VMValue value = Pop(); diff --git a/source/Engine/Bytecode/Values.cpp b/source/Engine/Bytecode/Values.cpp index 91e9b85d..8c105084 100644 --- a/source/Engine/Bytecode/Values.cpp +++ b/source/Engine/Bytecode/Values.cpp @@ -1,13 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class Values { -public: -}; -#endif - #include #include @@ -15,16 +5,16 @@ class Values { #include // NOTE: This is for printing, not string conversion -PUBLIC STATIC void Values::PrintValue(VMValue value) { +void Values::PrintValue(VMValue value) { Values::PrintValue(NULL, value); } -PUBLIC STATIC void Values::PrintValue(PrintBuffer* buffer, VMValue value) { +void Values::PrintValue(PrintBuffer* buffer, VMValue value) { Values::PrintValue(buffer, value, 0, false); } -PUBLIC STATIC void Values::PrintValue(PrintBuffer* buffer, VMValue value, bool prettyPrint) { +void Values::PrintValue(PrintBuffer* buffer, VMValue value, bool prettyPrint) { Values::PrintValue(buffer, value, 0, prettyPrint); } -PUBLIC STATIC void Values::PrintValue(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint) { +void Values::PrintValue(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint) { switch (value.Type) { case VAL_NULL: buffer_printf(buffer, "null"); @@ -44,7 +34,7 @@ PUBLIC STATIC void Values::PrintValue(PrintBuffer* buffer, VMValue value, int in buffer_printf(buffer, "", value.Type); } } -PUBLIC STATIC void Values::PrintObject(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint) { +void Values::PrintObject(PrintBuffer* buffer, VMValue value, int indent, bool prettyPrint) { switch (OBJECT_TYPE(value)) { case OBJ_CLASS: buffer_printf(buffer, "", AS_CLASS(value)->Name ? AS_CLASS(value)->Name->Chars : "(null)"); diff --git a/source/Engine/Diagnostics/Clock.cpp b/source/Engine/Diagnostics/Clock.cpp index cda13327..e39a568b 100644 --- a/source/Engine/Diagnostics/Clock.cpp +++ b/source/Engine/Diagnostics/Clock.cpp @@ -1,11 +1,3 @@ -#if INTERFACE -#include - -class Clock { -public: -}; -#endif - #include #include @@ -30,7 +22,7 @@ class Clock { std::chrono::steady_clock::time_point GameStartTime; stack ClockStack; -PUBLIC STATIC void Clock::Init() { +void Clock::Init() { #ifdef USE_WIN32_CLOCK LARGE_INTEGER Win32_Frequency; @@ -52,7 +44,7 @@ PUBLIC STATIC void Clock::Init() { GameStartTime = std::chrono::steady_clock::now(); } -PUBLIC STATIC void Clock::Start() { +void Clock::Start() { #ifdef USE_WIN32_CLOCK if (Win32_PerformanceFrequencyEnabled) { Win32_ClockStack.push(Clock::GetTicks()); @@ -62,7 +54,7 @@ PUBLIC STATIC void Clock::Start() { ClockStack.push(std::chrono::steady_clock::now()); } -PUBLIC STATIC double Clock::GetTicks() { +double Clock::GetTicks() { #ifdef USE_WIN32_CLOCK if (Win32_PerformanceFrequencyEnabled) { LARGE_INTEGER ticks; @@ -76,7 +68,7 @@ PUBLIC STATIC double Clock::GetTicks() { return (std::chrono::steady_clock::now() - GameStartTime).count() / 1000000.0; } -PUBLIC STATIC double Clock::End() { +double Clock::End() { #ifdef USE_WIN32_CLOCK if (Win32_PerformanceFrequencyEnabled) { auto t1 = Win32_ClockStack.top(); @@ -91,7 +83,7 @@ PUBLIC STATIC double Clock::End() { ClockStack.pop(); return (t2 - t1).count() / 1000000.0; } -PUBLIC STATIC void Clock::Delay(double milliseconds) { +void Clock::Delay(double milliseconds) { #ifdef USE_WIN32_CLOCK if (Win32_PerformanceFrequencyEnabled) { Sleep((DWORD)milliseconds); diff --git a/source/Engine/Diagnostics/Log.cpp b/source/Engine/Diagnostics/Log.cpp index 8306c86b..f29f744b 100644 --- a/source/Engine/Diagnostics/Log.cpp +++ b/source/Engine/Diagnostics/Log.cpp @@ -1,20 +1,3 @@ -#if INTERFACE -class Log { -public: - enum LogLevels { - LOG_VERBOSE = -1, - LOG_INFO = 0, - LOG_WARN = 1, - LOG_ERROR = 2, - LOG_IMPORTANT = 3, - }; - - static int LogLevel; - static const char* LogFilename; - static bool WriteToFile; -}; -#endif - #include #include @@ -47,7 +30,7 @@ bool Log_Initialized = false; #define USING_COLOR_CODES 1 #endif -PUBLIC STATIC void Log::Init() { +void Log::Init() { if (Log_Initialized) return; @@ -84,11 +67,11 @@ PUBLIC STATIC void Log::Init() { Log_Initialized = true; } -PUBLIC STATIC void Log::SetLogLevel(int sev) { +void Log::SetLogLevel(int sev) { Log::LogLevel = sev; } -PUBLIC STATIC void Log::Print(int sev, const char* format, ...) { +void Log::Print(int sev, const char* format, ...) { #ifdef USING_COLOR_CODES int ColorCode = 0; #endif diff --git a/source/Engine/Diagnostics/Memory.cpp b/source/Engine/Diagnostics/Memory.cpp index f972733a..cd39c93e 100644 --- a/source/Engine/Diagnostics/Memory.cpp +++ b/source/Engine/Diagnostics/Memory.cpp @@ -1,32 +1,13 @@ -#if INTERFACE - -#include - -class Memory { -private: - static vector TrackedMemory; - static vector TrackedSizes; - static vector TrackedMemoryNames; -public: - static size_t MemoryUsage; - static bool IsTracking; -}; -#endif - #include #include -// #if defined(ANDROID) -// #define NOTRACK -// #endif - vector Memory::TrackedMemory; vector Memory::TrackedSizes; vector Memory::TrackedMemoryNames; size_t Memory::MemoryUsage = 0; bool Memory::IsTracking = false; -PUBLIC STATIC void Memory::Memset4(void* dst, Uint32 val, size_t dwords) { +void Memory::Memset4(void* dst, Uint32 val, size_t dwords) { #if defined(__GNUC__) && defined(i386) int u0, u1, u2; __asm__ __volatile__ ( @@ -53,7 +34,7 @@ PUBLIC STATIC void Memory::Memset4(void* dst, Uint32 val, size_t dwords) { #endif } -PUBLIC STATIC void* Memory::Malloc(size_t size) { +void* Memory::Malloc(size_t size) { void* mem = malloc(size); if (Memory::IsTracking) { if (mem) { @@ -69,7 +50,7 @@ PUBLIC STATIC void* Memory::Malloc(size_t size) { } return mem; } -PUBLIC STATIC void* Memory::Calloc(size_t count, size_t size) { +void* Memory::Calloc(size_t count, size_t size) { void* mem = calloc(count, size); if (Memory::IsTracking) { if (mem) { @@ -85,7 +66,7 @@ PUBLIC STATIC void* Memory::Calloc(size_t count, size_t size) { } return mem; } -PUBLIC STATIC void* Memory::Realloc(void* pointer, size_t size) { +void* Memory::Realloc(void* pointer, size_t size) { void* mem = realloc(pointer, size); if (Memory::IsTracking) { if (mem) { @@ -106,7 +87,7 @@ PUBLIC STATIC void* Memory::Realloc(void* pointer, size_t size) { return mem; } // Tracking functions -PUBLIC STATIC void* Memory::TrackedMalloc(const char* identifier, size_t size) { +void* Memory::TrackedMalloc(const char* identifier, size_t size) { void* mem = malloc(size); if (Memory::IsTracking) { if (mem) { @@ -125,7 +106,7 @@ PUBLIC STATIC void* Memory::TrackedMalloc(const char* identifier, size_t size) } return mem; } -PUBLIC STATIC void* Memory::TrackedCalloc(const char* identifier, size_t count, size_t size) { +void* Memory::TrackedCalloc(const char* identifier, size_t count, size_t size) { void* mem = calloc(count, size); if (Memory::IsTracking) { if (mem) { @@ -141,7 +122,7 @@ PUBLIC STATIC void* Memory::TrackedCalloc(const char* identifier, size_t count, } return mem; } -PUBLIC STATIC void Memory::Track(void* pointer, const char* identifier) { +void Memory::Track(void* pointer, const char* identifier) { if (Memory::IsTracking) { for (Uint32 i = 0; i < TrackedMemory.size(); i++) { if (TrackedMemory[i] == pointer) { @@ -151,7 +132,7 @@ PUBLIC STATIC void Memory::Track(void* pointer, const char* identifier) { } } } -PUBLIC STATIC void Memory::Track(void* pointer, size_t size, const char* identifier) { +void Memory::Track(void* pointer, size_t size, const char* identifier) { if (Memory::IsTracking) { for (Uint32 i = 0; i < TrackedMemory.size(); i++) { if (TrackedMemory[i] == pointer) { @@ -166,13 +147,13 @@ PUBLIC STATIC void Memory::Track(void* pointer, size_t size, const char* ident TrackedMemoryNames.push_back(identifier); } } -PUBLIC STATIC void Memory::TrackLast(const char* identifier) { +void Memory::TrackLast(const char* identifier) { if (Memory::IsTracking) { if (TrackedMemoryNames.size() == 0) return; TrackedMemoryNames[TrackedMemoryNames.size() - 1] = identifier; } } -PUBLIC STATIC void Memory::Free(void* pointer) { +void Memory::Free(void* pointer) { if (Memory::IsTracking) { #ifdef DEBUG for (Uint32 i = 0; i < TrackedMemory.size(); i++) { @@ -202,7 +183,7 @@ PUBLIC STATIC void Memory::Free(void* pointer) { free(pointer); } -PUBLIC STATIC void Memory::Remove(void* pointer) { +void Memory::Remove(void* pointer) { if (!pointer) return; if (Memory::IsTracking) { for (Uint32 i = 0; i < TrackedMemory.size(); i++) { @@ -219,7 +200,7 @@ PUBLIC STATIC void Memory::Remove(void* pointer) { } } -PUBLIC STATIC const char* Memory::GetName(void* pointer) { +const char* Memory::GetName(void* pointer) { if (Memory::IsTracking) { for (Uint32 i = 0; i < TrackedMemory.size(); i++) { if (TrackedMemory[i] == pointer) { @@ -230,19 +211,19 @@ PUBLIC STATIC const char* Memory::GetName(void* pointer) { return NULL; } -PUBLIC STATIC void Memory::ClearTrackedMemory() { +void Memory::ClearTrackedMemory() { TrackedMemoryNames.clear(); TrackedMemory.clear(); TrackedSizes.clear(); } -PUBLIC STATIC size_t Memory::CheckLeak() { +size_t Memory::CheckLeak() { size_t total = 0; for (Uint32 i = 0; i < TrackedMemory.size(); i++) { total += TrackedSizes[i]; } return total; } -PUBLIC STATIC void Memory::PrintLeak() { +void Memory::PrintLeak() { size_t total = 0; Log::Print(Log::LOG_VERBOSE, "Printing unfreed memory... (%u count)", TrackedMemory.size()); for (Uint32 i = 0; i < TrackedMemory.size(); i++) { diff --git a/source/Engine/Diagnostics/PerformanceMeasure.cpp b/source/Engine/Diagnostics/PerformanceMeasure.cpp index 7fb55be5..47531dd1 100644 --- a/source/Engine/Diagnostics/PerformanceMeasure.cpp +++ b/source/Engine/Diagnostics/PerformanceMeasure.cpp @@ -1,20 +1,9 @@ -#if INTERFACE -#include -#include - -class PerformanceMeasure { -public: - static bool Initialized; - static Perf_ViewRender PERF_ViewRender[MAX_SCENE_VIEWS]; -}; -#endif - #include bool PerformanceMeasure::Initialized = false; Perf_ViewRender PerformanceMeasure::PERF_ViewRender[MAX_SCENE_VIEWS]; -PUBLIC STATIC void PerformanceMeasure::Init() { +void PerformanceMeasure::Init() { if (PerformanceMeasure::Initialized) return; diff --git a/source/Engine/Diagnostics/RemoteDebug.cpp b/source/Engine/Diagnostics/RemoteDebug.cpp index 2a59b3ae..f14095d9 100644 --- a/source/Engine/Diagnostics/RemoteDebug.cpp +++ b/source/Engine/Diagnostics/RemoteDebug.cpp @@ -1,25 +1,17 @@ -#if INTERFACE -class RemoteDebug { -public: - static bool Initialized; - static bool UsingRemoteDebug; -}; -#endif - #include #include bool RemoteDebug::Initialized = false; bool RemoteDebug::UsingRemoteDebug = false; -PUBLIC STATIC void RemoteDebug::Init() { +void RemoteDebug::Init() { if (RemoteDebug::Initialized) return; RemoteDebug::Initialized = true; } -PUBLIC STATIC bool RemoteDebug::AwaitResponse() { +bool RemoteDebug::AwaitResponse() { // To be used inside a for loop while awaiting a response from the remote debugger return true; } diff --git a/source/Engine/Extensions/Discord.cpp b/source/Engine/Extensions/Discord.cpp index 1c79c302..65673a05 100644 --- a/source/Engine/Extensions/Discord.cpp +++ b/source/Engine/Extensions/Discord.cpp @@ -1,20 +1,7 @@ -#if INTERFACE - -#include - -class Discord { -public: - static bool Initialized; -}; -#endif - #include #include #ifdef WIN32 -// #pragma pack(push, 8) -// #include -// #pragma pack(pop) #include @@ -30,21 +17,10 @@ void (*_Discord_Shutdown)(void) = NULL; bool Discord::Initialized = false; -// struct DiscordUser { -// char* username; -// char* discriminator; -// char* userId; -// }; -// void Discord_Ready(const DiscordUser* connectedUser) { Discord::Initialized = true; } -// void Discord_Disconnected(int errcode, const char* message) { } -// void Discord_Error(int errcode, const char* message) { } -// void Discord_Spectate(const char* secret) { } - -// Discord::Init("623985235150766081", ""); - -PUBLIC STATIC void Discord::Init(const char* application_id, const char* steam_id) { - #ifdef HAS_DISCORD_RPC +void Discord::Init(const char* application_id, const char* steam_id) { + Discord::Initialized = false; +#ifdef HAS_DISCORD_RPC library = SDL_LoadObject("discord-rpc.dll"); if (!library) return; @@ -57,78 +33,51 @@ PUBLIC STATIC void Discord::Init(const char* application_id, const char* steam_i DiscordEventHandlers handlers; memset(&handlers, 0, sizeof(handlers)); - // handlers.ready = Discord_Ready; - // handlers.errored = Discord_Error; - // handlers.disconnected = Discord_Disconnected; - _Discord_Initialize(application_id, &handlers, 1, steam_id); - // struct Application { - // struct IDiscordCore* core; - // struct IDiscordUsers* users; - // }; - // - // struct Application app; - // // Don't forget to memset or otherwise initialize your classes! - // memset(&app, 0, sizeof(app)); - // - // struct IDiscordCoreEvents events; - // memset(&events, 0, sizeof(events)); - // - // struct DiscordCreateParams params; - // params.client_id = 379010971139702784; - // params.flags = DiscordCreateFlags_Default; - // params.events = &events; - // params.event_data = &app; - // - // DiscordCreate(DISCORD_VERSION, ¶ms, &app.core); Discord::Initialized = true; Discord::UpdatePresence(NULL); - return; - #endif - - Discord::Initialized = false; +#endif } -PUBLIC STATIC void Discord::UpdatePresence(char* details) { +void Discord::UpdatePresence(char* details) { Discord::UpdatePresence(details, NULL); } -PUBLIC STATIC void Discord::UpdatePresence(char* details, char* state) { +void Discord::UpdatePresence(char* details, char* state) { Discord::UpdatePresence(details, state, NULL); } -PUBLIC STATIC void Discord::UpdatePresence(char* details, char* state, char* image_key) { +void Discord::UpdatePresence(char* details, char* state, char* image_key) { Discord::UpdatePresence(details, state, image_key, 0, 0); } -PUBLIC STATIC void Discord::UpdatePresence(char* details, char* state, char* image_key, time_t start_time) { +void Discord::UpdatePresence(char* details, char* state, char* image_key, time_t start_time) { Discord::UpdatePresence(details, state, image_key, 0, 0, start_time); } -PUBLIC STATIC void Discord::UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max) { +void Discord::UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max) { Discord::UpdatePresence(details, state, image_key, party_size, party_max, 0); } -PUBLIC STATIC void Discord::UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max, time_t start_time) { +void Discord::UpdatePresence(char* details, char* state, char* image_key, int party_size, int party_max, time_t start_time) { if (!Discord::Initialized) return; - #ifdef HAS_DISCORD_RPC +#ifdef HAS_DISCORD_RPC DiscordRichPresence discordPresence; memset(&discordPresence, 0, sizeof(discordPresence)); discordPresence.details = details; discordPresence.state = state; discordPresence.largeImageKey = image_key; - //discordPresence.partyId = 0; discordPresence.partySize = party_size; discordPresence.partyMax = party_max; discordPresence.startTimestamp = start_time; discordPresence.instance = 1; _Discord_UpdatePresence(&discordPresence); - #endif +#endif } -PUBLIC STATIC void Discord::Dispose() { +void Discord::Dispose() { if (!Discord::Initialized) return; - #ifdef HAS_DISCORD_RPC +#ifdef HAS_DISCORD_RPC _Discord_Shutdown(); SDL_UnloadObject(library); - #endif +#endif } diff --git a/source/Engine/Filesystem/Directory.cpp b/source/Engine/Filesystem/Directory.cpp index ac0bd65e..ea3bb8ce 100644 --- a/source/Engine/Filesystem/Directory.cpp +++ b/source/Engine/Filesystem/Directory.cpp @@ -1,12 +1,3 @@ -#if INTERFACE - -#include - -class Directory { -private: -}; -#endif - #include #include @@ -25,7 +16,7 @@ bool CompareFunction(char* i, char* j) { return strcmp(i, j) < 0; } -PUBLIC STATIC bool Directory::Exists(const char* path) { +bool Directory::Exists(const char* path) { #if WIN32 DWORD ftyp = GetFileAttributesA(path); if (ftyp == INVALID_FILE_ATTRIBUTES) return false; // Something is wrong with your path @@ -39,7 +30,7 @@ PUBLIC STATIC bool Directory::Exists(const char* path) { #endif return false; } -PUBLIC STATIC bool Directory::Create(const char* path) { +bool Directory::Create(const char* path) { #if WIN32 return CreateDirectoryA(path, NULL); #else @@ -47,7 +38,7 @@ PUBLIC STATIC bool Directory::Create(const char* path) { #endif } -PUBLIC STATIC bool Directory::GetCurrentWorkingDirectory(char* out, size_t sz) { +bool Directory::GetCurrentWorkingDirectory(char* out, size_t sz) { #if WIN32 return _getcwd(out, sz) != NULL; #else @@ -55,7 +46,7 @@ PUBLIC STATIC bool Directory::GetCurrentWorkingDirectory(char* out, siz #endif } -PUBLIC STATIC void Directory::GetFiles(vector* files, const char* path, const char* searchPattern, bool allDirs) { +void Directory::GetFiles(vector* files, const char* path, const char* searchPattern, bool allDirs) { #if WIN32 char winPath[MAX_PATH_SIZE]; snprintf(winPath, MAX_PATH_SIZE, "%s%s*", path, path[strlen(path) - 1] == '/' ? "" : "/"); @@ -126,13 +117,13 @@ PUBLIC STATIC void Directory::GetFiles(vector* files, const char std::sort(files->begin(), files->end(), CompareFunction); #endif } -PUBLIC STATIC vector Directory::GetFiles(const char* path, const char* searchPattern, bool allDirs) { +vector Directory::GetFiles(const char* path, const char* searchPattern, bool allDirs) { vector files; Directory::GetFiles(&files, path, searchPattern, allDirs); return files; } -PUBLIC STATIC void Directory::GetDirectories(vector* files, const char* path, const char* searchPattern, bool allDirs) { +void Directory::GetDirectories(vector* files, const char* path, const char* searchPattern, bool allDirs) { #if WIN32 char winPath[MAX_PATH_SIZE]; snprintf(winPath, MAX_PATH_SIZE, "%s%s*", path, path[strlen(path) - 1] == '/' ? "" : "/"); @@ -200,7 +191,7 @@ PUBLIC STATIC void Directory::GetDirectories(vector* files, cons } #endif } -PUBLIC STATIC vector Directory::GetDirectories(const char* path, const char* searchPattern, bool allDirs) { +vector Directory::GetDirectories(const char* path, const char* searchPattern, bool allDirs) { vector files; Directory::GetDirectories(&files, path, searchPattern, allDirs); return files; diff --git a/source/Engine/Filesystem/File.cpp b/source/Engine/Filesystem/File.cpp index 8b379c13..7e2b108e 100644 --- a/source/Engine/Filesystem/File.cpp +++ b/source/Engine/Filesystem/File.cpp @@ -1,12 +1,3 @@ -#if INTERFACE - -#include - -class File { -private: -}; -#endif - #include #include @@ -22,7 +13,7 @@ class File { #include #endif -PUBLIC STATIC bool File::Exists(const char* path) { +bool File::Exists(const char* path) { #if WIN32 return _access(path, 0) != -1; #elif MACOSX @@ -60,7 +51,7 @@ PUBLIC STATIC bool File::Exists(const char* path) { #endif } -PUBLIC STATIC size_t File::ReadAllBytes(const char* path, char** out) { +size_t File::ReadAllBytes(const char* path, char** out) { FileStream* stream; if ((stream = FileStream::New(path, FileStream::READ_ACCESS))) { size_t size = stream->Length(); @@ -75,7 +66,7 @@ PUBLIC STATIC size_t File::ReadAllBytes(const char* path, char** out) { return 0; } -PUBLIC STATIC bool File::WriteAllBytes(const char* path, const char* bytes, size_t len) { +bool File::WriteAllBytes(const char* path, const char* bytes, size_t len) { if (!path) return false; if (!*path) return false; if (!bytes) return false; diff --git a/source/Engine/FontFace.cpp b/source/Engine/FontFace.cpp index f3681d7b..0ef905c0 100644 --- a/source/Engine/FontFace.cpp +++ b/source/Engine/FontFace.cpp @@ -1,17 +1,3 @@ -#if INTERFACE -#include -#include -#include - -#include -#include - -class FontFace { -public: - -}; -#endif - #include #include #include @@ -149,7 +135,7 @@ FT_Package* PackBoxes(FT_GlyphBox* boxes, int boxCount, int defWidth, int de return package; } -PUBLIC STATIC ISprite* FontFace::SpriteFromFont(Stream* stream, int pixelSize, char* filename) { +ISprite* FontFace::SpriteFromFont(Stream* stream, int pixelSize, char* filename) { #ifdef USING_FREETYPE if (!ftInitialized) { diff --git a/source/Engine/Graphics.cpp b/source/Engine/Graphics.cpp index eb520063..a7e3ae9c 100644 --- a/source/Engine/Graphics.cpp +++ b/source/Engine/Graphics.cpp @@ -1,101 +1,3 @@ -#if INTERFACE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -need_t ISprite; -need_t IModel; - -class Graphics { -public: - static HashMap* TextureMap; - static map SpriteSheetTextureMap; - static bool VsyncEnabled; - static int MultisamplingEnabled; - static int FontDPI; - static bool SupportsBatching; - static bool TextureBlend; - static bool TextureInterpolate; - static Uint32 PreferredPixelFormat; - - static Uint32 MaxTextureWidth; - static Uint32 MaxTextureHeight; - static Texture* TextureHead; - - static vector VertexBuffers; - static Scene3D Scene3Ds[MAX_3D_SCENES]; - - static stack StateStack; - static stack MatrixStack; - - static Matrix4x4* ModelViewMatrix; - - static Viewport CurrentViewport; - static Viewport BackupViewport; - static ClipArea CurrentClip; - static ClipArea BackupClip; - - static View* CurrentView; - - static float BlendColors[4]; - static float TintColors[4]; - - static int BlendMode; - static int TintMode; - - static int StencilTest; - static int StencilOpPass; - static int StencilOpFail; - - static void* FramebufferPixels; - static size_t FramebufferSize; - - static Uint32 PaletteColors[MAX_PALETTE_COUNT][0x100]; - static Uint8 PaletteIndexLines[MAX_FRAMEBUFFER_HEIGHT]; - static bool PaletteUpdated; - - static Texture* PaletteTexture; - - static Texture* CurrentRenderTarget; - static Sint32 CurrentScene3D; - static Sint32 CurrentVertexBuffer; - - static void* CurrentShader; - static bool SmoothFill; - static bool SmoothStroke; - - static float PixelOffset; - static bool NoInternalTextures; - static bool UsePalettes; - static bool UsePaletteIndexLines; - static bool UseTinting; - static bool UseDepthTesting; - static bool UseSoftwareRenderer; - - static unsigned CurrentFrame; - - // Rendering functions - static GraphicsFunctions Internal; - static GraphicsFunctions* GfxFunctions; - static const char* Renderer; -}; -#endif - #include #include @@ -182,7 +84,7 @@ GraphicsFunctions Graphics::Internal; GraphicsFunctions* Graphics::GfxFunctions = &Graphics::Internal; const char* Graphics::Renderer = "default"; -PUBLIC STATIC void Graphics::Init() { +void Graphics::Init() { Graphics::TextureMap = new HashMap(NULL, 32); Graphics::ModelViewMatrix = Matrix4x4::Create(); @@ -214,7 +116,7 @@ PUBLIC STATIC void Graphics::Init() { Log::Print(Log::LOG_VERBOSE, "Multisample: false"); Log::Print(Log::LOG_VERBOSE, "Max Texture Size: %d x %d", Graphics::MaxTextureWidth, Graphics::MaxTextureHeight); } -PUBLIC STATIC void Graphics::ChooseBackend() { +void Graphics::ChooseBackend() { char renderer[64]; SoftwareRenderer::SetGraphicsFunctions(); @@ -271,13 +173,13 @@ PUBLIC STATIC void Graphics::ChooseBackend() { SDL2Renderer::SetGraphicsFunctions(); } } -PUBLIC STATIC Uint32 Graphics::GetWindowFlags() { +Uint32 Graphics::GetWindowFlags() { return Graphics::GfxFunctions->GetWindowFlags(); } -PUBLIC STATIC void Graphics::SetVSync(bool enabled) { +void Graphics::SetVSync(bool enabled) { Graphics::GfxFunctions->SetVSync(enabled); } -PUBLIC STATIC void Graphics::Reset() { +void Graphics::Reset() { Graphics::UseSoftwareRenderer = false; Graphics::UsePalettes = false; Graphics::UsePaletteIndexLines = false; @@ -307,7 +209,7 @@ PUBLIC STATIC void Graphics::Reset() { Graphics::StencilOpPass = StencilOp_Keep; Graphics::StencilOpFail = StencilOp_Keep; } -PUBLIC STATIC void Graphics::Dispose() { +void Graphics::Dispose() { for (Uint32 i = 0; i < Graphics::VertexBuffers.size(); i++) Graphics::DeleteVertexBuffer(i); Graphics::VertexBuffers.clear(); @@ -336,7 +238,7 @@ PUBLIC STATIC void Graphics::Dispose() { Memory::Free(Graphics::FramebufferPixels); } -PUBLIC STATIC Point Graphics::ProjectToScreen(float x, float y, float z) { +Point Graphics::ProjectToScreen(float x, float y, float z) { Point p; float vec4[4]; Matrix4x4* matrix; @@ -352,7 +254,7 @@ PUBLIC STATIC Point Graphics::ProjectToScreen(float x, float y, float z) { return p; } -PUBLIC STATIC Texture* Graphics::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* Graphics::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture; if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || Graphics::NoInternalTextures) { @@ -374,33 +276,33 @@ PUBLIC STATIC Texture* Graphics::CreateTexture(Uint32 format, Uint32 access, Uin return texture; } -PUBLIC STATIC Texture* Graphics::CreateTextureFromPixels(Uint32 width, Uint32 height, void* pixels, int pitch) { +Texture* Graphics::CreateTextureFromPixels(Uint32 width, Uint32 height, void* pixels, int pitch) { Texture* texture = Graphics::CreateTexture(SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); if (texture) Graphics::UpdateTexture(texture, NULL, pixels, pitch); return texture; } -PUBLIC STATIC Texture* Graphics::CreateTextureFromSurface(SDL_Surface* surface) { +Texture* Graphics::CreateTextureFromSurface(SDL_Surface* surface) { Texture* texture = Graphics::CreateTexture(surface->format->format, SDL_TEXTUREACCESS_STATIC, surface->w, surface->h); if (texture) Graphics::GfxFunctions->UpdateTexture(texture, NULL, surface->pixels, surface->pitch); return texture; } -PUBLIC STATIC int Graphics::LockTexture(Texture* texture, void** pixels, int* pitch) { +int Graphics::LockTexture(Texture* texture, void** pixels, int* pitch) { if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || Graphics::NoInternalTextures) return 1; return Graphics::GfxFunctions->LockTexture(texture, pixels, pitch); } -PUBLIC STATIC int Graphics::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { +int Graphics::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { memcpy(texture->Pixels, pixels, sizeof(Uint32) * texture->Width * texture->Height); if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || Graphics::NoInternalTextures) return 1; return Graphics::GfxFunctions->UpdateTexture(texture, src, pixels, pitch); } -PUBLIC STATIC int Graphics::UpdateYUVTexture(Texture* texture, SDL_Rect* src, Uint8* pixelsY, int pitchY, Uint8* pixelsU, int pitchU, Uint8* pixelsV, int pitchV) { +int Graphics::UpdateYUVTexture(Texture* texture, SDL_Rect* src, Uint8* pixelsY, int pitchY, Uint8* pixelsU, int pitchU, Uint8* pixelsV, int pitchV) { if (!Graphics::GfxFunctions->UpdateYUVTexture) return 0; if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || @@ -408,21 +310,21 @@ PUBLIC STATIC int Graphics::UpdateYUVTexture(Texture* texture, SDL_Rect* sr return 1; return Graphics::GfxFunctions->UpdateYUVTexture(texture, src, pixelsY, pitchY, pixelsU, pitchU, pixelsV, pitchV); } -PUBLIC STATIC int Graphics::SetTexturePalette(Texture* texture, void* palette, unsigned numPaletteColors) { +int Graphics::SetTexturePalette(Texture* texture, void* palette, unsigned numPaletteColors) { texture->SetPalette((Uint32*)palette, numPaletteColors); if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || !Graphics::GfxFunctions->SetTexturePalette || Graphics::NoInternalTextures) return 1; return Graphics::GfxFunctions->SetTexturePalette(texture, palette, numPaletteColors); } -PUBLIC STATIC int Graphics::ConvertTextureToRGBA(Texture* texture) { +int Graphics::ConvertTextureToRGBA(Texture* texture) { texture->ConvertToRGBA(); if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions || Graphics::NoInternalTextures) return 1; return Graphics::GfxFunctions->UpdateTexture(texture, NULL, texture->Pixels, texture->Pitch); } -PUBLIC STATIC int Graphics::ConvertTextureToPalette(Texture* texture, unsigned paletteNumber) { +int Graphics::ConvertTextureToPalette(Texture* texture, unsigned paletteNumber) { Uint32* colors = (Uint32*)Memory::TrackedMalloc("Texture::Colors", 256 * sizeof(Uint32)); if (!colors) return 0; @@ -445,10 +347,10 @@ PUBLIC STATIC int Graphics::ConvertTextureToPalette(Texture* texture, unsig return ok; } -PUBLIC STATIC void Graphics::UnlockTexture(Texture* texture) { +void Graphics::UnlockTexture(Texture* texture) { Graphics::GfxFunctions->UnlockTexture(texture); } -PUBLIC STATIC void Graphics::DisposeTexture(Texture* texture) { +void Graphics::DisposeTexture(Texture* texture) { Graphics::GfxFunctions->DisposeTexture(texture); if (texture->Next) @@ -463,7 +365,7 @@ PUBLIC STATIC void Graphics::DisposeTexture(Texture* texture) { Memory::Free(texture); } -PUBLIC STATIC TextureReference* Graphics::GetSpriteSheet(string sheetPath) { +TextureReference* Graphics::GetSpriteSheet(string sheetPath) { if (Graphics::SpriteSheetTextureMap.count(sheetPath) != 0) { TextureReference* textureRef = Graphics::SpriteSheetTextureMap.at(sheetPath); textureRef->AddRef(); @@ -472,7 +374,7 @@ PUBLIC STATIC TextureReference* Graphics::GetSpriteSheet(string sheetPath) { return nullptr; } -PUBLIC STATIC TextureReference* Graphics::AddSpriteSheet(string sheetPath, Texture* texture) { +TextureReference* Graphics::AddSpriteSheet(string sheetPath, Texture* texture) { TextureReference *ref = Graphics::GetSpriteSheet(sheetPath); if (ref == nullptr) { ref = new TextureReference(texture); @@ -480,7 +382,7 @@ PUBLIC STATIC TextureReference* Graphics::AddSpriteSheet(string sheetPath, Textu } return ref; } -PUBLIC STATIC void Graphics::DisposeSpriteSheet(string sheetPath) { +void Graphics::DisposeSpriteSheet(string sheetPath) { if (Graphics::SpriteSheetTextureMap.count(sheetPath) != 0) { TextureReference* textureRef = Graphics::SpriteSheetTextureMap.at(sheetPath); if (textureRef->TakeRef()) { @@ -490,7 +392,7 @@ PUBLIC STATIC void Graphics::DisposeSpriteSheet(string sheetPath) { } } } -PUBLIC STATIC void Graphics::DeleteSpriteSheetMap() { +void Graphics::DeleteSpriteSheetMap() { for (std::map::iterator it = Graphics::SpriteSheetTextureMap.begin(); it != Graphics::SpriteSheetTextureMap.end(); it++) @@ -502,7 +404,7 @@ PUBLIC STATIC void Graphics::DeleteSpriteSheetMap() { Graphics::SpriteSheetTextureMap.clear(); } -PUBLIC STATIC Uint32 Graphics::CreateVertexBuffer(Uint32 maxVertices, int unloadPolicy) { +Uint32 Graphics::CreateVertexBuffer(Uint32 maxVertices, int unloadPolicy) { Uint32 idx = 0xFFFFFFFF; for (Uint32 i = 0; i < Graphics::VertexBuffers.size(); i++) { @@ -532,7 +434,7 @@ PUBLIC STATIC Uint32 Graphics::CreateVertexBuffer(Uint32 maxVertices, int unlo return idx; } -PUBLIC STATIC void Graphics::DeleteVertexBuffer(Uint32 vertexBufferIndex) { +void Graphics::DeleteVertexBuffer(Uint32 vertexBufferIndex) { if (vertexBufferIndex < 0 || vertexBufferIndex >= Graphics::VertexBuffers.size()) return; if (!Graphics::VertexBuffers[vertexBufferIndex]) @@ -545,33 +447,33 @@ PUBLIC STATIC void Graphics::DeleteVertexBuffer(Uint32 vertexBufferIndex) { Graphics::VertexBuffers[vertexBufferIndex] = NULL; } -PUBLIC STATIC void Graphics::UseShader(void* shader) { +void Graphics::UseShader(void* shader) { Graphics::CurrentShader = shader; Graphics::GfxFunctions->UseShader(shader); } -PUBLIC STATIC void Graphics::SetTextureInterpolation(bool interpolate) { +void Graphics::SetTextureInterpolation(bool interpolate) { Graphics::TextureInterpolate = interpolate; } -PUBLIC STATIC void Graphics::Clear() { +void Graphics::Clear() { Graphics::GfxFunctions->Clear(); } -PUBLIC STATIC void Graphics::Present() { +void Graphics::Present() { Graphics::GfxFunctions->Present(); Graphics::CurrentFrame++; } -PUBLIC STATIC void Graphics::SoftwareStart() { +void Graphics::SoftwareStart() { Graphics::GfxFunctions = &SoftwareRenderer::BackendFunctions; SoftwareRenderer::RenderStart(); } -PUBLIC STATIC void Graphics::SoftwareEnd() { +void Graphics::SoftwareEnd() { SoftwareRenderer::RenderEnd(); Graphics::GfxFunctions = &Graphics::Internal; Graphics::UpdateTexture(Graphics::CurrentRenderTarget, NULL, Graphics::CurrentRenderTarget->Pixels, Graphics::CurrentRenderTarget->Width * 4); } -PUBLIC STATIC void Graphics::UpdateGlobalPalette() { +void Graphics::UpdateGlobalPalette() { if (!Graphics::GfxFunctions->UpdateGlobalPalette) return; @@ -588,7 +490,7 @@ PUBLIC STATIC void Graphics::UpdateGlobalPalette() { Graphics::GfxFunctions->UpdateGlobalPalette(); } -PUBLIC STATIC void Graphics::UnloadSceneData() { +void Graphics::UnloadSceneData() { for (Uint32 i = 0; i < Graphics::VertexBuffers.size(); i++) { VertexBuffer* buffer = Graphics::VertexBuffers[i]; if (!buffer || buffer->UnloadPolicy > SCOPE_SCENE) @@ -606,7 +508,7 @@ PUBLIC STATIC void Graphics::UnloadSceneData() { } } -PUBLIC STATIC void Graphics::SetRenderTarget(Texture* texture) { +void Graphics::SetRenderTarget(Texture* texture) { if (texture && !Graphics::CurrentRenderTarget) { Graphics::BackupViewport = Graphics::CurrentViewport; Graphics::BackupClip = Graphics::CurrentClip; @@ -631,7 +533,7 @@ PUBLIC STATIC void Graphics::SetRenderTarget(Texture* texture) { Graphics::GfxFunctions->UpdateViewport(); Graphics::GfxFunctions->UpdateClipRect(); } -PUBLIC STATIC void Graphics::CopyScreen(int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h, Texture* texture) { +void Graphics::CopyScreen(int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h, Texture* texture) { if (!Graphics::GfxFunctions->ReadFramebuffer) return; @@ -669,22 +571,22 @@ PUBLIC STATIC void Graphics::CopyScreen(int source_x, int source_y, int sour } } } -PUBLIC STATIC void Graphics::UpdateOrtho(float width, float height) { +void Graphics::UpdateOrtho(float width, float height) { Graphics::GfxFunctions->UpdateOrtho(0.0f, 0.0f, width, height); } -PUBLIC STATIC void Graphics::UpdateOrthoFlipped(float width, float height) { +void Graphics::UpdateOrthoFlipped(float width, float height) { Graphics::GfxFunctions->UpdateOrtho(0.0f, height, width, 0.0f); } -PUBLIC STATIC void Graphics::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { +void Graphics::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { Graphics::GfxFunctions->UpdatePerspective(fovy, aspect, nearv, farv); } -PUBLIC STATIC void Graphics::UpdateProjectionMatrix() { +void Graphics::UpdateProjectionMatrix() { Graphics::GfxFunctions->UpdateProjectionMatrix(); } -PUBLIC STATIC void Graphics::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { +void Graphics::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { Graphics::GfxFunctions->MakePerspectiveMatrix(out, fov, near, far, aspect); } -PUBLIC STATIC void Graphics::CalculateMVPMatrix(Matrix4x4* output, Matrix4x4* modelMatrix, Matrix4x4* viewMatrix, Matrix4x4* projMatrix) { +void Graphics::CalculateMVPMatrix(Matrix4x4* output, Matrix4x4* modelMatrix, Matrix4x4* viewMatrix, Matrix4x4* projMatrix) { if (viewMatrix && projMatrix) { Matrix4x4 modelView; @@ -700,7 +602,7 @@ PUBLIC STATIC void Graphics::CalculateMVPMatrix(Matrix4x4* output, Matrix4x4 else Matrix4x4::Identity(output); } -PUBLIC STATIC void Graphics::SetViewport(float x, float y, float w, float h) { +void Graphics::SetViewport(float x, float y, float w, float h) { Viewport* vp = &Graphics::CurrentViewport; if (x < 0) { vp->X = 0.0; @@ -724,14 +626,14 @@ PUBLIC STATIC void Graphics::SetViewport(float x, float y, float w, float h) } Graphics::GfxFunctions->UpdateViewport(); } -PUBLIC STATIC void Graphics::ResetViewport() { +void Graphics::ResetViewport() { Graphics::SetViewport(-1.0, 0.0, 0.0, 0.0); } -PUBLIC STATIC void Graphics::Resize(int width, int height) { +void Graphics::Resize(int width, int height) { Graphics::GfxFunctions->UpdateWindowSize(width, height); } -PUBLIC STATIC void Graphics::SetClip(int x, int y, int width, int height) { +void Graphics::SetClip(int x, int y, int width, int height) { Graphics::CurrentClip.Enabled = true; Graphics::CurrentClip.X = x; Graphics::CurrentClip.Y = y; @@ -739,12 +641,12 @@ PUBLIC STATIC void Graphics::SetClip(int x, int y, int width, int height) { Graphics::CurrentClip.Height = height; Graphics::GfxFunctions->UpdateClipRect(); } -PUBLIC STATIC void Graphics::ClearClip() { +void Graphics::ClearClip() { Graphics::CurrentClip.Enabled = false; Graphics::GfxFunctions->UpdateClipRect(); } -PUBLIC STATIC void Graphics::Save() { +void Graphics::Save() { Matrix4x4* top = MatrixStack.top(); Matrix4x4* push = Matrix4x4::Create(); Matrix4x4::Copy(push, top); @@ -757,18 +659,18 @@ PUBLIC STATIC void Graphics::Save() { MatrixStack.push(push); ModelViewMatrix = push; } -PUBLIC STATIC void Graphics::Translate(float x, float y, float z) { +void Graphics::Translate(float x, float y, float z) { Matrix4x4::Translate(ModelViewMatrix, ModelViewMatrix, x, y, z); } -PUBLIC STATIC void Graphics::Rotate(float x, float y, float z) { +void Graphics::Rotate(float x, float y, float z) { Matrix4x4::Rotate(ModelViewMatrix, ModelViewMatrix, x, 1.0, 0.0, 0.0); Matrix4x4::Rotate(ModelViewMatrix, ModelViewMatrix, y, 0.0, 1.0, 0.0); Matrix4x4::Rotate(ModelViewMatrix, ModelViewMatrix, z, 0.0, 0.0, 1.0); } -PUBLIC STATIC void Graphics::Scale(float x, float y, float z) { +void Graphics::Scale(float x, float y, float z) { Matrix4x4::Scale(ModelViewMatrix, ModelViewMatrix, x, y, z); } -PUBLIC STATIC void Graphics::Restore() { +void Graphics::Restore() { if (MatrixStack.size() == 1) return; delete MatrixStack.top(); @@ -777,7 +679,7 @@ PUBLIC STATIC void Graphics::Restore() { ModelViewMatrix = MatrixStack.top(); } -PUBLIC STATIC BlendState Graphics::GetBlendState() { +BlendState Graphics::GetBlendState() { BlendState state; state.Opacity = (int)(Graphics::BlendColors[3] * 0xFF); state.Mode = Graphics::BlendMode; @@ -789,7 +691,7 @@ PUBLIC STATIC BlendState Graphics::GetBlendState() { return state; } -PUBLIC STATIC void Graphics::PushState() { +void Graphics::PushState() { if (StateStack.size() == 256) { Log::Print(Log::LOG_ERROR, "Graphics::PushState stack too big!"); exit(-1); @@ -814,7 +716,7 @@ PUBLIC STATIC void Graphics::PushState() { Graphics::Save(); } -PUBLIC STATIC void Graphics::PopState() { +void Graphics::PopState() { if (StateStack.size() == 0) return; GraphicsState state = StateStack.top(); @@ -843,14 +745,14 @@ PUBLIC STATIC void Graphics::PopState() { Graphics::Restore(); } -PUBLIC STATIC void Graphics::SetBlendColor(float r, float g, float b, float a) { +void Graphics::SetBlendColor(float r, float g, float b, float a) { Graphics::BlendColors[0] = Math::Clamp(r, 0.0f, 1.0f); Graphics::BlendColors[1] = Math::Clamp(g, 0.0f, 1.0f); Graphics::BlendColors[2] = Math::Clamp(b, 0.0f, 1.0f); Graphics::BlendColors[3] = Math::Clamp(a, 0.0f, 1.0f); Graphics::GfxFunctions->SetBlendColor(r, g, b, a); } -PUBLIC STATIC void Graphics::SetBlendMode(int blendMode) { +void Graphics::SetBlendMode(int blendMode) { Graphics::BlendMode = blendMode; switch (blendMode) { case BlendMode_NORMAL: @@ -879,75 +781,75 @@ PUBLIC STATIC void Graphics::SetBlendMode(int blendMode) { BlendFactor_SRC_ALPHA, BlendFactor_INV_SRC_ALPHA); } } -PUBLIC STATIC void Graphics::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { +void Graphics::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { Graphics::GfxFunctions->SetBlendMode(srcC, dstC, srcA, dstA); } -PUBLIC STATIC void Graphics::SetTintColor(float r, float g, float b, float a) { +void Graphics::SetTintColor(float r, float g, float b, float a) { Graphics::TintColors[0] = Math::Clamp(r, 0.0f, 1.0f); Graphics::TintColors[1] = Math::Clamp(g, 0.0f, 1.0f); Graphics::TintColors[2] = Math::Clamp(b, 0.0f, 1.0f); Graphics::TintColors[3] = Math::Clamp(a, 0.0f, 1.0f); Graphics::GfxFunctions->SetTintColor(r, g, b, a); } -PUBLIC STATIC void Graphics::SetTintMode(int mode) { +void Graphics::SetTintMode(int mode) { Graphics::TintMode = mode; Graphics::GfxFunctions->SetTintMode(mode); } -PUBLIC STATIC void Graphics::SetTintEnabled(bool enabled) { +void Graphics::SetTintEnabled(bool enabled) { Graphics::UseTinting = enabled; Graphics::GfxFunctions->SetTintEnabled(enabled); } -PUBLIC STATIC void Graphics::SetLineWidth(float n) { +void Graphics::SetLineWidth(float n) { Graphics::GfxFunctions->SetLineWidth(n); } -PUBLIC STATIC void Graphics::StrokeLine(float x1, float y1, float x2, float y2) { +void Graphics::StrokeLine(float x1, float y1, float x2, float y2) { Graphics::GfxFunctions->StrokeLine(x1, y1, x2, y2); } -PUBLIC STATIC void Graphics::StrokeCircle(float x, float y, float rad, float thickness) { +void Graphics::StrokeCircle(float x, float y, float rad, float thickness) { Graphics::GfxFunctions->StrokeCircle(x, y, rad, thickness); } -PUBLIC STATIC void Graphics::StrokeEllipse(float x, float y, float w, float h) { +void Graphics::StrokeEllipse(float x, float y, float w, float h) { Graphics::GfxFunctions->StrokeEllipse(x, y, w, h); } -PUBLIC STATIC void Graphics::StrokeTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void Graphics::StrokeTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { Graphics::GfxFunctions->StrokeLine(x1, y1, x2, y2); Graphics::GfxFunctions->StrokeLine(x2, y2, x3, y3); Graphics::GfxFunctions->StrokeLine(x3, y3, x1, y1); } -PUBLIC STATIC void Graphics::StrokeRectangle(float x, float y, float w, float h) { +void Graphics::StrokeRectangle(float x, float y, float w, float h) { Graphics::GfxFunctions->StrokeRectangle(x, y, w, h); } -PUBLIC STATIC void Graphics::FillCircle(float x, float y, float rad) { +void Graphics::FillCircle(float x, float y, float rad) { Graphics::GfxFunctions->FillCircle(x, y, rad); } -PUBLIC STATIC void Graphics::FillEllipse(float x, float y, float w, float h) { +void Graphics::FillEllipse(float x, float y, float w, float h) { Graphics::GfxFunctions->FillEllipse(x, y, w, h); } -PUBLIC STATIC void Graphics::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void Graphics::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { Graphics::GfxFunctions->FillTriangle(x1, y1, x2, y2, x3, y3); } -PUBLIC STATIC void Graphics::FillRectangle(float x, float y, float w, float h) { +void Graphics::FillRectangle(float x, float y, float w, float h) { Graphics::GfxFunctions->FillRectangle(x, y, w, h); } -PUBLIC STATIC void Graphics::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { +void Graphics::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { Graphics::GfxFunctions->DrawTexture(texture, sx, sy, sw, sh, x, y, w, h); } -PUBLIC STATIC void Graphics::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void Graphics::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { Graphics::GfxFunctions->DrawSprite(sprite, animation, frame, x, y, flipX, flipY, scaleW, scaleH, rotation, paletteID); } -PUBLIC STATIC void Graphics::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void Graphics::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { Graphics::GfxFunctions->DrawSpritePart(sprite, animation, frame, sx, sy, sw, sh, x, y, flipX, flipY, scaleW, scaleH, rotation, paletteID); } -PUBLIC STATIC void Graphics::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { +void Graphics::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { DrawSprite(sprite, animation, frame, x, y, flipX, flipY, scaleW, scaleH, rotation, 0); } -PUBLIC STATIC void Graphics::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { +void Graphics::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { DrawSpritePart(sprite, animation, frame, sx, sy, sw, sh, x, y, flipX, flipY, scaleW, scaleH, rotation, 0); } -PUBLIC STATIC void Graphics::DrawTile(int tile, int x, int y, bool flipX, bool flipY) { +void Graphics::DrawTile(int tile, int x, int y, bool flipX, bool flipY) { // If possible, uses optimized software-renderer call instead. if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions) { SoftwareRenderer::DrawTile(tile, x, y, flipX, flipY); @@ -957,7 +859,7 @@ PUBLIC STATIC void Graphics::DrawTile(int tile, int x, int y, bool flipX, bo TileSpriteInfo info = Scene::TileSpriteInfos[tile]; DrawSprite(info.Sprite, info.AnimationIndex, info.FrameIndex, x, y, flipX, flipY, 1.0f, 1.0f, 0.0f); } -PUBLIC STATIC void Graphics::DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView) { +void Graphics::DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView) { int tileWidth = Scene::TileWidth; int tileWidthHalf = tileWidth >> 1; int tileHeight = Scene::TileHeight; @@ -1225,10 +1127,10 @@ PUBLIC STATIC void Graphics::DrawSceneLayer_HorizontalParallax(SceneLayer* l } } } -PUBLIC STATIC void Graphics::DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView) { +void Graphics::DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView) { } -PUBLIC STATIC void Graphics::DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction) { +void Graphics::DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction) { // If possible, uses optimized software-renderer call instead. if (Graphics::GfxFunctions == &SoftwareRenderer::BackendFunctions) { SoftwareRenderer::DrawSceneLayer(layer, currentView, layerIndex, useCustomFunction); @@ -1252,7 +1154,7 @@ PUBLIC STATIC void Graphics::DrawSceneLayer(SceneLayer* layer, View* current break; } } -PUBLIC STATIC void Graphics::RunCustomSceneLayerFunction(ObjFunction* func, int layerIndex) { +void Graphics::RunCustomSceneLayerFunction(ObjFunction* func, int layerIndex) { VMThread* thread = &ScriptManager::Threads[0]; if (func->Arity == 0) { thread->RunEntityFunction(func, 0); @@ -1264,27 +1166,27 @@ PUBLIC STATIC void Graphics::RunCustomSceneLayerFunction(ObjFunction* func, } // 3D drawing -PUBLIC STATIC void Graphics::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void Graphics::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::GfxFunctions->DrawPolygon3D) Graphics::GfxFunctions->DrawPolygon3D(data, vertexCount, vertexFlag, texture, modelMatrix, normalMatrix); } -PUBLIC STATIC void Graphics::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void Graphics::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::GfxFunctions->DrawSceneLayer3D) Graphics::GfxFunctions->DrawSceneLayer3D(layer, sx, sy, sw, sh, modelMatrix, normalMatrix); } -PUBLIC STATIC void Graphics::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void Graphics::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::GfxFunctions->DrawModel) Graphics::GfxFunctions->DrawModel(model, animation, frame, modelMatrix, normalMatrix); } -PUBLIC STATIC void Graphics::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void Graphics::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::GfxFunctions->DrawModelSkinned) Graphics::GfxFunctions->DrawModelSkinned(model, armature, modelMatrix, normalMatrix); } -PUBLIC STATIC void Graphics::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void Graphics::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::GfxFunctions->DrawVertexBuffer) Graphics::GfxFunctions->DrawVertexBuffer(vertexBufferIndex, modelMatrix, normalMatrix); } -PUBLIC STATIC void Graphics::BindVertexBuffer(Uint32 vertexBufferIndex) { +void Graphics::BindVertexBuffer(Uint32 vertexBufferIndex) { if (vertexBufferIndex < 0 || vertexBufferIndex >= MAX_VERTEX_BUFFERS) { UnbindVertexBuffer(); return; @@ -1294,12 +1196,12 @@ PUBLIC STATIC void Graphics::BindVertexBuffer(Uint32 vertexBufferIndex) { Graphics::GfxFunctions->BindVertexBuffer(vertexBufferIndex); CurrentVertexBuffer = vertexBufferIndex; } -PUBLIC STATIC void Graphics::UnbindVertexBuffer() { +void Graphics::UnbindVertexBuffer() { if (Graphics::GfxFunctions->UnbindVertexBuffer) Graphics::GfxFunctions->UnbindVertexBuffer(); CurrentVertexBuffer = -1; } -PUBLIC STATIC void Graphics::BindScene3D(Uint32 sceneIndex) { +void Graphics::BindScene3D(Uint32 sceneIndex) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -1318,7 +1220,7 @@ PUBLIC STATIC void Graphics::BindScene3D(Uint32 sceneIndex) { Graphics::GfxFunctions->BindScene3D(sceneIndex); CurrentScene3D = sceneIndex; } -PUBLIC STATIC void Graphics::ClearScene3D(Uint32 sceneIndex) { +void Graphics::ClearScene3D(Uint32 sceneIndex) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -1328,12 +1230,12 @@ PUBLIC STATIC void Graphics::ClearScene3D(Uint32 sceneIndex) { if (Graphics::GfxFunctions->ClearScene3D) Graphics::GfxFunctions->ClearScene3D(sceneIndex); } -PUBLIC STATIC void Graphics::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { +void Graphics::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { if (Graphics::GfxFunctions->DrawScene3D) Graphics::GfxFunctions->DrawScene3D(sceneIndex, drawMode); } -PUBLIC STATIC Uint32 Graphics::CreateScene3D(int unloadPolicy) { +Uint32 Graphics::CreateScene3D(int unloadPolicy) { for (Uint32 i = 0; i < MAX_3D_SCENES; i++) { if (!Graphics::Scene3Ds[i].Initialized) { Graphics::InitScene3D(i, 0); @@ -1344,7 +1246,7 @@ PUBLIC STATIC Uint32 Graphics::CreateScene3D(int unloadPolicy) { return 0xFFFFFFFF; } -PUBLIC STATIC void Graphics::DeleteScene3D(Uint32 sceneIndex) { +void Graphics::DeleteScene3D(Uint32 sceneIndex) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -1358,7 +1260,7 @@ PUBLIC STATIC void Graphics::DeleteScene3D(Uint32 sceneIndex) { scene->Initialized = false; } } -PUBLIC STATIC void Graphics::InitScene3D(Uint32 sceneIndex, Uint32 numVertices) { +void Graphics::InitScene3D(Uint32 sceneIndex, Uint32 numVertices) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -1383,7 +1285,7 @@ PUBLIC STATIC void Graphics::InitScene3D(Uint32 sceneIndex, Uint32 numVertic scene->Clear(); } -PUBLIC STATIC void Graphics::MakeSpritePolygon(VertexAttribute data[4], float x, float y, float z, int flipX, int flipY, float scaleX, float scaleY, Texture* texture, int frameX, int frameY, int frameW, int frameH) { +void Graphics::MakeSpritePolygon(VertexAttribute data[4], float x, float y, float z, int flipX, int flipY, float scaleX, float scaleY, Texture* texture, int frameX, int frameY, int frameW, int frameH) { data[3].Position.X = FP16_TO(x); data[3].Position.Y = FP16_TO(y - (frameH * scaleY)); data[3].Position.Z = FP16_TO(z); @@ -1407,7 +1309,7 @@ PUBLIC STATIC void Graphics::MakeSpritePolygon(VertexAttribute data[4], floa Graphics::MakeSpritePolygonUVs(data, flipX, flipY, texture, frameX, frameY, frameW, frameH); } -PUBLIC STATIC void Graphics::MakeSpritePolygonUVs(VertexAttribute data[4], int flipX, int flipY, Texture* texture, int frameX, int frameY, int frameW, int frameH) { +void Graphics::MakeSpritePolygonUVs(VertexAttribute data[4], int flipX, int flipY, Texture* texture, int frameX, int frameY, int frameW, int frameH) { Sint64 textureWidth = FP16_TO(texture->Width); Sint64 textureHeight = FP16_TO(texture->Height); @@ -1447,21 +1349,21 @@ PUBLIC STATIC void Graphics::MakeSpritePolygonUVs(VertexAttribute data[4], i data[0].UV.Y = FP16_DIVIDE(FP16_TO(top_v), textureHeight); } -PUBLIC STATIC void Graphics::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { +void Graphics::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { if (Graphics::GfxFunctions->MakeFrameBufferID) Graphics::GfxFunctions->MakeFrameBufferID(sprite, frame); } -PUBLIC STATIC void Graphics::DeleteFrameBufferID(AnimFrame* frame) { +void Graphics::DeleteFrameBufferID(AnimFrame* frame) { if (Graphics::GfxFunctions->DeleteFrameBufferID) Graphics::GfxFunctions->DeleteFrameBufferID(frame); } -PUBLIC STATIC void Graphics::SetDepthTesting(bool enabled) { +void Graphics::SetDepthTesting(bool enabled) { if (Graphics::GfxFunctions->SetDepthTesting) Graphics::GfxFunctions->SetDepthTesting(enabled); } -PUBLIC STATIC bool Graphics::SpriteRangeCheck(ISprite* sprite, int animation, int frame) { +bool Graphics::SpriteRangeCheck(ISprite* sprite, int animation, int frame) { //#ifdef DEBUG if (!sprite) return true; if (animation < 0 || animation >= (int)sprite->Animations.size()) { @@ -1476,47 +1378,47 @@ PUBLIC STATIC bool Graphics::SpriteRangeCheck(ISprite* sprite, int animation return false; } -PUBLIC STATIC void Graphics::ConvertFromARGBtoNative(Uint32* argb, int count) { +void Graphics::ConvertFromARGBtoNative(Uint32* argb, int count) { if (Graphics::PreferredPixelFormat == SDL_PIXELFORMAT_ABGR8888) ColorUtils::ConvertFromARGBtoABGR(argb, count); } -PUBLIC STATIC void Graphics::ConvertFromNativeToARGB(Uint32* argb, int count) { +void Graphics::ConvertFromNativeToARGB(Uint32* argb, int count) { if (Graphics::PreferredPixelFormat == SDL_PIXELFORMAT_ABGR8888) ColorUtils::ConvertFromABGRtoARGB(argb, count); } -PUBLIC STATIC void Graphics::SetStencilEnabled(bool enabled) { +void Graphics::SetStencilEnabled(bool enabled) { if (Graphics::GfxFunctions->SetStencilEnabled) Graphics::GfxFunctions->SetStencilEnabled(enabled); } -PUBLIC STATIC bool Graphics::GetStencilEnabled() { +bool Graphics::GetStencilEnabled() { if (Graphics::GfxFunctions->IsStencilEnabled) return Graphics::GfxFunctions->IsStencilEnabled(); return false; } -PUBLIC STATIC void Graphics::SetStencilTestFunc(int stencilTest) { +void Graphics::SetStencilTestFunc(int stencilTest) { if (stencilTest >= StencilTest_Never && stencilTest <= StencilTest_GEqual) { StencilTest = stencilTest; if (Graphics::GfxFunctions->SetStencilTestFunc) Graphics::GfxFunctions->SetStencilTestFunc(stencilTest); } } -PUBLIC STATIC void Graphics::SetStencilPassFunc(int stencilOp) { +void Graphics::SetStencilPassFunc(int stencilOp) { if (stencilOp >= StencilOp_Keep && stencilOp <= StencilOp_DecrWrap) { StencilOpPass = stencilOp; if (Graphics::GfxFunctions->SetStencilPassFunc) Graphics::GfxFunctions->SetStencilPassFunc(stencilOp); } } -PUBLIC STATIC void Graphics::SetStencilFailFunc(int stencilOp) { +void Graphics::SetStencilFailFunc(int stencilOp) { if (stencilOp >= StencilOp_Keep && stencilOp <= StencilOp_DecrWrap) { StencilOpFail = stencilOp; if (Graphics::GfxFunctions->SetStencilFailFunc) Graphics::GfxFunctions->SetStencilFailFunc(stencilOp); } } -PUBLIC STATIC void Graphics::SetStencilValue(int value) { +void Graphics::SetStencilValue(int value) { if (value < 0) value = 0; else if (value > 255) @@ -1524,7 +1426,7 @@ PUBLIC STATIC void Graphics::SetStencilValue(int value) { if (Graphics::GfxFunctions->SetStencilValue) Graphics::GfxFunctions->SetStencilValue(value); } -PUBLIC STATIC void Graphics::SetStencilMask(int mask) { +void Graphics::SetStencilMask(int mask) { if (mask < 0) mask = 0; else if (mask > 255) @@ -1532,7 +1434,7 @@ PUBLIC STATIC void Graphics::SetStencilMask(int mask) { if (Graphics::GfxFunctions->SetStencilMask) Graphics::GfxFunctions->SetStencilMask(mask); } -PUBLIC STATIC void Graphics::ClearStencil() { +void Graphics::ClearStencil() { if (Graphics::GfxFunctions->ClearStencil) Graphics::GfxFunctions->ClearStencil(); } diff --git a/source/Engine/Hashing/CRC32.cpp b/source/Engine/Hashing/CRC32.cpp index 64d6d577..1c87c35e 100644 --- a/source/Engine/Hashing/CRC32.cpp +++ b/source/Engine/Hashing/CRC32.cpp @@ -1,26 +1,16 @@ -#if INTERFACE - -#include - -class CRC32 { -public: - -}; -#endif - #include -PUBLIC STATIC Uint32 CRC32::EncryptString(char* data) { +Uint32 CRC32::EncryptString(char* data) { return CRC32::EncryptData(data, strlen(data)); } -PUBLIC STATIC Uint32 CRC32::EncryptString(const char* message) { +Uint32 CRC32::EncryptString(const char* message) { return CRC32::EncryptString((char*)message); } -PUBLIC STATIC Uint32 CRC32::EncryptData(const void* data, size_t size) { +Uint32 CRC32::EncryptData(const void* data, size_t size) { return CRC32::EncryptData(data, size, 0xFFFFFFFFU); } -PUBLIC STATIC Uint32 CRC32::EncryptData(const void* data, size_t size, Uint32 crc) { +Uint32 CRC32::EncryptData(const void* data, size_t size, Uint32 crc) { int j; Uint32 byte, mask; Uint8* message = (Uint8*)data; diff --git a/source/Engine/Hashing/CombinedHash.cpp b/source/Engine/Hashing/CombinedHash.cpp index 50b3fb4c..35c83f80 100644 --- a/source/Engine/Hashing/CombinedHash.cpp +++ b/source/Engine/Hashing/CombinedHash.cpp @@ -1,27 +1,17 @@ -#if INTERFACE - -#include - -class CombinedHash { -public: - -}; -#endif - #include #include #include -PUBLIC STATIC Uint32 CombinedHash::EncryptString(char* data) { +Uint32 CombinedHash::EncryptString(char* data) { Uint8 objMD5[16]; return CRC32::EncryptData(MD5::EncryptString(objMD5, data), 16); } -PUBLIC STATIC Uint32 CombinedHash::EncryptString(const char* message) { +Uint32 CombinedHash::EncryptString(const char* message) { return CombinedHash::EncryptString((char*)message); } -PUBLIC STATIC Uint32 CombinedHash::EncryptData(const void* message, size_t len) { +Uint32 CombinedHash::EncryptData(const void* message, size_t len) { Uint8 objMD5[16]; return CRC32::EncryptData(MD5::EncryptData(objMD5, (void*)message, len), 16); } diff --git a/source/Engine/Hashing/FNV1A.cpp b/source/Engine/Hashing/FNV1A.cpp index 7f9e9338..2fda016c 100644 --- a/source/Engine/Hashing/FNV1A.cpp +++ b/source/Engine/Hashing/FNV1A.cpp @@ -1,16 +1,6 @@ -#if INTERFACE - -#include - -class FNV1A { -public: - -}; -#endif - #include -PUBLIC STATIC Uint32 FNV1A::EncryptString(char* message) { +Uint32 FNV1A::EncryptString(char* message) { Uint32 hash = 0x811C9DC5U; while (*message) { @@ -20,14 +10,14 @@ PUBLIC STATIC Uint32 FNV1A::EncryptString(char* message) { } return hash; } -PUBLIC STATIC Uint32 FNV1A::EncryptString(const char* message) { +Uint32 FNV1A::EncryptString(const char* message) { return FNV1A::EncryptString((char*)message); } -PUBLIC STATIC Uint32 FNV1A::EncryptData(const void* data, size_t size) { +Uint32 FNV1A::EncryptData(const void* data, size_t size) { return FNV1A::EncryptData(data, size, 0x811C9DC5U); } -PUBLIC STATIC Uint32 FNV1A::EncryptData(const void* data, size_t size, Uint32 hash) { +Uint32 FNV1A::EncryptData(const void* data, size_t size, Uint32 hash) { size_t i = size; char* message = (char*)data; while (i) { diff --git a/source/Engine/Hashing/MD5.cpp b/source/Engine/Hashing/MD5.cpp index 54c7bc85..583c7d64 100644 --- a/source/Engine/Hashing/MD5.cpp +++ b/source/Engine/Hashing/MD5.cpp @@ -1,13 +1,3 @@ -#if INTERFACE - -#include - -class MD5 { -public: - -}; -#endif - #include #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) @@ -33,7 +23,7 @@ class MD5 { (dst)[2] = (Uint8)((src) >> 16); \ (dst)[3] = (Uint8)((src) >> 24); -PRIVATE STATIC void* MD5::Body(Uint32* pa, Uint32* pb, Uint32* pc, Uint32* pd, void *data, unsigned long size) { +void* MD5::Body(Uint32* pa, Uint32* pb, Uint32* pc, Uint32* pd, void *data, unsigned long size) { Uint32 saved_a, saved_b, saved_c, saved_d; Uint8* ptr = (Uint8*)data; @@ -140,14 +130,14 @@ PRIVATE STATIC void* MD5::Body(Uint32* pa, Uint32* pb, Uint32* pc, Uint32* pd, v return ptr; } -PUBLIC STATIC Uint8* MD5::EncryptString(Uint8* dest, char* message) { +Uint8* MD5::EncryptString(Uint8* dest, char* message) { return MD5::EncryptData(dest, message, strlen(message)); } -PUBLIC STATIC Uint8* MD5::EncryptString(Uint8* dest, const char* message) { +Uint8* MD5::EncryptString(Uint8* dest, const char* message) { return MD5::EncryptString(dest, (char*)message); } -PUBLIC STATIC Uint8* MD5::EncryptData(Uint8* dest, void* data, size_t size) { +Uint8* MD5::EncryptData(Uint8* dest, void* data, size_t size) { // Init Uint8 buffer[64]; size_t lo = 0, hi = 0; diff --git a/source/Engine/Hashing/Murmur.cpp b/source/Engine/Hashing/Murmur.cpp index 346b0d10..4ec7fb65 100644 --- a/source/Engine/Hashing/Murmur.cpp +++ b/source/Engine/Hashing/Murmur.cpp @@ -1,27 +1,17 @@ -#if INTERFACE - -#include - -class Murmur { -public: - -}; -#endif - #include #include -PUBLIC STATIC Uint32 Murmur::EncryptString(char* message) { +Uint32 Murmur::EncryptString(char* message) { return Murmur::EncryptData(message, strlen(message), 0xDEADBEEF); } -PUBLIC STATIC Uint32 Murmur::EncryptString(const char* message) { +Uint32 Murmur::EncryptString(const char* message) { return Murmur::EncryptString((char*)message); } -PUBLIC STATIC Uint32 Murmur::EncryptData(const void* data, size_t size) { +Uint32 Murmur::EncryptData(const void* data, size_t size) { return Murmur::EncryptData(data, size, 0xDEADBEEF); } -PUBLIC STATIC Uint32 Murmur::EncryptData(const void* key, size_t size, Uint32 hash) { +Uint32 Murmur::EncryptData(const void* key, size_t size, Uint32 hash) { const unsigned int m = 0x5bd1e995; const int r = 24; unsigned int h = hash ^ (Uint32)size; diff --git a/source/Engine/IO/Compression/Huffman.cpp b/source/Engine/IO/Compression/Huffman.cpp index a7e10998..ded20d25 100644 --- a/source/Engine/IO/Compression/Huffman.cpp +++ b/source/Engine/IO/Compression/Huffman.cpp @@ -1,14 +1,6 @@ -#if INTERFACE -#include -class Huffman { -public: - -}; -#endif - #include -PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { +bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { #define datat_t uint8_t datat_t* in_head = (datat_t*)in; datat_t* out_head = (datat_t*)out; @@ -23,26 +15,11 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, return false; // get tree size - // if (!buffer_read(buffer, &tree[0], 1, callback, userdata)) { - // free(tree); - // return false; - // } tree[0] = *in_head++; - printf("Tree Size: %X (%d)\n", tree[0], tree[0]); // read tree - // if (!buffer_read(buffer, &tree[1], (((size_t)tree[0])+1)*2-1, callback, userdata)) { - // free(tree); - // return false; - // } int len_to_read = (tree[0] + 1) * 2 - 1; memcpy(&tree[1], in_head, len_to_read); - printf("Tree Size To Read: %X (%d)\n", len_to_read, len_to_read); - printf("Nodes: "); - for (int i = 0; i < len_to_read; i++) { - printf("%02X ", tree[1 + i]); - } - printf("\n"); in_head += len_to_read; uint32_t word = 0; // 32-bits of input bitstream @@ -81,8 +58,6 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, | (wordbuf[1] << 8) | (wordbuf[2] << 16) | (wordbuf[3] << 24); - - printf("New Word: %08X\n", word); } // read the current node's offset value @@ -95,9 +70,6 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, // point to the "right" child child++; - printf("r node: %zu (%02X)\n", node, tree[node]); - printf("r child: %zu (%02X)\n", child, tree[child]); - // "right" child is a data node if (tree[node] & 0x40) { // copy the child node into the output buffer and apply mask @@ -106,8 +78,6 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, *out_head++ = tree[child] & dataMask; --size; - printf("found: node (%02X), child (%02X)\n", tree[node], tree[child]); - // start over at the root node node = 1; } @@ -118,8 +88,6 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, else { // pointed to the "left" child - printf("l node: %zu (%02X)\n", node, tree[node]); - printf("l child: %zu (%02X)\n", child, tree[child]); // "left" child is a data node if (tree[node] & 0x80) { // copy the child node into the output buffer and apply mask @@ -128,8 +96,6 @@ PUBLIC STATIC bool Huffman::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, *out_head++ = tree[child] & dataMask; --size; - printf("found: node (%02X), child (%02X)\n", tree[node], tree[child]); - // start over at the root node node = 1; } diff --git a/source/Engine/IO/Compression/LZ11.cpp b/source/Engine/IO/Compression/LZ11.cpp index d9f8899b..659e7dd8 100644 --- a/source/Engine/IO/Compression/LZ11.cpp +++ b/source/Engine/IO/Compression/LZ11.cpp @@ -1,19 +1,10 @@ -#if INTERFACE -#include -class LZ11 { -public: - -}; -#endif - #include -PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { - typedef uint8_t datat_t; +bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { int i; - datat_t flags; - datat_t* in_head = (datat_t*)in; - datat_t* out_head = (datat_t*)out; + uint8_t flags; + uint8_t* in_head = (uint8_t*)in; + uint8_t* out_head = (uint8_t*)out; size_t size = out_sz; int bits = sizeof(flags) << 3; @@ -25,26 +16,18 @@ PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, siz // 0: raw byte // 1: compressed block flags = *in_head++; - if (in_head >= in_sz + (datat_t*)in) + if (in_head >= in_sz + (uint8_t*)in) return false; - // printf("Flag: %04X (", flags); - for (i = 0; i < bits; i++) { - // if (!(i & 7) && i) - // printf(" "); - // printf("%d", ((flags << i) & mask) >> (bits - 1)); - } - // printf(")\n"); - // the first flag cannot start with 1, as that needs data to pull from for (i = 0; i < bits && size > 0; i++, flags <<= 1) { // Compressed block if (flags & 0x80) { - datat_t displen[4]; + uint8_t displen[4]; displen[0] = *in_head++; - if (in_head >= in_sz + (datat_t*)in) + if (in_head >= in_sz + (uint8_t*)in) return false; size_t len; // length @@ -53,8 +36,8 @@ PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, siz switch (displen[pos] >> 4) { case 0: // extended block - displen[1] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; - displen[2] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; + displen[1] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; + displen[2] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; len = displen[pos++] << 4; len |= displen[pos] >> 4; @@ -62,9 +45,9 @@ PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, siz break; case 1: // extra extended block - displen[1] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; - displen[2] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; - displen[3] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; + displen[1] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; + displen[2] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; + displen[3] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; len = (displen[pos++] & 0x0F) << 12; len |= (displen[pos++]) << 4; @@ -73,9 +56,7 @@ PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, siz break; default: // normal block - // if (!buffer_get(buffer, &displen[1], callback, userdata)) - // return false; - displen[1] = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; + displen[1] = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; len = (displen[pos] >> 4) + 1; break; @@ -89,22 +70,15 @@ PUBLIC STATIC bool LZ11::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, siz size -= len; - // iov_iter in = out; - // iov_sub(&in, disp + 1); - // iov_memmove(&out, &in, len); - - datat_t* sup = out_head - (disp + 1); - // printf("Len: %d\n", lol); + uint8_t* sup = out_head - (disp + 1); while (len-- > 0) { - // printf("Out (cmp): %04X\n", *sup); *out_head++ = *sup++; } } // Uncompressed block else { - // printf("Out (raw): %04X\n", *in_head); // copy a raw byte from the input to the output - *out_head++ = *in_head++; if (in_head >= in_sz + (datat_t*)in) return false; + *out_head++ = *in_head++; if (in_head >= in_sz + (uint8_t*)in) return false; --size; } } diff --git a/source/Engine/IO/Compression/LZSS.cpp b/source/Engine/IO/Compression/LZSS.cpp index 2070efb8..9b06964a 100644 --- a/source/Engine/IO/Compression/LZSS.cpp +++ b/source/Engine/IO/Compression/LZSS.cpp @@ -1,67 +1,5 @@ -#if INTERFACE -#include -class LZSS { -public: - -}; -#endif - #include -PUBLIC STATIC bool LZSS::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { - /* - uint8_t flags = 0; - uint8_t mask = 0; - unsigned int len; - unsigned int disp; - - while(size > 0) - { - if(mask == 0) - { - // read in the flags data - // from bit 7 to bit 0: - // 0: raw byte - // 1: compressed block - if(!buffer_get(buffer, &flags, callback, userdata)) - return false; - mask = 0x80; - } - - if(flags & mask) // compressed block - { - uint8_t displen[2]; - if(!buffer_get(buffer, &displen[0], callback, userdata) - || !buffer_get(buffer, &displen[1], callback, userdata)) - return false; - - // disp: displacement - // len: length - len = ((displen[0] & 0xF0) >> 4) + 3; - disp = displen[0] & 0x0F; - disp = disp << 8 | displen[1]; - - if(len > size) - len = size; - - size -= len; - - iov_iter in = out; - iov_sub(&in, disp+1); - iov_memmove(&out, &in, len); - } - else // uncompressed block - { - // copy a raw byte from the input to the output - if(!buffer_get(buffer, iov_addr(&out), callback, userdata)) - return false; - - --size; - iov_increment(&out); - } - - mask >>= 1; - } -//*/ - return true; +bool LZSS::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { + return true; } diff --git a/source/Engine/IO/Compression/RunLength.cpp b/source/Engine/IO/Compression/RunLength.cpp index 272b8d7d..badea381 100644 --- a/source/Engine/IO/Compression/RunLength.cpp +++ b/source/Engine/IO/Compression/RunLength.cpp @@ -1,14 +1,6 @@ -#if INTERFACE -#include -class RunLength { -public: - -}; -#endif - #include -PUBLIC STATIC bool RunLength::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { +bool RunLength::Decompress(uint8_t* in, size_t in_sz, uint8_t* out, size_t out_sz) { uint8_t byte; size_t len; uint8_t* in_head = in; diff --git a/source/Engine/IO/Compression/ZLibStream.cpp b/source/Engine/IO/Compression/ZLibStream.cpp index 686f7428..85e08b31 100644 --- a/source/Engine/IO/Compression/ZLibStream.cpp +++ b/source/Engine/IO/Compression/ZLibStream.cpp @@ -1,16 +1,3 @@ -#if INTERFACE -#include -#include -class ZLibStream : public Stream { -public: - Stream* other_stream = NULL; - uint32_t mode = 0; - - void* memory = NULL; - size_t memory_size = 0; -}; -#endif - #include #include @@ -20,7 +7,7 @@ class ZLibStream : public Stream { #define MINIZ_HEADER_FILE_ONLY #include -PUBLIC STATIC ZLibStream* ZLibStream::New(Stream* other_stream, uint32_t mode) { +ZLibStream* ZLibStream::New(Stream* other_stream, uint32_t mode) { ZLibStream* stream = new ZLibStream; if (!stream) { return NULL; @@ -51,7 +38,7 @@ PUBLIC STATIC ZLibStream* ZLibStream::New(Stream* other_stream, uint32_t mode) { return NULL; } -PUBLIC void ZLibStream::Close() { +void ZLibStream::Close() { if (memory) { Memory::Free(memory); memory_size = 0; @@ -60,37 +47,37 @@ PUBLIC void ZLibStream::Close() { Stream::Close(); } -PUBLIC void ZLibStream::Seek(Sint64 offset) { +void ZLibStream::Seek(Sint64 offset) { // pointer = pointer_start + offset; } -PUBLIC void ZLibStream::SeekEnd(Sint64 offset) { +void ZLibStream::SeekEnd(Sint64 offset) { // pointer = pointer_start + size - offset; } -PUBLIC void ZLibStream::Skip(Sint64 offset) { +void ZLibStream::Skip(Sint64 offset) { // pointer = pointer + offset; } -PUBLIC size_t ZLibStream::Position() { +size_t ZLibStream::Position() { // return pointer - pointer_start; return 0; } -PUBLIC size_t ZLibStream::Length() { +size_t ZLibStream::Length() { // return pointer - pointer_start; return 0; } -PUBLIC size_t ZLibStream::ReadBytes(void* data, size_t n) { +size_t ZLibStream::ReadBytes(void* data, size_t n) { memcpy(data, memory, n); // pointer += n; return n; } -PUBLIC size_t ZLibStream::WriteBytes(void* data, size_t n) { +size_t ZLibStream::WriteBytes(void* data, size_t n) { // memcpy(pointer, data, n); // pointer += n; return n; } -PUBLIC STATIC void ZLibStream::Decompress(void* dst, size_t dstLen, void* src, size_t srcLen) { +void ZLibStream::Decompress(void* dst, size_t dstLen, void* src, size_t srcLen) { z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; @@ -106,7 +93,7 @@ PUBLIC STATIC void ZLibStream::Decompress(void* dst, size_t dstLen, void* inflateEnd(&infstream); } -PRIVATE void ZLibStream::Decompress(void* in, size_t inLen) { +void ZLibStream::Decompress(void* in, size_t inLen) { z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; diff --git a/source/Engine/IO/FileStream.cpp b/source/Engine/IO/FileStream.cpp index bb24e683..dc207e71 100644 --- a/source/Engine/IO/FileStream.cpp +++ b/source/Engine/IO/FileStream.cpp @@ -1,20 +1,3 @@ -#if INTERFACE -#include -#include -class FileStream : public Stream { -public: - FILE* f; - size_t size; - enum { - READ_ACCESS = 0, - WRITE_ACCESS = 1, - APPEND_ACCESS = 2, - SAVEGAME_ACCESS = 16, - PREFERENCES_ACCESS = 32, - }; -}; -#endif - #include #include #include @@ -25,7 +8,7 @@ extern "C" { } #endif -PUBLIC STATIC FileStream* FileStream::New(const char* filename, Uint32 access) { +FileStream* FileStream::New(const char* filename, Uint32 access) { FileStream* stream = new (std::nothrow) FileStream; if (!stream) { return NULL; @@ -131,32 +114,32 @@ PUBLIC STATIC FileStream* FileStream::New(const char* filename, Uint32 access) { return NULL; } -PUBLIC void FileStream::Close() { +void FileStream::Close() { fclose(f); f = NULL; Stream::Close(); } -PUBLIC void FileStream::Seek(Sint64 offset) { +void FileStream::Seek(Sint64 offset) { fseek(f, offset, SEEK_SET); } -PUBLIC void FileStream::SeekEnd(Sint64 offset) { +void FileStream::SeekEnd(Sint64 offset) { fseek(f, offset, SEEK_END); } -PUBLIC void FileStream::Skip(Sint64 offset) { +void FileStream::Skip(Sint64 offset) { fseek(f, offset, SEEK_CUR); } -PUBLIC size_t FileStream::Position() { +size_t FileStream::Position() { return ftell(f); } -PUBLIC size_t FileStream::Length() { +size_t FileStream::Length() { return size; } -PUBLIC size_t FileStream::ReadBytes(void* data, size_t n) { +size_t FileStream::ReadBytes(void* data, size_t n) { // if (!f) Log::Print(Log::LOG_ERROR, "Attempt to read from closed stream.") return fread(data, 1, n, f); } -PUBLIC size_t FileStream::WriteBytes(void* data, size_t n) { +size_t FileStream::WriteBytes(void* data, size_t n) { return fwrite(data, 1, n, f); } diff --git a/source/Engine/IO/MemoryStream.cpp b/source/Engine/IO/MemoryStream.cpp index 36cbcfdd..22eb2ee2 100644 --- a/source/Engine/IO/MemoryStream.cpp +++ b/source/Engine/IO/MemoryStream.cpp @@ -1,19 +1,7 @@ -#if INTERFACE -#include -#include -class MemoryStream : public Stream { -public: - Uint8* pointer = NULL; - Uint8* pointer_start = NULL; - size_t size = 0; - bool owns_memory = false; -}; -#endif - #include #include -PUBLIC STATIC MemoryStream* MemoryStream::New(size_t size) { +MemoryStream* MemoryStream::New(size_t size) { void* data = Memory::Malloc(size); MemoryStream* stream = MemoryStream::New(data, size); if (!stream) { @@ -24,7 +12,7 @@ PUBLIC STATIC MemoryStream* MemoryStream::New(size_t size) { } return stream; } -PUBLIC STATIC MemoryStream* MemoryStream::New(Stream* other) { +MemoryStream* MemoryStream::New(Stream* other) { MemoryStream* stream = MemoryStream::New(other->Length()); if (stream) { other->CopyTo(stream); @@ -32,7 +20,7 @@ PUBLIC STATIC MemoryStream* MemoryStream::New(Stream* other) { } return stream; } -PUBLIC STATIC MemoryStream* MemoryStream::New(void* data, size_t size) { +MemoryStream* MemoryStream::New(void* data, size_t size) { MemoryStream* stream = new (std::nothrow) MemoryStream; if (!stream) { return NULL; @@ -52,29 +40,29 @@ PUBLIC STATIC MemoryStream* MemoryStream::New(void* data, size_t size) { return NULL; } -PUBLIC void MemoryStream::Close() { +void MemoryStream::Close() { if (owns_memory) Memory::Free(pointer_start); Stream::Close(); } -PUBLIC void MemoryStream::Seek(Sint64 offset) { +void MemoryStream::Seek(Sint64 offset) { pointer = pointer_start + offset; } -PUBLIC void MemoryStream::SeekEnd(Sint64 offset) { +void MemoryStream::SeekEnd(Sint64 offset) { pointer = pointer_start + size + offset; } -PUBLIC void MemoryStream::Skip(Sint64 offset) { +void MemoryStream::Skip(Sint64 offset) { pointer = pointer + offset; } -PUBLIC size_t MemoryStream::Position() { +size_t MemoryStream::Position() { return pointer - pointer_start; } -PUBLIC size_t MemoryStream::Length() { +size_t MemoryStream::Length() { return size; } -PUBLIC size_t MemoryStream::ReadBytes(void* data, size_t n) { +size_t MemoryStream::ReadBytes(void* data, size_t n) { if (n > size - Position()) { n = size - Position(); } @@ -84,7 +72,7 @@ PUBLIC size_t MemoryStream::ReadBytes(void* data, size_t n) { pointer += n; return n; } -PUBLIC Uint32 MemoryStream::ReadCompressed(void* out) { +Uint32 MemoryStream::ReadCompressed(void* out) { Uint32 compressed_size = ReadUInt32() - 4; Uint32 uncompressed_size = ReadUInt32BE(); @@ -93,7 +81,7 @@ PUBLIC Uint32 MemoryStream::ReadCompressed(void* out) { return uncompressed_size; } -PUBLIC Uint32 MemoryStream::ReadCompressed(void* out, size_t outSz) { +Uint32 MemoryStream::ReadCompressed(void* out, size_t outSz) { Uint32 compressed_size = ReadUInt32() - 4; ReadUInt32BE(); // Uint32 uncompressed_size = ReadUInt32BE(); @@ -103,7 +91,7 @@ PUBLIC Uint32 MemoryStream::ReadCompressed(void* out, size_t outSz return (Uint32)outSz; } -PUBLIC size_t MemoryStream::WriteBytes(void* data, size_t n) { +size_t MemoryStream::WriteBytes(void* data, size_t n) { if (Position() + n > size) { size_t pos = Position(); pointer_start = (unsigned char*)Memory::Realloc(pointer_start, pos + n); diff --git a/source/Engine/IO/NetworkStream.cpp b/source/Engine/IO/NetworkStream.cpp index 2aa1b81a..14ec9eb3 100644 --- a/source/Engine/IO/NetworkStream.cpp +++ b/source/Engine/IO/NetworkStream.cpp @@ -1,21 +1,7 @@ -#if INTERFACE -#include -#include -class NetworkStream : public Stream { -public: - FILE* f; - size_t size; - enum { - SERVER_SOCKET = 0, - CLIENT_SOCKET = 1, - }; -}; -#endif - #include #include -PUBLIC STATIC NetworkStream* NetworkStream::New(const char* filename, Uint32 access) { +NetworkStream* NetworkStream::New(const char* filename, Uint32 access) { NetworkStream* stream = new NetworkStream; if (!stream) { return NULL; @@ -55,32 +41,32 @@ PUBLIC STATIC NetworkStream* NetworkStream::New(const char* filename, Uint32 acc return NULL; } -PUBLIC void NetworkStream::Close() { +void NetworkStream::Close() { fclose(f); f = NULL; Stream::Close(); } -PUBLIC void NetworkStream::Seek(Sint64 offset) { +void NetworkStream::Seek(Sint64 offset) { fseek(f, offset, SEEK_SET); } -PUBLIC void NetworkStream::SeekEnd(Sint64 offset) { +void NetworkStream::SeekEnd(Sint64 offset) { fseek(f, offset, SEEK_END); } -PUBLIC void NetworkStream::Skip(Sint64 offset) { +void NetworkStream::Skip(Sint64 offset) { fseek(f, offset, SEEK_CUR); } -PUBLIC size_t NetworkStream::Position() { +size_t NetworkStream::Position() { return ftell(f); } -PUBLIC size_t NetworkStream::Length() { +size_t NetworkStream::Length() { return size; } -PUBLIC size_t NetworkStream::ReadBytes(void* data, size_t n) { +size_t NetworkStream::ReadBytes(void* data, size_t n) { // if (!f) Log::Print(Log::LOG_ERROR, "Attempt to read from closed stream.") return fread(data, 1, n, f); } -PUBLIC size_t NetworkStream::WriteBytes(void* data, size_t n) { +size_t NetworkStream::WriteBytes(void* data, size_t n) { return fwrite(data, 1, n, f); } diff --git a/source/Engine/IO/ResourceStream.cpp b/source/Engine/IO/ResourceStream.cpp index 976abd9c..c8e75c45 100644 --- a/source/Engine/IO/ResourceStream.cpp +++ b/source/Engine/IO/ResourceStream.cpp @@ -1,19 +1,8 @@ -#if INTERFACE -#include -#include -class ResourceStream : public Stream { -public: - Uint8* pointer = NULL; - Uint8* pointer_start = NULL; - size_t size = 0; -}; -#endif - #include #include -PUBLIC STATIC ResourceStream* ResourceStream::New(const char* filename) { +ResourceStream* ResourceStream::New(const char* filename) { ResourceStream* stream = new (std::nothrow) ResourceStream; if (!stream) { return NULL; @@ -34,27 +23,27 @@ PUBLIC STATIC ResourceStream* ResourceStream::New(const char* filename) { return NULL; } -PUBLIC void ResourceStream::Close() { +void ResourceStream::Close() { Memory::Free(pointer_start); Stream::Close(); } -PUBLIC void ResourceStream::Seek(Sint64 offset) { +void ResourceStream::Seek(Sint64 offset) { pointer = pointer_start + offset; } -PUBLIC void ResourceStream::SeekEnd(Sint64 offset) { +void ResourceStream::SeekEnd(Sint64 offset) { pointer = pointer_start + size + offset; } -PUBLIC void ResourceStream::Skip(Sint64 offset) { +void ResourceStream::Skip(Sint64 offset) { pointer = pointer + offset; } -PUBLIC size_t ResourceStream::Position() { +size_t ResourceStream::Position() { return pointer - pointer_start; } -PUBLIC size_t ResourceStream::Length() { +size_t ResourceStream::Length() { return size; } -PUBLIC size_t ResourceStream::ReadBytes(void* data, size_t n) { +size_t ResourceStream::ReadBytes(void* data, size_t n) { if (n > size - Position()) { n = size - Position(); } @@ -64,7 +53,7 @@ PUBLIC size_t ResourceStream::ReadBytes(void* data, size_t n) { pointer += n; return n; } -PUBLIC size_t ResourceStream::WriteBytes(void* data, size_t n) { +size_t ResourceStream::WriteBytes(void* data, size_t n) { // Cannot write to a resource. return 0; } diff --git a/source/Engine/IO/SDLStream.cpp b/source/Engine/IO/SDLStream.cpp index 618dbf7c..c24cd46e 100644 --- a/source/Engine/IO/SDLStream.cpp +++ b/source/Engine/IO/SDLStream.cpp @@ -1,21 +1,6 @@ -#if INTERFACE -#include -#include -#include -class SDLStream : public Stream { -public: - SDL_RWops* f; - enum { - READ_ACCESS = 0, - WRITE_ACCESS = 1, - APPEND_ACCESS = 2, - }; -}; -#endif - #include -PUBLIC STATIC SDLStream* SDLStream::New(const char* filename, Uint32 access) { +SDLStream* SDLStream::New(const char* filename, Uint32 access) { SDLStream* stream = new SDLStream; if (!stream) { return NULL; @@ -40,32 +25,32 @@ PUBLIC STATIC SDLStream* SDLStream::New(const char* filename, Uint32 access) { return NULL; } -PUBLIC void SDLStream::Close() { +void SDLStream::Close() { SDL_RWclose(f); f = NULL; Stream::Close(); } -PUBLIC void SDLStream::Seek(Sint64 offset) { +void SDLStream::Seek(Sint64 offset) { SDL_RWseek(f, offset, RW_SEEK_SET); } -PUBLIC void SDLStream::SeekEnd(Sint64 offset) { +void SDLStream::SeekEnd(Sint64 offset) { SDL_RWseek(f, offset, RW_SEEK_END); } -PUBLIC void SDLStream::Skip(Sint64 offset) { +void SDLStream::Skip(Sint64 offset) { SDL_RWseek(f, offset, RW_SEEK_CUR); } -PUBLIC size_t SDLStream::Position() { +size_t SDLStream::Position() { return SDL_RWtell(f); } -PUBLIC size_t SDLStream::Length() { +size_t SDLStream::Length() { return SDL_RWsize(f); } -PUBLIC size_t SDLStream::ReadBytes(void* data, size_t n) { +size_t SDLStream::ReadBytes(void* data, size_t n) { // if (!f) Log::Print(Log::LOG_ERROR, "Attempt to read from closed stream.") return SDL_RWread(f, data, 1, n); } -PUBLIC size_t SDLStream::WriteBytes(void* data, size_t n) { +size_t SDLStream::WriteBytes(void* data, size_t n) { return SDL_RWwrite(f, data, 1, n); } diff --git a/source/Engine/IO/Serializer.cpp b/source/Engine/IO/Serializer.cpp index cffe5bfa..db800339 100644 --- a/source/Engine/IO/Serializer.cpp +++ b/source/Engine/IO/Serializer.cpp @@ -1,57 +1,3 @@ -#if INTERFACE -#include -#include - -class Serializer { -public: - std::map ObjToID; - std::vector ObjList; - Stream* StreamPtr; - - size_t StoredStreamPos; - size_t StoredChunkPos; - Uint32 CurrentChunkType; - - struct Chunk { - Uint32 Type; - size_t Offset; - size_t Size; - }; - std::vector ChunkList; - Serializer::Chunk LastChunk; - - struct String { - Uint32 Length; - char* Chars; - }; - std::vector StringList; - - enum { - CHUNK_OBJS = MakeFourCC("OBJS"), - CHUNK_TEXT = MakeFourCC("TEXT") - }; - - enum { - VAL_TYPE_NULL, - VAL_TYPE_INTEGER, - VAL_TYPE_DECIMAL, - VAL_TYPE_OBJECT, - - END = 0xFF - }; - - enum { - OBJ_TYPE_UNIMPLEMENTED, - OBJ_TYPE_STRING, - OBJ_TYPE_ARRAY, - OBJ_TYPE_MAP - }; - - static Uint32 Magic; - static Uint32 Version; -}; -#endif - #include #include @@ -59,7 +5,7 @@ class Serializer { Uint32 Serializer::Magic = 0x9D939FF0; Uint32 Serializer::Version = 0x00000001; -PUBLIC Serializer::Serializer(Stream* stream) { +Serializer::Serializer(Stream* stream) { StreamPtr = stream; ObjToID.clear(); ObjList.clear(); @@ -67,7 +13,7 @@ PUBLIC Serializer::Serializer(Stream* stream) { StringList.clear(); } -PRIVATE void Serializer::WriteValue(VMValue val) { +void Serializer::WriteValue(VMValue val) { switch (val.Type) { case VAL_DECIMAL: case VAL_LINKED_DECIMAL: { @@ -106,7 +52,7 @@ PRIVATE void Serializer::WriteValue(VMValue val) { } } -PRIVATE void Serializer::WriteObject(Obj* obj) { +void Serializer::WriteObject(Obj* obj) { switch (obj->Type) { case OBJ_STRING: { WriteObjectPreamble(Serializer::OBJ_TYPE_STRING); @@ -161,7 +107,7 @@ PRIVATE void Serializer::WriteObject(Obj* obj) { PatchObjectSize(); } -PRIVATE void Serializer::WriteObjectsChunk() { +void Serializer::WriteObjectsChunk() { BeginChunk(Serializer::CHUNK_OBJS); StreamPtr->WriteUInt32(ObjList.size()); @@ -173,7 +119,7 @@ PRIVATE void Serializer::WriteObjectsChunk() { AddChunkToList(); } -PRIVATE void Serializer::WriteTextChunk() { +void Serializer::WriteTextChunk() { BeginChunk(Serializer::CHUNK_TEXT); StreamPtr->WriteUInt32(StringList.size()); @@ -190,19 +136,19 @@ PRIVATE void Serializer::WriteTextChunk() { ChunkList.insert(ChunkList.begin(), LastChunk); } -PRIVATE Uint32 Serializer::GetUniqueObjectID(Obj* obj) { +Uint32 Serializer::GetUniqueObjectID(Obj* obj) { if (ObjToID.count(obj)) return ObjToID[obj]; return 0xFFFFFFFF; } -PRIVATE void Serializer::BeginChunk(Uint32 type) { +void Serializer::BeginChunk(Uint32 type) { CurrentChunkType = type; StoredChunkPos = StreamPtr->Position(); } -PRIVATE void Serializer::FinishChunk() { +void Serializer::FinishChunk() { LastChunk.Type = CurrentChunkType; LastChunk.Offset = StoredChunkPos; LastChunk.Size = StreamPtr->Position() - StoredChunkPos; @@ -211,18 +157,18 @@ PRIVATE void Serializer::FinishChunk() { StreamPtr->WriteByte(Serializer::END); } -PRIVATE void Serializer::AddChunkToList() { +void Serializer::AddChunkToList() { ChunkList.push_back(LastChunk); } -PRIVATE void Serializer::WriteObjectPreamble(Uint8 type) { +void Serializer::WriteObjectPreamble(Uint8 type) { StreamPtr->WriteByte(type); StreamPtr->WriteUInt32(0); // To be patched in later StoredStreamPos = StreamPtr->Position(); } -PRIVATE void Serializer::PatchObjectSize() { +void Serializer::PatchObjectSize() { size_t curPos = StreamPtr->Position(); size_t size = curPos - StoredStreamPos; StreamPtr->Seek(StoredStreamPos - 4); @@ -230,7 +176,7 @@ PRIVATE void Serializer::PatchObjectSize() { StreamPtr->Seek(curPos); } -PRIVATE void Serializer::AddUniqueString(char* chars, size_t length) { +void Serializer::AddUniqueString(char* chars, size_t length) { if (StringList.size() >= 0xFFFFFFFF) return; @@ -245,7 +191,7 @@ PRIVATE void Serializer::AddUniqueString(char* chars, size_t length) { StringList.push_back(str); } -PRIVATE Uint32 Serializer::GetUniqueStringID(char* chars, size_t length) { +Uint32 Serializer::GetUniqueStringID(char* chars, size_t length) { for (size_t i = 0; i < StringList.size(); i++) { if (StringList[i].Length == length && !memcmp(StringList[i].Chars, chars, length)) return (Uint32)i; @@ -254,7 +200,7 @@ PRIVATE Uint32 Serializer::GetUniqueStringID(char* chars, size_t length) { return 0xFFFFFFFF; } -PRIVATE void Serializer::AddUniqueObject(Obj* obj) { +void Serializer::AddUniqueObject(Obj* obj) { if (ObjToID.count(obj) || ObjList.size() >= 0xFFFFFFFF) return; @@ -292,7 +238,7 @@ PRIVATE void Serializer::AddUniqueObject(Obj* obj) { } } -PUBLIC void Serializer::Store(VMValue val) { +void Serializer::Store(VMValue val) { // Write header StreamPtr->WriteUInt32(Serializer::Magic); StreamPtr->WriteUInt32(Serializer::Version); @@ -345,7 +291,7 @@ PUBLIC void Serializer::Store(VMValue val) { ObjList.clear(); } -PRIVATE void Serializer::GetObject() { +void Serializer::GetObject() { Uint8 type = StreamPtr->ReadByte(); Uint32 size = StreamPtr->ReadUInt32(); switch (type) { @@ -388,7 +334,7 @@ PRIVATE void Serializer::GetObject() { } } -PRIVATE void Serializer::ReadObject(Obj* obj) { +void Serializer::ReadObject(Obj* obj) { Uint8 type = StreamPtr->ReadByte(); Uint32 size = StreamPtr->ReadUInt32(); switch (type) { @@ -428,7 +374,7 @@ PRIVATE void Serializer::ReadObject(Obj* obj) { } } -PRIVATE VMValue Serializer::ReadValue() { +VMValue Serializer::ReadValue() { Uint8 type = StreamPtr->ReadByte(); switch (type) { case Serializer::VAL_TYPE_INTEGER: @@ -455,7 +401,7 @@ PRIVATE VMValue Serializer::ReadValue() { return NULL_VAL; } -PUBLIC bool Serializer::ReadObjectsChunk() { +bool Serializer::ReadObjectsChunk() { // Read the object count Uint32 count = StreamPtr->ReadUInt32(); if (!count) @@ -479,7 +425,7 @@ PUBLIC bool Serializer::ReadObjectsChunk() { return StreamPtr->ReadByte() == Serializer::END; } -PUBLIC bool Serializer::ReadTextChunk() { +bool Serializer::ReadTextChunk() { // Read the count Uint32 count = StreamPtr->ReadUInt32(); @@ -499,7 +445,7 @@ PUBLIC bool Serializer::ReadTextChunk() { return StreamPtr->ReadByte() == Serializer::END; } -PUBLIC VMValue Serializer::Retrieve() { +VMValue Serializer::Retrieve() { Uint32 magic = StreamPtr->ReadUInt32(); if (magic != Serializer::Magic) { Log::Print(Log::LOG_ERROR, "Invalid magic!"); diff --git a/source/Engine/IO/Stream.cpp b/source/Engine/IO/Stream.cpp index 2f8f84c3..1ce953bc 100644 --- a/source/Engine/IO/Stream.cpp +++ b/source/Engine/IO/Stream.cpp @@ -1,11 +1,3 @@ -#if INTERFACE -#include -#include -class Stream { -public: -}; -#endif - #include #include #include @@ -14,23 +6,23 @@ class Stream { type data; \ ReadBytes(&data, sizeof(data)); -PUBLIC VIRTUAL void Stream::Close() { - delete this; +void Stream::Close() { + delete this; } -PUBLIC VIRTUAL void Stream::Seek(Sint64 offset) { +void Stream::Seek(Sint64 offset) { } -PUBLIC VIRTUAL void Stream::SeekEnd(Sint64 offset) { +void Stream::SeekEnd(Sint64 offset) { } -PUBLIC VIRTUAL void Stream::Skip(Sint64 offset) { +void Stream::Skip(Sint64 offset) { } -PUBLIC VIRTUAL size_t Stream::Position() { - return 0; +size_t Stream::Position() { + return 0; } -PUBLIC VIRTUAL size_t Stream::Length() { - return 0; +size_t Stream::Length() { + return 0; } -PUBLIC VIRTUAL size_t Stream::ReadBytes(void* data, size_t n) { +size_t Stream::ReadBytes(void* data, size_t n) { #if DEBUG if (Position() + n > Length()) { Log::Print(Log::LOG_ERROR, "Attempted to read past stream."); @@ -39,51 +31,51 @@ PUBLIC VIRTUAL size_t Stream::ReadBytes(void* data, size_t n) { #endif return 0; } -PUBLIC Uint8 Stream::ReadByte() { +Uint8 Stream::ReadByte() { READ_TYPE_MACRO(Uint8); return data; } -PUBLIC Uint16 Stream::ReadUInt16() { +Uint16 Stream::ReadUInt16() { READ_TYPE_MACRO(Uint16); return data; } -PUBLIC Uint16 Stream::ReadUInt16BE() { +Uint16 Stream::ReadUInt16BE() { return (Uint16)(ReadByte() << 8 | ReadByte()); } -PUBLIC Uint32 Stream::ReadUInt32() { +Uint32 Stream::ReadUInt32() { READ_TYPE_MACRO(Uint32); return data; } -PUBLIC Uint32 Stream::ReadUInt32BE() { +Uint32 Stream::ReadUInt32BE() { return (Uint32)(ReadByte() << 24 | ReadByte() << 16 | ReadByte() << 8 | ReadByte()); } -PUBLIC Uint64 Stream::ReadUInt64() { +Uint64 Stream::ReadUInt64() { READ_TYPE_MACRO(Uint64); return data; } -PUBLIC Sint16 Stream::ReadInt16() { +Sint16 Stream::ReadInt16() { READ_TYPE_MACRO(Sint16); return data; } -PUBLIC Sint16 Stream::ReadInt16BE() { +Sint16 Stream::ReadInt16BE() { return (Sint16)(ReadByte() << 8 | ReadByte()); } -PUBLIC Sint32 Stream::ReadInt32() { +Sint32 Stream::ReadInt32() { READ_TYPE_MACRO(Sint32); return data; } -PUBLIC Sint32 Stream::ReadInt32BE() { +Sint32 Stream::ReadInt32BE() { return (Sint32)(ReadByte() << 24 | ReadByte() << 16 | ReadByte() << 8 | ReadByte()); } -PUBLIC Sint64 Stream::ReadInt64() { +Sint64 Stream::ReadInt64() { READ_TYPE_MACRO(Sint64); return data; } -PUBLIC float Stream::ReadFloat() { +float Stream::ReadFloat() { READ_TYPE_MACRO(float); return data; } -PUBLIC char* Stream::ReadLine() { +char* Stream::ReadLine() { Uint8 byte = 0; size_t start = Position(); while ((byte = ReadByte()) != '\n' && byte); @@ -97,7 +89,7 @@ PUBLIC char* Stream::ReadLine() { return data; } -PUBLIC char* Stream::ReadString() { +char* Stream::ReadString() { size_t start = Position(); while (ReadByte()); @@ -110,10 +102,10 @@ PUBLIC char* Stream::ReadString() { return data; } -PUBLIC void Stream::SkipString() { +void Stream::SkipString() { while (ReadByte()); } -PUBLIC Uint16* Stream::ReadUnicodeString() { +Uint16* Stream::ReadUnicodeString() { size_t start = Position(); while (ReadUInt16()); @@ -125,8 +117,8 @@ PUBLIC Uint16* Stream::ReadUnicodeString() { return data; } -PUBLIC char* Stream::ReadHeaderedString() { - Uint8 size = ReadByte(); +char* Stream::ReadHeaderedString() { + Uint8 size = ReadByte(); char* data = (char*)Memory::TrackedMalloc("Stream::ReadHeaderedString", size + 1); ReadBytes(data, size); @@ -134,7 +126,7 @@ PUBLIC char* Stream::ReadHeaderedString() { return data; } -PUBLIC VIRTUAL Uint32 Stream::ReadCompressed(void* out) { +Uint32 Stream::ReadCompressed(void* out) { Uint32 compressed_size = ReadUInt32() - 4; Uint32 uncompressed_size = ReadUInt32BE(); @@ -146,7 +138,7 @@ PUBLIC VIRTUAL Uint32 Stream::ReadCompressed(void* out) { return uncompressed_size; } -PUBLIC VIRTUAL Uint32 Stream::ReadCompressed(void* out, size_t outSz) { +Uint32 Stream::ReadCompressed(void* out, size_t outSz) { Uint32 compressed_size = ReadUInt32() - 4; ReadUInt32BE(); // uncompressed_size @@ -159,60 +151,60 @@ PUBLIC VIRTUAL Uint32 Stream::ReadCompressed(void* out, size_t outSz) { return (Uint32)outSz; } -PUBLIC VIRTUAL size_t Stream::WriteBytes(void* data, size_t n) { +size_t Stream::WriteBytes(void* data, size_t n) { return 0; } -PUBLIC void Stream::WriteByte(Uint8 data) { +void Stream::WriteByte(Uint8 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteUInt16(Uint16 data) { +void Stream::WriteUInt16(Uint16 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteUInt16BE(Uint16 data) { +void Stream::WriteUInt16BE(Uint16 data) { WriteByte(data >> 8 & 0xFF); WriteByte(data & 0xFF); } -PUBLIC void Stream::WriteUInt32(Uint32 data) { +void Stream::WriteUInt32(Uint32 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteUInt32BE(Uint32 data) { +void Stream::WriteUInt32BE(Uint32 data) { WriteByte(data >> 24 & 0xFF); WriteByte(data >> 16 & 0xFF); WriteByte(data >> 8 & 0xFF); WriteByte(data & 0xFF); } -PUBLIC void Stream::WriteUInt64(Uint64 data) { +void Stream::WriteUInt64(Uint64 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteInt16(Sint16 data) { +void Stream::WriteInt16(Sint16 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteInt16BE(Sint16 data) { +void Stream::WriteInt16BE(Sint16 data) { WriteUInt16BE((Uint16)data); } -PUBLIC void Stream::WriteInt32(Sint32 data) { + void Stream::WriteInt32(Sint32 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteInt32BE(Sint32 data) { +void Stream::WriteInt32BE(Sint32 data) { WriteUInt32BE((Sint32)data); } -PUBLIC void Stream::WriteInt64(Sint64 data) { +void Stream::WriteInt64(Sint64 data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteFloat(float data) { +void Stream::WriteFloat(float data) { WriteBytes(&data, sizeof(data)); } -PUBLIC void Stream::WriteString(const char* string) { +void Stream::WriteString(const char* string) { size_t size = strlen(string) + 1; WriteBytes((void*)string, size); } -PUBLIC void Stream::WriteHeaderedString(const char* string) { +void Stream::WriteHeaderedString(const char* string) { size_t size = strlen(string) + 1; WriteByte((Uint8)size); WriteBytes((void*)string, size); } -PUBLIC void Stream::CopyTo(Stream* dest) { +void Stream::CopyTo(Stream* dest) { size_t length = Length() - Position(); void* memory = Memory::Malloc(length); @@ -224,5 +216,5 @@ PUBLIC void Stream::CopyTo(Stream* dest) { Memory::Free(memory); } -PUBLIC VIRTUAL Stream::~Stream() { +Stream::~Stream() { } diff --git a/source/Engine/Input/Controller.cpp b/source/Engine/Input/Controller.cpp index 54c0d755..5f3caffe 100644 --- a/source/Engine/Input/Controller.cpp +++ b/source/Engine/Input/Controller.cpp @@ -1,35 +1,12 @@ -#if INTERFACE -#include -#include -#include -#include - -class Controller { -public: - ControllerType Type; - bool Connected; - - bool* ButtonsPressed; - bool* ButtonsHeld; - float* AxisValues; - - ControllerRumble* Rumble; - - SDL_GameController* Device; - SDL_Joystick* JoystickDevice; - SDL_JoystickID JoystickID; -}; -#endif - #include #include -PUBLIC Controller::Controller(int index) { +Controller::Controller(int index) { Reset(); Open(index); } -PUBLIC Controller::~Controller() { +Controller::~Controller() { Close(); } @@ -75,7 +52,7 @@ static SDL_GameControllerAxis AxisEnums[] = { #undef CONST_AXIS -PRIVATE STATIC ControllerType Controller::DetermineType(void* gamecontroller) { +ControllerType Controller::DetermineType(void* gamecontroller) { switch (SDL_GameControllerGetType((SDL_GameController*)gamecontroller)) { case SDL_CONTROLLER_TYPE_XBOX360: return ControllerType::Xbox360; @@ -110,7 +87,7 @@ PRIVATE STATIC ControllerType Controller::DetermineType(void* gamecontroller) { } } -PUBLIC bool Controller::Open(int index) { +bool Controller::Open(int index) { Device = SDL_GameControllerOpen(index); if (!Device) return false; @@ -130,7 +107,7 @@ PUBLIC bool Controller::Open(int index) { return true; } -PUBLIC void Controller::Close() { +void Controller::Close() { if (Rumble) { Rumble->Stop(); delete Rumble; @@ -156,7 +133,7 @@ PUBLIC void Controller::Close() { Reset(); } -PUBLIC void Controller::Reset() { +void Controller::Reset() { Type = ControllerType::Unknown; Connected = false; Device = nullptr; @@ -165,38 +142,38 @@ PUBLIC void Controller::Reset() { JoystickID = -1; } -PUBLIC char* Controller::GetName() { +char* Controller::GetName() { return (char*)SDL_GameControllerName(Device); } // Sets the LEDs in some controllers -PUBLIC void Controller::SetPlayerIndex(int index) { +void Controller::SetPlayerIndex(int index) { SDL_GameControllerSetPlayerIndex(Device, index); } -PUBLIC bool Controller::GetButton(int button) { +bool Controller::GetButton(int button) { if (button >= (int)ControllerButton::Max) return false; return SDL_GameControllerGetButton(Device, ButtonEnums[button]); } -PUBLIC bool Controller::IsButtonHeld(int button) { +bool Controller::IsButtonHeld(int button) { if (button < 0 || button >= (int)ControllerButton::Max) return false; return ButtonsHeld[button]; } -PUBLIC bool Controller::IsButtonPressed(int button) { +bool Controller::IsButtonPressed(int button) { if (button < 0 || button >= (int)ControllerButton::Max) return false; return ButtonsPressed[button]; } -PUBLIC float Controller::GetAxis(int axis) { +float Controller::GetAxis(int axis) { if (axis < 0 || axis >= (int)ControllerAxis::Max) return 0.0f; return AxisValues[axis]; } -PUBLIC void Controller::Update() { +void Controller::Update() { if (Rumble) Rumble->Update(); @@ -212,30 +189,30 @@ PUBLIC void Controller::Update() { } } -PUBLIC bool Controller::IsXbox() { +bool Controller::IsXbox() { return Type == ControllerType::Xbox360 || Type == ControllerType::XboxOne || Type == ControllerType::XboxSeriesXS || Type == ControllerType::XboxElite; } -PUBLIC bool Controller::IsPlayStation() { +bool Controller::IsPlayStation() { return Type == ControllerType::PS3 || Type == ControllerType::PS4 || Type == ControllerType::PS5; } -PUBLIC bool Controller::IsJoyCon() { +bool Controller::IsJoyCon() { return Type == ControllerType::SwitchJoyConLeft || Type == ControllerType::SwitchJoyConRight; } -PUBLIC bool Controller::HasShareButton() { +bool Controller::HasShareButton() { return Type == ControllerType::XboxSeriesXS || Type == ControllerType::SwitchPro || Type == ControllerType::SwitchJoyConLeft; } -PUBLIC bool Controller::HasMicrophoneButton() { +bool Controller::HasMicrophoneButton() { return Type == ControllerType::PS5 || Type == ControllerType::AmazonLuna; } -PUBLIC bool Controller::HasPaddles() { +bool Controller::HasPaddles() { return Type == ControllerType::XboxElite; } diff --git a/source/Engine/Input/InputAction.cpp b/source/Engine/Input/InputAction.cpp index ceeb5bf8..d09ff11c 100644 --- a/source/Engine/Input/InputAction.cpp +++ b/source/Engine/Input/InputAction.cpp @@ -1,20 +1,9 @@ -#if INTERFACE -#include -#include - -class InputAction { -public: - unsigned ID; - string Name; -}; -#endif - #include -PUBLIC InputAction::InputAction(const char* name, unsigned id) { +InputAction::InputAction(const char* name, unsigned id) { Name = std::string(name); ID = id; } -PUBLIC InputAction::~InputAction() { +InputAction::~InputAction() { } diff --git a/source/Engine/Input/InputPlayer.cpp b/source/Engine/Input/InputPlayer.cpp index 9f5bbfb4..ee0f31a9 100644 --- a/source/Engine/Input/InputPlayer.cpp +++ b/source/Engine/Input/InputPlayer.cpp @@ -1,45 +1,12 @@ -#if INTERFACE -#include -#include -#include - -class InputPlayer { -public: - int ID; - - vector Binds; - vector DefaultBinds; - - PlayerInputStatus Status[InputDevice_MAX]; - PlayerInputStatus AllStatus; - - vector NumHeld; - vector NumPressed; - vector NumReleased; - - bool AnyHeld; - bool AnyPressed; - bool AnyReleased; - - vector ControllerState; - - bool IsUsingDevice[InputDevice_MAX]; - - int ControllerIndex = -1; - - const char* ConfigFilename = nullptr; -}; -#endif - #include #include #include -PUBLIC InputPlayer::InputPlayer(int id) { +InputPlayer::InputPlayer(int id) { ID = id; } -PUBLIC void InputPlayer::SetNumActions(size_t num) { +void InputPlayer::SetNumActions(size_t num) { size_t oldNum = Binds.size(); Binds.resize(num); @@ -66,12 +33,12 @@ PUBLIC void InputPlayer::SetNumActions(size_t num) { AllStatus.SetNumActions(num); } -PUBLIC void InputPlayer::ClearBinds() { +void InputPlayer::ClearBinds() { for (size_t i = 0; i < Binds.size(); i++) { Binds[i].Clear(); } } -PUBLIC void InputPlayer::ResetBinds() { +void InputPlayer::ResetBinds() { for (size_t i = 0; i < DefaultBinds.size(); i++) { Binds[i].Clear(); @@ -82,7 +49,7 @@ PUBLIC void InputPlayer::ResetBinds() { } } -PUBLIC void InputPlayer::Update() { +void InputPlayer::Update() { IsUsingDevice[InputDevice_Keyboard] = false; IsUsingDevice[InputDevice_Controller] = false; @@ -164,13 +131,13 @@ PUBLIC void InputPlayer::Update() { } } -PRIVATE size_t InputPlayer::PushBindToList(PlayerInputConfig& config, InputBind* def) { +size_t InputPlayer::PushBindToList(PlayerInputConfig& config, InputBind* def) { config.Binds.push_back(def); return config.Binds.size() - 1; } -PRIVATE bool InputPlayer::ReplaceBindInList(PlayerInputConfig& config, InputBind* def, unsigned index) { +bool InputPlayer::ReplaceBindInList(PlayerInputConfig& config, InputBind* def, unsigned index) { if (index >= 0 && index < config.Binds.size()) { if (config.Binds[index]) delete config.Binds[index]; @@ -181,7 +148,7 @@ PRIVATE bool InputPlayer::ReplaceBindInList(PlayerInputConfig& config, InputBind return false; } -PRIVATE bool InputPlayer::RemoveBindFromList(PlayerInputConfig& config, unsigned index) { +bool InputPlayer::RemoveBindFromList(PlayerInputConfig& config, unsigned index) { if (index >= 0 && index < config.Binds.size()) { config.Binds.erase(config.Binds.begin() + index); return true; @@ -190,7 +157,7 @@ PRIVATE bool InputPlayer::RemoveBindFromList(PlayerInputConfig& config, unsigned return false; } -PUBLIC int InputPlayer::AddBind(unsigned num, InputBind* bind) { +int InputPlayer::AddBind(unsigned num, InputBind* bind) { if (num < Binds.size()) { return (int)PushBindToList(Binds[num], bind); } @@ -198,46 +165,46 @@ PUBLIC int InputPlayer::AddBind(unsigned num, InputBind* bind) { return -1; } -PUBLIC bool InputPlayer::ReplaceBind(unsigned num, InputBind* bind, unsigned index) { +bool InputPlayer::ReplaceBind(unsigned num, InputBind* bind, unsigned index) { if (num < Binds.size()) { return ReplaceBindInList(Binds[num], bind, index); } return false; } -PUBLIC bool InputPlayer::RemoveBind(unsigned num, unsigned index) { +bool InputPlayer::RemoveBind(unsigned num, unsigned index) { if (num < Binds.size()) { return RemoveBindFromList(Binds[num], index); } return false; } -PRIVATE InputBind* InputPlayer::GetBindAtIndex(PlayerInputConfig& config, unsigned index) { +InputBind* InputPlayer::GetBindAtIndex(PlayerInputConfig& config, unsigned index) { if (config.Binds.size() > 0 && index < config.Binds.size()) return config.Binds[index]; return nullptr; } -PRIVATE size_t InputPlayer::GetBindCount(PlayerInputConfig& config) { +size_t InputPlayer::GetBindCount(PlayerInputConfig& config) { return config.Binds.size(); } -PUBLIC InputBind* InputPlayer::GetBind(unsigned num, unsigned index) { +InputBind* InputPlayer::GetBind(unsigned num, unsigned index) { if (num < Binds.size()) return GetBindAtIndex(Binds[num], index); return nullptr; } -PUBLIC size_t InputPlayer::GetBindCount(unsigned num) { +size_t InputPlayer::GetBindCount(unsigned num) { if (num < Binds.size()) return GetBindCount(Binds[num]); return 0; } -PUBLIC int InputPlayer::AddDefaultBind(unsigned num, InputBind* bind) { +int InputPlayer::AddDefaultBind(unsigned num, InputBind* bind) { if (num < DefaultBinds.size()) { return (int)PushBindToList(DefaultBinds[num], bind); } @@ -245,7 +212,7 @@ PUBLIC int InputPlayer::AddDefaultBind(unsigned num, InputBind* bind) { return -1; } -PRIVATE void InputPlayer::CopyDefaultBinds(InputPlayer& src, bool filter, int filterType) { +void InputPlayer::CopyDefaultBinds(InputPlayer& src, bool filter, int filterType) { for (size_t i = 0; i < src.Binds.size(); i++) { PlayerInputConfig& config = src.Binds[i]; for (size_t j = 0; j < config.Binds.size(); j++) { @@ -256,43 +223,43 @@ PRIVATE void InputPlayer::CopyDefaultBinds(InputPlayer& src, bool filter, int fi } } -PUBLIC void InputPlayer::CopyDefaultBinds(InputPlayer& src) { +void InputPlayer::CopyDefaultBinds(InputPlayer& src) { CopyDefaultBinds(src, false, 0); } -PUBLIC void InputPlayer::CopyDefaultBinds(InputPlayer& src, int filterType) { +void InputPlayer::CopyDefaultBinds(InputPlayer& src, int filterType) { CopyDefaultBinds(src, true, filterType); } -PUBLIC bool InputPlayer::ReplaceDefaultBind(unsigned num, InputBind* bind, unsigned index) { +bool InputPlayer::ReplaceDefaultBind(unsigned num, InputBind* bind, unsigned index) { if (num < DefaultBinds.size()) { return ReplaceBindInList(DefaultBinds[num], bind, index); } return false; } -PUBLIC bool InputPlayer::RemoveDefaultBind(unsigned num, unsigned index) { +bool InputPlayer::RemoveDefaultBind(unsigned num, unsigned index) { if (num < DefaultBinds.size()) { return RemoveBindFromList(DefaultBinds[num], index); } return false; } -PUBLIC InputBind* InputPlayer::GetDefaultBind(unsigned num, unsigned index) { +InputBind* InputPlayer::GetDefaultBind(unsigned num, unsigned index) { if (num < DefaultBinds.size()) return GetBindAtIndex(DefaultBinds[num], index); return nullptr; } -PUBLIC size_t InputPlayer::GetDefaultBindCount(unsigned num) { +size_t InputPlayer::GetDefaultBindCount(unsigned num) { if (num < DefaultBinds.size()) return GetBindCount(DefaultBinds[num]); return 0; } -PUBLIC bool InputPlayer::IsBindIndexValid(unsigned num, unsigned index) { +bool InputPlayer::IsBindIndexValid(unsigned num, unsigned index) { if (num < Binds.size()) { return index < Binds[num].Binds.size(); } @@ -300,17 +267,17 @@ PUBLIC bool InputPlayer::IsBindIndexValid(unsigned num, unsigned index) { return false; } -PUBLIC void InputPlayer::ClearBinds(unsigned num) { +void InputPlayer::ClearBinds(unsigned num) { if (num < Binds.size()) Binds[num].Binds.clear(); } -PUBLIC void InputPlayer::ClearDefaultBinds(unsigned num) { +void InputPlayer::ClearDefaultBinds(unsigned num) { if (num < DefaultBinds.size()) DefaultBinds[num].Binds.clear(); } -PRIVATE void InputPlayer::ResetBindList(PlayerInputConfig &dest, PlayerInputConfig &src) { +void InputPlayer::ResetBindList(PlayerInputConfig &dest, PlayerInputConfig &src) { dest.Binds.clear(); for (size_t i = 0; i < src.Binds.size(); i++) { @@ -318,13 +285,13 @@ PRIVATE void InputPlayer::ResetBindList(PlayerInputConfig &dest, PlayerInputConf } } -PUBLIC void InputPlayer::ResetBind(unsigned num) { +void InputPlayer::ResetBind(unsigned num) { if (num < Binds.size() && num < DefaultBinds.size()) { ResetBindList(Binds[num], DefaultBinds[num]); } } -PRIVATE bool InputPlayer::CheckInputBindState(InputBind* bind, bool held) { +bool InputPlayer::CheckInputBindState(InputBind* bind, bool held) { if (bind->IsDefined() && bind->Type == INPUT_BIND_KEYBOARD) { KeyboardBind* keyBind = static_cast(bind); @@ -342,7 +309,7 @@ PRIVATE bool InputPlayer::CheckInputBindState(InputBind* bind, bool held) { return false; } -PRIVATE bool InputPlayer::CheckIfInputHeld(unsigned actionID, unsigned device) { +bool InputPlayer::CheckIfInputHeld(unsigned actionID, unsigned device) { if (actionID >= InputManager::Actions.size()) return false; @@ -362,7 +329,7 @@ PRIVATE bool InputPlayer::CheckIfInputHeld(unsigned actionID, unsigned device) { return false; } -PRIVATE bool InputPlayer::CheckIfInputPressed(unsigned actionID, unsigned device) { +bool InputPlayer::CheckIfInputPressed(unsigned actionID, unsigned device) { if (actionID >= InputManager::Actions.size()) return false; @@ -383,74 +350,74 @@ PRIVATE bool InputPlayer::CheckIfInputPressed(unsigned actionID, unsigned device return false; } -PUBLIC bool InputPlayer::IsInputHeld(unsigned actionID, unsigned device) { +bool InputPlayer::IsInputHeld(unsigned actionID, unsigned device) { if (actionID >= InputManager::Actions.size() || device >= InputDevice_Controller) return false; Uint8 state = Status[device].State[actionID]; return state == INPUT_STATE_PRESSED || state == INPUT_STATE_HELD; } -PUBLIC bool InputPlayer::IsInputPressed(unsigned actionID, unsigned device) { +bool InputPlayer::IsInputPressed(unsigned actionID, unsigned device) { if (actionID >= InputManager::Actions.size() || device >= InputDevice_Controller) return false; return Status[device].State[actionID] == INPUT_STATE_PRESSED; } -PUBLIC bool InputPlayer::IsInputReleased(unsigned actionID, unsigned device) { +bool InputPlayer::IsInputReleased(unsigned actionID, unsigned device) { if (actionID >= InputManager::Actions.size() || device >= InputDevice_Controller) return false; return Status[device].State[actionID] == INPUT_STATE_RELEASED; } -PUBLIC bool InputPlayer::IsAnyInputHeld(unsigned device) { +bool InputPlayer::IsAnyInputHeld(unsigned device) { if (device >= InputDevice_Controller) return false; return Status[device].NumHeld != 0; } -PUBLIC bool InputPlayer::IsAnyInputPressed(unsigned device) { +bool InputPlayer::IsAnyInputPressed(unsigned device) { if (device >= InputDevice_Controller) return false; return Status[device].NumPressed != 0; } -PUBLIC bool InputPlayer::IsAnyInputReleased(unsigned device) { +bool InputPlayer::IsAnyInputReleased(unsigned device) { if (device >= InputDevice_Controller) return false; return Status[device].NumReleased != 0; } -PUBLIC bool InputPlayer::IsInputHeld(unsigned actionID) { +bool InputPlayer::IsInputHeld(unsigned actionID) { if (actionID >= InputManager::Actions.size()) return false; Uint8 state = AllStatus.State[actionID]; return state == INPUT_STATE_PRESSED || state == INPUT_STATE_HELD; } -PUBLIC bool InputPlayer::IsInputPressed(unsigned actionID) { +bool InputPlayer::IsInputPressed(unsigned actionID) { if (actionID >= InputManager::Actions.size()) return false; return AllStatus.State[actionID] == INPUT_STATE_PRESSED; } -PUBLIC bool InputPlayer::IsInputReleased(unsigned actionID) { +bool InputPlayer::IsInputReleased(unsigned actionID) { if (actionID >= InputManager::Actions.size()) return false; return AllStatus.State[actionID] == INPUT_STATE_RELEASED; } -PUBLIC bool InputPlayer::IsAnyInputHeld() { +bool InputPlayer::IsAnyInputHeld() { return AnyHeld; } -PUBLIC bool InputPlayer::IsAnyInputPressed() { +bool InputPlayer::IsAnyInputPressed() { return AnyPressed; } -PUBLIC bool InputPlayer::IsAnyInputReleased() { +bool InputPlayer::IsAnyInputReleased() { return AnyReleased; } -PUBLIC float InputPlayer::GetAnalogActionInput(unsigned actionID) { +float InputPlayer::GetAnalogActionInput(unsigned actionID) { if (actionID >= InputManager::Actions.size()) return false; @@ -464,11 +431,11 @@ PUBLIC float InputPlayer::GetAnalogActionInput(unsigned actionID) { return result; } -PRIVATE bool InputPlayer::IsControllerBindHeld(unsigned num) { +bool InputPlayer::IsControllerBindHeld(unsigned num) { Uint8 state = ControllerState[num]; return state == INPUT_STATE_PRESSED || state == INPUT_STATE_HELD; } -PRIVATE bool InputPlayer::IsControllerBindPressed(unsigned num) { +bool InputPlayer::IsControllerBindPressed(unsigned num) { return ControllerState[num] == INPUT_STATE_PRESSED; } @@ -522,7 +489,7 @@ static bool CheckControllerBindHeld(PlayerInputConfig& config, Controller* contr return false; } -PRIVATE void InputPlayer::UpdateControllerBind(unsigned num) { +void InputPlayer::UpdateControllerBind(unsigned num) { Controller* controller = InputManager::GetController(ControllerIndex); if (CheckControllerBindHeld(Binds[num], controller)) { @@ -536,7 +503,7 @@ PRIVATE void InputPlayer::UpdateControllerBind(unsigned num) { else if (ControllerState[num] != INPUT_STATE_UNPUSHED) ControllerState[num] = INPUT_STATE_UNPUSHED; } -PRIVATE bool InputPlayer::GetAnalogControllerBind(unsigned num, float& result) { +bool InputPlayer::GetAnalogControllerBind(unsigned num, float& result) { if (ControllerIndex == -1) return false; diff --git a/source/Engine/InputManager.cpp b/source/Engine/InputManager.cpp index 48644b70..76dd4129 100644 --- a/source/Engine/InputManager.cpp +++ b/source/Engine/InputManager.cpp @@ -1,40 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class InputManager { -public: - static float MouseX; - static float MouseY; - static int MouseDown; - static int MousePressed; - static int MouseReleased; - - static Uint8 KeyboardState[0x120]; - static Uint8 KeyboardStateLast[0x120]; - static Uint16 KeymodState; - static SDL_Scancode KeyToSDLScancode[NUM_KEYBOARD_KEYS]; - - static int NumControllers; - static vector Controllers; - - static SDL_TouchID TouchDevice; - static void* TouchStates; - - static vector Players; - static vector Actions; -}; -#endif - #include #include @@ -69,7 +32,7 @@ struct TouchState { bool Released; }; -PUBLIC STATIC void InputManager::Init() { +void InputManager::Init() { memset(KeyboardState, 0, NUM_KEYBOARD_KEYS); memset(KeyboardStateLast, 0, NUM_KEYBOARD_KEYS); @@ -95,7 +58,7 @@ namespace NameMap { BijectiveMap* Axes; } -PRIVATE STATIC void InputManager::InitStringLookup() { +void InputManager::InitStringLookup() { NameMap::Keys = new BijectiveMap(); NameMap::Buttons = new BijectiveMap(); NameMap::Axes = new BijectiveMap(); @@ -268,17 +231,17 @@ PRIVATE STATIC void InputManager::InitStringLookup() { KeymodStrToFlags.insert({ "capslock", KB_MODIFIER_CAPS }); } -PUBLIC STATIC char* InputManager::GetKeyName(int key) { +char* InputManager::GetKeyName(int key) { if (!NameMap::Keys->Exists(key)) return nullptr; return (char*)NameMap::Keys->Get(key); } -PUBLIC STATIC char* InputManager::GetButtonName(int button) { +char* InputManager::GetButtonName(int button) { if (!NameMap::Buttons->Exists(button)) return nullptr; return (char*)NameMap::Buttons->Get(button); } -PUBLIC STATIC char* InputManager::GetAxisName(int axis) { +char* InputManager::GetAxisName(int axis) { if (!NameMap::Axes->Exists(axis)) return nullptr; return (char*)NameMap::Axes->Get(axis); @@ -296,19 +259,19 @@ PUBLIC STATIC char* InputManager::GetAxisName(int axis) { return found; \ } -PUBLIC STATIC int InputManager::ParseKeyName(const char* key) { +int InputManager::ParseKeyName(const char* key) { FIND_IN_BIJECTIVE(NameMap::Keys, key); } -PUBLIC STATIC int InputManager::ParseButtonName(const char* button) { +int InputManager::ParseButtonName(const char* button) { FIND_IN_BIJECTIVE(NameMap::Buttons, button); } -PUBLIC STATIC int InputManager::ParseAxisName(const char* axis) { +int InputManager::ParseAxisName(const char* axis) { FIND_IN_BIJECTIVE(NameMap::Axes, axis); } #undef FIND_IN_BIJECTIVE -PUBLIC STATIC Controller* InputManager::OpenController(int index) { +Controller* InputManager::OpenController(int index) { Controller* controller = new Controller(index); if (controller->Device == nullptr) { Log::Print(Log::LOG_ERROR, "Opening controller %d failed: %s", index, SDL_GetError()); @@ -320,7 +283,7 @@ PUBLIC STATIC Controller* InputManager::OpenController(int index) { return controller; } -PUBLIC STATIC void InputManager::InitControllers() { +void InputManager::InitControllers() { int numControllers = 0; int numJoysticks = SDL_NumJoysticks(); for (int i = 0; i < numJoysticks; i++) { @@ -345,7 +308,7 @@ PUBLIC STATIC void InputManager::InitControllers() { } } -PRIVATE STATIC int InputManager::FindController(int joystickID) { +int InputManager::FindController(int joystickID) { for (int i = 0; i < InputManager::NumControllers; i++) { Controller* controller = InputManager::Controllers[i]; if (controller->Connected && controller->JoystickID == joystickID) @@ -355,7 +318,7 @@ PRIVATE STATIC int InputManager::FindController(int joystickID) { return -1; } -PUBLIC STATIC bool InputManager::AddController(int index) { +bool InputManager::AddController(int index) { Controller* controller; for (int i = 0; i < InputManager::NumControllers; i++) { controller = InputManager::Controllers[i]; @@ -373,7 +336,7 @@ PUBLIC STATIC bool InputManager::AddController(int index) { return true; } -PUBLIC STATIC void InputManager::RemoveController(int joystickID) { +void InputManager::RemoveController(int joystickID) { int controller_id = InputManager::FindController(joystickID); if (controller_id == -1) return; @@ -381,7 +344,7 @@ PUBLIC STATIC void InputManager::RemoveController(int joystickID) { InputManager::Controllers[controller_id]->Close(); } -PUBLIC STATIC void InputManager::Poll() { +void InputManager::Poll() { if (Application::Platform == Platforms::iOS || Application::Platform == Platforms::Android || Application::Platform == Platforms::Switch) { @@ -492,134 +455,134 @@ PUBLIC STATIC void InputManager::Poll() { InputManager::Players[i].Update(); } -PUBLIC STATIC Uint16 InputManager::CheckKeyModifiers(Uint16 modifiers) { +Uint16 InputManager::CheckKeyModifiers(Uint16 modifiers) { return (KeymodState & modifiers) == modifiers; } -PUBLIC STATIC bool InputManager::IsKeyDown(int key) { +bool InputManager::IsKeyDown(int key) { int scancode = (int)KeyToSDLScancode[key]; return KeyboardState[scancode]; } -PUBLIC STATIC bool InputManager::IsKeyPressed(int key) { +bool InputManager::IsKeyPressed(int key) { int scancode = (int)KeyToSDLScancode[key]; return KeyboardState[scancode] && !KeyboardStateLast[scancode]; } -PUBLIC STATIC bool InputManager::IsKeyReleased(int key) { +bool InputManager::IsKeyReleased(int key) { int scancode = (int)KeyToSDLScancode[key]; return !KeyboardState[scancode] && KeyboardStateLast[scancode]; } -PUBLIC STATIC Controller* InputManager::GetController(int index) { +Controller* InputManager::GetController(int index) { if (index >= 0 && index < InputManager::NumControllers) { return InputManager::Controllers[index]; } return nullptr; } -PUBLIC STATIC bool InputManager::ControllerIsConnected(int index) { +bool InputManager::ControllerIsConnected(int index) { Controller* controller = GetController(index); if (controller) return controller->Connected; return false; } -PUBLIC STATIC bool InputManager::ControllerIsXbox(int index) { +bool InputManager::ControllerIsXbox(int index) { Controller* controller = GetController(index); if (controller) return controller->IsXbox(); return false; } -PUBLIC STATIC bool InputManager::ControllerIsPlayStation(int index) { +bool InputManager::ControllerIsPlayStation(int index) { Controller* controller = GetController(index); if (controller) return controller->IsPlayStation(); return false; } -PUBLIC STATIC bool InputManager::ControllerIsJoyCon(int index) { +bool InputManager::ControllerIsJoyCon(int index) { Controller* controller = GetController(index); if (controller) return controller->IsJoyCon(); return false; } -PUBLIC STATIC bool InputManager::ControllerHasShareButton(int index) { +bool InputManager::ControllerHasShareButton(int index) { Controller* controller = GetController(index); if (controller) return controller->HasShareButton(); return false; } -PUBLIC STATIC bool InputManager::ControllerHasMicrophoneButton(int index) { +bool InputManager::ControllerHasMicrophoneButton(int index) { Controller* controller = GetController(index); if (controller) return controller->HasMicrophoneButton(); return false; } -PUBLIC STATIC bool InputManager::ControllerHasPaddles(int index) { +bool InputManager::ControllerHasPaddles(int index) { Controller* controller = GetController(index); if (controller) return controller->HasPaddles(); return false; } -PUBLIC STATIC bool InputManager::ControllerIsButtonHeld(int index, int button) { +bool InputManager::ControllerIsButtonHeld(int index, int button) { Controller* controller = GetController(index); if (controller) return controller->IsButtonHeld(button); return false; } -PUBLIC STATIC bool InputManager::ControllerIsButtonPressed(int index, int button) { +bool InputManager::ControllerIsButtonPressed(int index, int button) { Controller* controller = GetController(index); if (controller) return controller->IsButtonPressed(button); return false; } -PUBLIC STATIC float InputManager::ControllerGetAxis(int index, int axis) { +float InputManager::ControllerGetAxis(int index, int axis) { Controller* controller = GetController(index); if (controller) return controller->GetAxis(axis); return 0.0f; } -PUBLIC STATIC int InputManager::ControllerGetType(int index) { +int InputManager::ControllerGetType(int index) { Controller* controller = GetController(index); if (controller) return (int)controller->Type; return (int)ControllerType::Unknown; } -PUBLIC STATIC char* InputManager::ControllerGetName(int index) { +char* InputManager::ControllerGetName(int index) { Controller* controller = GetController(index); if (controller) return controller->GetName(); return nullptr; } -PUBLIC STATIC void InputManager::ControllerSetPlayerIndex(int index, int player_index) { +void InputManager::ControllerSetPlayerIndex(int index, int player_index) { Controller* controller = GetController(index); if (controller) controller->SetPlayerIndex(player_index); } -PUBLIC STATIC bool InputManager::ControllerHasRumble(int index) { +bool InputManager::ControllerHasRumble(int index) { Controller* controller = GetController(index); if (controller) return controller->Rumble != nullptr; return false; } -PUBLIC STATIC bool InputManager::ControllerIsRumbleActive(int index) { +bool InputManager::ControllerIsRumbleActive(int index) { Controller* controller = GetController(index); if (controller && controller->Rumble) return controller->Rumble->Active; return false; } -PUBLIC STATIC bool InputManager::ControllerRumble(int index, float large_frequency, float small_frequency, int duration) { +bool InputManager::ControllerRumble(int index, float large_frequency, float small_frequency, int duration) { Controller* controller = GetController(index); if (controller && controller->Rumble) return controller->Rumble->Enable(large_frequency, small_frequency, (Uint32)duration); return false; } -PUBLIC STATIC bool InputManager::ControllerRumble(int index, float strength, int duration) { +bool InputManager::ControllerRumble(int index, float strength, int duration) { return ControllerRumble(index, strength, strength, duration); } -PUBLIC STATIC void InputManager::ControllerStopRumble(int index) { +void InputManager::ControllerStopRumble(int index) { Controller* controller = GetController(index); if (controller && controller->Rumble) controller->Rumble->Stop(); } -PUBLIC STATIC void InputManager::ControllerStopRumble() { +void InputManager::ControllerStopRumble() { for (int i = 0; i < InputManager::NumControllers; i++) { Controller* controller = InputManager::Controllers[i]; if (!controller || !controller->Rumble) @@ -629,62 +592,62 @@ PUBLIC STATIC void InputManager::ControllerStopRumble() { controller->Rumble->Stop(); } } -PUBLIC STATIC bool InputManager::ControllerIsRumblePaused(int index) { +bool InputManager::ControllerIsRumblePaused(int index) { Controller* controller = GetController(index); if (controller && controller->Rumble) return controller->Rumble->Paused; return false; } -PUBLIC STATIC void InputManager::ControllerSetRumblePaused(int index, bool paused) { +void InputManager::ControllerSetRumblePaused(int index, bool paused) { Controller* controller = GetController(index); if (controller && controller->Rumble) controller->Rumble->SetPaused(paused); } -PUBLIC STATIC bool InputManager::ControllerSetLargeMotorFrequency(int index, float frequency) { +bool InputManager::ControllerSetLargeMotorFrequency(int index, float frequency) { Controller* controller = GetController(index); if (controller && controller->Rumble) return controller->Rumble->SetLargeMotorFrequency(frequency); return false; } -PUBLIC STATIC bool InputManager::ControllerSetSmallMotorFrequency(int index, float frequency) { +bool InputManager::ControllerSetSmallMotorFrequency(int index, float frequency) { Controller* controller = GetController(index); if (controller && controller->Rumble) return controller->Rumble->SetSmallMotorFrequency(frequency); return false; } -PUBLIC STATIC float InputManager::TouchGetX(int touch_index) { +float InputManager::TouchGetX(int touch_index) { if (touch_index < 0 || touch_index >= NUM_TOUCH_STATES) return 0.0f; TouchState* states = (TouchState*)TouchStates; return states[touch_index].X; } -PUBLIC STATIC float InputManager::TouchGetY(int touch_index) { +float InputManager::TouchGetY(int touch_index) { if (touch_index < 0 || touch_index >= NUM_TOUCH_STATES) return 0.0f; TouchState* states = (TouchState*)TouchStates; return states[touch_index].Y; } -PUBLIC STATIC bool InputManager::TouchIsDown(int touch_index) { +bool InputManager::TouchIsDown(int touch_index) { if (touch_index < 0 || touch_index >= NUM_TOUCH_STATES) return false; TouchState* states = (TouchState*)TouchStates; return states[touch_index].Down; } -PUBLIC STATIC bool InputManager::TouchIsPressed(int touch_index) { +bool InputManager::TouchIsPressed(int touch_index) { if (touch_index < 0 || touch_index >= NUM_TOUCH_STATES) return false; TouchState* states = (TouchState*)TouchStates; return states[touch_index].Pressed; } -PUBLIC STATIC bool InputManager::TouchIsReleased(int touch_index) { +bool InputManager::TouchIsReleased(int touch_index) { if (touch_index < 0 || touch_index >= NUM_TOUCH_STATES) return false; TouchState* states = (TouchState*)TouchStates; return states[touch_index].Released; } -PUBLIC STATIC int InputManager::AddPlayer() { +int InputManager::AddPlayer() { int id = (int)Players.size(); InputPlayer player(id); @@ -695,10 +658,10 @@ PUBLIC STATIC int InputManager::AddPlayer() { return id; } -PUBLIC STATIC int InputManager::GetPlayerCount() { +int InputManager::GetPlayerCount() { return (int)Players.size(); } -PUBLIC STATIC void InputManager::SetPlayerControllerIndex(unsigned playerID, int index) { +void InputManager::SetPlayerControllerIndex(unsigned playerID, int index) { if (playerID >= Players.size()) return; @@ -707,13 +670,13 @@ PUBLIC STATIC void InputManager::SetPlayerControllerIndex(unsigned playerID, in Players[playerID].ControllerIndex = index; } -PUBLIC STATIC int InputManager::GetPlayerControllerIndex(unsigned playerID) { +int InputManager::GetPlayerControllerIndex(unsigned playerID) { if (playerID >= Players.size()) return -1; return Players[playerID].ControllerIndex; } -PUBLIC STATIC bool InputManager::IsActionHeld(unsigned playerID, unsigned actionID) { +bool InputManager::IsActionHeld(unsigned playerID, unsigned actionID) { if (playerID >= Players.size()) return false; @@ -721,7 +684,7 @@ PUBLIC STATIC bool InputManager::IsActionHeld(unsigned playerID, unsigned actio return player.IsInputHeld(actionID); } -PUBLIC STATIC bool InputManager::IsActionPressed(unsigned playerID, unsigned actionID) { +bool InputManager::IsActionPressed(unsigned playerID, unsigned actionID) { if (playerID >= Players.size()) return false; @@ -729,7 +692,7 @@ PUBLIC STATIC bool InputManager::IsActionPressed(unsigned playerID, unsigned ac return player.IsInputPressed(actionID); } -PUBLIC STATIC bool InputManager::IsActionReleased(unsigned playerID, unsigned actionID) { +bool InputManager::IsActionReleased(unsigned playerID, unsigned actionID) { if (playerID >= Players.size()) return false; @@ -737,7 +700,7 @@ PUBLIC STATIC bool InputManager::IsActionReleased(unsigned playerID, unsigned a return player.IsInputReleased(actionID); } -PUBLIC STATIC bool InputManager::IsAnyActionHeld(unsigned playerID) { +bool InputManager::IsAnyActionHeld(unsigned playerID) { if (playerID >= Players.size()) return false; @@ -745,7 +708,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionHeld(unsigned playerID) { return player.IsAnyInputHeld(); } -PUBLIC STATIC bool InputManager::IsAnyActionPressed(unsigned playerID) { +bool InputManager::IsAnyActionPressed(unsigned playerID) { if (playerID >= Players.size()) return false; @@ -753,7 +716,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionPressed(unsigned playerID) { return player.IsAnyInputPressed(); } -PUBLIC STATIC bool InputManager::IsAnyActionReleased(unsigned playerID) { +bool InputManager::IsAnyActionReleased(unsigned playerID) { if (playerID >= Players.size()) return false; @@ -761,7 +724,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionReleased(unsigned playerID) { return player.IsAnyInputReleased(); } -PUBLIC STATIC bool InputManager::IsActionHeld(unsigned playerID, unsigned actionID, unsigned device) { +bool InputManager::IsActionHeld(unsigned playerID, unsigned actionID, unsigned device) { if (playerID >= Players.size()) return false; @@ -769,7 +732,7 @@ PUBLIC STATIC bool InputManager::IsActionHeld(unsigned playerID, unsigned actio return player.IsInputHeld(actionID, device); } -PUBLIC STATIC bool InputManager::IsActionPressed(unsigned playerID, unsigned actionID, unsigned device) { +bool InputManager::IsActionPressed(unsigned playerID, unsigned actionID, unsigned device) { if (playerID >= Players.size()) return false; @@ -777,7 +740,7 @@ PUBLIC STATIC bool InputManager::IsActionPressed(unsigned playerID, unsigned ac return player.IsInputPressed(actionID, device); } -PUBLIC STATIC bool InputManager::IsActionReleased(unsigned playerID, unsigned actionID, unsigned device) { +bool InputManager::IsActionReleased(unsigned playerID, unsigned actionID, unsigned device) { if (playerID >= Players.size()) return false; @@ -785,7 +748,7 @@ PUBLIC STATIC bool InputManager::IsActionReleased(unsigned playerID, unsigned a return player.IsInputReleased(actionID, device); } -PUBLIC STATIC bool InputManager::IsAnyActionHeld(unsigned playerID, unsigned device) { +bool InputManager::IsAnyActionHeld(unsigned playerID, unsigned device) { if (playerID >= Players.size()) return false; @@ -793,7 +756,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionHeld(unsigned playerID, unsigned de return player.IsAnyInputHeld(device); } -PUBLIC STATIC bool InputManager::IsAnyActionPressed(unsigned playerID, unsigned device) { +bool InputManager::IsAnyActionPressed(unsigned playerID, unsigned device) { if (playerID >= Players.size()) return false; @@ -801,7 +764,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionPressed(unsigned playerID, unsigned return player.IsAnyInputPressed(device); } -PUBLIC STATIC bool InputManager::IsAnyActionReleased(unsigned playerID, unsigned device) { +bool InputManager::IsAnyActionReleased(unsigned playerID, unsigned device) { if (playerID >= Players.size()) return false; @@ -809,7 +772,7 @@ PUBLIC STATIC bool InputManager::IsAnyActionReleased(unsigned playerID, unsigne return player.IsAnyInputReleased(device); } -PUBLIC STATIC bool InputManager::IsPlayerUsingDevice(unsigned playerID, unsigned device) { +bool InputManager::IsPlayerUsingDevice(unsigned playerID, unsigned device) { if (playerID >= Players.size() || device >= InputDevice_MAX) return false; @@ -817,7 +780,7 @@ PUBLIC STATIC bool InputManager::IsPlayerUsingDevice(unsigned playerID, unsigne return player.IsUsingDevice[device]; } -PUBLIC STATIC float InputManager::GetAnalogActionInput(unsigned playerID, unsigned actionID) { +float InputManager::GetAnalogActionInput(unsigned playerID, unsigned actionID) { if (playerID >= Players.size()) return 0.0f; @@ -826,7 +789,7 @@ PUBLIC STATIC float InputManager::GetAnalogActionInput(unsigned playerID, unsign return player.GetAnalogActionInput(actionID); } -PUBLIC STATIC InputBind* InputManager::GetPlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault) { +InputBind* InputManager::GetPlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault) { if (playerID >= Players.size()) return nullptr; @@ -837,7 +800,7 @@ PUBLIC STATIC InputBind* InputManager::GetPlayerInputBind(unsigned playerID, uns else return player.GetBind(actionID, index); } -PUBLIC STATIC bool InputManager::SetPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, unsigned index, bool isDefault) { +bool InputManager::SetPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, unsigned index, bool isDefault) { if (playerID >= Players.size()) return false; @@ -848,7 +811,7 @@ PUBLIC STATIC bool InputManager::SetPlayerInputBind(unsigned playerID, unsigned else return player.ReplaceBind(actionID, bind, index); } -PUBLIC STATIC int InputManager::AddPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, bool isDefault) { +int InputManager::AddPlayerInputBind(unsigned playerID, unsigned actionID, InputBind* bind, bool isDefault) { if (playerID >= Players.size()) return -1; @@ -859,7 +822,7 @@ PUBLIC STATIC int InputManager::AddPlayerInputBind(unsigned playerID, unsigned else return player.AddBind(actionID, bind); } -PUBLIC STATIC bool InputManager::RemovePlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault) { +bool InputManager::RemovePlayerInputBind(unsigned playerID, unsigned actionID, unsigned index, bool isDefault) { if (playerID >= Players.size()) return false; @@ -870,7 +833,7 @@ PUBLIC STATIC bool InputManager::RemovePlayerInputBind(unsigned playerID, unsig else return player.RemoveBind(actionID, index); } -PUBLIC STATIC int InputManager::GetPlayerInputBindCount(unsigned playerID, unsigned actionID, bool isDefault) { +int InputManager::GetPlayerInputBindCount(unsigned playerID, unsigned actionID, bool isDefault) { if (playerID >= Players.size()) return 0; @@ -882,7 +845,7 @@ PUBLIC STATIC int InputManager::GetPlayerInputBindCount(unsigned playerID, unsig return player.GetBindCount(actionID); } -PUBLIC STATIC void InputManager::ClearPlayerBinds(unsigned playerID, unsigned actionID, bool isDefault) { +void InputManager::ClearPlayerBinds(unsigned playerID, unsigned actionID, bool isDefault) { if (playerID >= Players.size()) return; @@ -894,7 +857,7 @@ PUBLIC STATIC void InputManager::ClearPlayerBinds(unsigned playerID, unsigned a player.ClearBinds(actionID); } -PUBLIC STATIC bool InputManager::IsBindIndexValid(unsigned playerID, unsigned actionID, unsigned index) { +bool InputManager::IsBindIndexValid(unsigned playerID, unsigned actionID, unsigned index) { if (playerID >= Players.size()) return false; @@ -903,7 +866,7 @@ PUBLIC STATIC bool InputManager::IsBindIndexValid(unsigned playerID, unsigned a return player.IsBindIndexValid(actionID, index); } -PUBLIC STATIC void InputManager::ResetPlayerBinds(unsigned playerID) { +void InputManager::ResetPlayerBinds(unsigned playerID) { if (playerID >= Players.size()) return; @@ -912,11 +875,11 @@ PUBLIC STATIC void InputManager::ResetPlayerBinds(unsigned playerID) { player.ResetBinds(); } -PUBLIC STATIC void InputManager::ClearPlayers() { +void InputManager::ClearPlayers() { Players.clear(); } -PUBLIC STATIC int InputManager::RegisterAction(const char* name) { +int InputManager::RegisterAction(const char* name) { int id = GetActionID(name); if (id != -1) return id; @@ -932,7 +895,7 @@ PUBLIC STATIC int InputManager::RegisterAction(const char* name) { return id; } -PUBLIC STATIC int InputManager::GetActionID(const char* name) { +int InputManager::GetActionID(const char* name) { if (name != nullptr && name[0] != '\0') { for (size_t i = 0; i < Actions.size(); i++) { if (strcmp(Actions[i].Name.c_str(), name) == 0) @@ -942,14 +905,14 @@ PUBLIC STATIC int InputManager::GetActionID(const char* name) { return -1; } -PUBLIC STATIC void InputManager::ClearInputs() { +void InputManager::ClearInputs() { Actions.clear(); for (size_t i = 0; i < Players.size(); i++) Players[i].SetNumActions(0); } -PUBLIC STATIC void InputManager::InitPlayerControls() { +void InputManager::InitPlayerControls() { if (!Application::GameConfig) return; @@ -1011,7 +974,7 @@ PUBLIC STATIC void InputManager::InitPlayerControls() { } } -PRIVATE STATIC void InputManager::ParsePlayerControls(InputPlayer& player, XMLNode* node) { +void InputManager::ParsePlayerControls(InputPlayer& player, XMLNode* node) { for (size_t i = 0; i < node->children.size(); i++) { XMLNode* child = node->children[i]; if (XMLParser::MatchToken(child->name, "default")) { @@ -1052,7 +1015,7 @@ PRIVATE STATIC void InputManager::ParsePlayerControls(InputPlayer& player, XMLNo } } -PRIVATE STATIC Uint16 InputManager::ParseKeyModifiers(string& str, string& actionName) { +Uint16 InputManager::ParseKeyModifiers(string& str, string& actionName) { Uint16 flags = 0; std::stringstream strStream(str); @@ -1078,7 +1041,7 @@ PRIVATE STATIC Uint16 InputManager::ParseKeyModifiers(string& str, string& actio return flags; } -PRIVATE STATIC void InputManager::ParseDefaultInputBinds(InputPlayer& player, int actionID, string& actionName, XMLNode* node) { +void InputManager::ParseDefaultInputBinds(InputPlayer& player, int actionID, string& actionName, XMLNode* node) { for (size_t i = 0; i < node->children.size(); i++) { XMLNode* child = node->children[i]; @@ -1153,7 +1116,7 @@ PRIVATE STATIC void InputManager::ParseDefaultInputBinds(InputPlayer& player, in } } -PUBLIC STATIC void InputManager::Dispose() { +void InputManager::Dispose() { InputManager::ControllerStopRumble(); // Close controllers diff --git a/source/Engine/Math/Clipper.cpp b/source/Engine/Math/Clipper.cpp index 314167c0..1b3efb26 100644 --- a/source/Engine/Math/Clipper.cpp +++ b/source/Engine/Math/Clipper.cpp @@ -1,16 +1,7 @@ -#if INTERFACE -#include -#include - -class Clipper { -public: -}; -#endif - #include #include -PRIVATE STATIC void Clipper::AddPoint(VertexAttribute* buf, VertexAttribute* v1, VertexAttribute* v2, Vector4 p1, Vector4 p2, Sint64 t) { +void Clipper::AddPoint(VertexAttribute* buf, VertexAttribute* v1, VertexAttribute* v2, Vector4 p1, Vector4 p2, Sint64 t) { Vector4 diff = Vector::Subtract(p2, p1); Vector4 newPosition = Vector::Add(p1, Vector::Multiply(diff, t)); @@ -31,7 +22,7 @@ PRIVATE STATIC void Clipper::AddPoint(VertexAttribute* buf, VertexAttribute* v1, #undef DO_INTERP } -PRIVATE STATIC bool Clipper::ClipEdge(Frustum frustum, VertexAttribute* v1, VertexAttribute* v2, PolygonClipBuffer* output) { +bool Clipper::ClipEdge(Frustum frustum, VertexAttribute* v1, VertexAttribute* v2, PolygonClipBuffer* output) { VertexAttribute* buffer = &output->Buffer[output->NumPoints]; Vector4 pos1 = v1->Position; @@ -90,7 +81,7 @@ PRIVATE STATIC bool Clipper::ClipEdge(Frustum frustum, VertexAttribute* v1, Vert return true; } -PRIVATE STATIC int Clipper::ClipPolygon(Frustum frustum, PolygonClipBuffer* output, VertexAttribute* input, int vertexCount) { +int Clipper::ClipPolygon(Frustum frustum, PolygonClipBuffer* output, VertexAttribute* input, int vertexCount) { // Not even a triangle? if (vertexCount < 3) return 0; @@ -110,7 +101,7 @@ PRIVATE STATIC int Clipper::ClipPolygon(Frustum frustum, PolygonClipBuffer* out return output->NumPoints; } -PUBLIC STATIC int Clipper::FrustumClip(PolygonClipBuffer* output, Frustum* frustum, int num, VertexAttribute* input, int vertexCount) { +int Clipper::FrustumClip(PolygonClipBuffer* output, Frustum* frustum, int num, VertexAttribute* input, int vertexCount) { PolygonClipBuffer temp[NUM_FRUSTUM_PLANES]; VertexAttribute* buffer = input; diff --git a/source/Engine/Math/Ease.cpp b/source/Engine/Math/Ease.cpp index 9324126d..43637845 100644 --- a/source/Engine/Math/Ease.cpp +++ b/source/Engine/Math/Ease.cpp @@ -1,11 +1,3 @@ -#if INTERFACE -#include -class Ease { -public: - -}; -#endif - #include #include @@ -14,57 +6,57 @@ class Ease { #define PI 3.1415926545 #endif -PUBLIC STATIC float Ease::InSine(float t) { +float Ease::InSine(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return sin(1.5707963 * t); } -PUBLIC STATIC float Ease::OutSine(float t) { +float Ease::OutSine(float t) { t = Math::Clamp(t, 0.0f, 1.0f); t -= 1.0; return 1 + sin(1.5707963 * t); } -PUBLIC STATIC float Ease::InOutSine(float t) { +float Ease::InOutSine(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return 0.5 * (1 + sin(3.1415926 * (t - 0.5))); } -PUBLIC STATIC float Ease::InQuad(float t) { +float Ease::InQuad(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return t * t; } -PUBLIC STATIC float Ease::OutQuad(float t) { +float Ease::OutQuad(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return t * (2 - t); } -PUBLIC STATIC float Ease::InOutQuad(float t) { +float Ease::InOutQuad(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return t < 0.5 ? 2 * t * t : t * (4 - 2 * t) - 1; } -PUBLIC STATIC float Ease::InCubic(float t) { +float Ease::InCubic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return t * t * t; } -PUBLIC STATIC float Ease::OutCubic(float t) { +float Ease::OutCubic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); t -= 1.0; return 1 + t * t * t; } -PUBLIC STATIC float Ease::InOutCubic(float t) { +float Ease::InOutCubic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t >= 0.5) t -= 1.0; return t < 0.5 ? 4 * t * t * t : 1 + t * (2 * (t - 1)) * (2 * (t - 2)); } -PUBLIC STATIC float Ease::InQuart(float t) { +float Ease::InQuart(float t) { t = Math::Clamp(t, 0.0f, 1.0f); t *= t; return t * t; } -PUBLIC STATIC float Ease::OutQuart(float t) { +float Ease::OutQuart(float t) { t = Math::Clamp(t, 0.0f, 1.0f); t = (t - 1) * (t - 1); return 1 - t * t; } -PUBLIC STATIC float Ease::InOutQuart(float t) { +float Ease::InOutQuart(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { t *= t; @@ -75,17 +67,17 @@ PUBLIC STATIC float Ease::InOutQuart(float t) { return 1 - 8 * t * t; } } -PUBLIC STATIC float Ease::InQuint(float t) { +float Ease::InQuint(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2 = t * t; return t * t2 * t2; } -PUBLIC STATIC float Ease::OutQuint(float t) { +float Ease::OutQuint(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2 = (t - 1) * (t - 1); return 1 + t * t2 * t2; } -PUBLIC STATIC float Ease::InOutQuint(float t) { +float Ease::InOutQuint(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2; if (t < 0.5) { @@ -98,15 +90,15 @@ PUBLIC STATIC float Ease::InOutQuint(float t) { return 1.0f - 16.0f * t * t2 * t2; } } -PUBLIC STATIC float Ease::InExpo(float t) { +float Ease::InExpo(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return (pow(2, 8 * t) - 1) / 255; } -PUBLIC STATIC float Ease::OutExpo(float t) { +float Ease::OutExpo(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return 1 - pow(2, -8 * t); } -PUBLIC STATIC float Ease::InOutExpo(float t) { +float Ease::InOutExpo(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { return (pow(2, 16 * t) - 1) / 510; @@ -115,15 +107,15 @@ PUBLIC STATIC float Ease::InOutExpo(float t) { return 1 - 0.5 * pow(2, -16 * (t - 0.5)); } } -PUBLIC STATIC float Ease::InCirc(float t) { +float Ease::InCirc(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return 1 - sqrt(1 - t); } -PUBLIC STATIC float Ease::OutCirc(float t) { +float Ease::OutCirc(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return sqrt(t); } -PUBLIC STATIC float Ease::InOutCirc(float t) { +float Ease::InOutCirc(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { return (1 - sqrt(1 - 2 * t)) * 0.5; @@ -132,16 +124,16 @@ PUBLIC STATIC float Ease::InOutCirc(float t) { return (1 + sqrt(2 * t - 1)) * 0.5; } } -PUBLIC STATIC float Ease::InBack(float t) { +float Ease::InBack(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return t * t * (2.70158 * t - 1.70158); } -PUBLIC STATIC float Ease::OutBack(float t) { +float Ease::OutBack(float t) { t = Math::Clamp(t, 0.0f, 1.0f); t -= 1.0; return 1 + t * t * (2.70158 * t + 1.70158); } -PUBLIC STATIC float Ease::InOutBack(float t) { +float Ease::InOutBack(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { return t * t * (7 * t - 2.5) * 2; @@ -151,17 +143,17 @@ PUBLIC STATIC float Ease::InOutBack(float t) { return 1 + t * t * 2 * (7 * t + 2.5); } } -PUBLIC STATIC float Ease::InElastic(float t) { +float Ease::InElastic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2 = t * t; return t2 * t2 * sin(t * PI * 4.5); } -PUBLIC STATIC float Ease::OutElastic(float t) { +float Ease::OutElastic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2 = (t - 1) * (t - 1); return 1 - t2 * t2 * cos(t * PI * 4.5); } -PUBLIC STATIC float Ease::InOutElastic(float t) { +float Ease::InOutElastic(float t) { t = Math::Clamp(t, 0.0f, 1.0f); float t2; if (t < 0.45) { @@ -176,15 +168,15 @@ PUBLIC STATIC float Ease::InOutElastic(float t) { return 1 - 8 * t2 * t2 * sin(t * PI * 9); } } -PUBLIC STATIC float Ease::InBounce(float t) { +float Ease::InBounce(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return pow(2, 6 * (t - 1)) * abs(sin(t * PI * 3.5)); } -PUBLIC STATIC float Ease::OutBounce(float t) { +float Ease::OutBounce(float t) { t = Math::Clamp(t, 0.0f, 1.0f); return 1 - pow(2, -6 * t) * abs(cos(t * PI * 3.5)); } -PUBLIC STATIC float Ease::InOutBounce(float t) { +float Ease::InOutBounce(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { return 8 * pow(2, 8 * (t - 1)) * abs(sin(t * PI * 7)); @@ -193,7 +185,7 @@ PUBLIC STATIC float Ease::InOutBounce(float t) { return 1 - 8 * pow(2, -8 * t) * abs(sin(t * PI * 7)); } } -PUBLIC STATIC float Ease::Triangle(float t) { +float Ease::Triangle(float t) { t = Math::Clamp(t, 0.0f, 1.0f); if (t < 0.5) { return t * 2.0; diff --git a/source/Engine/Math/Geometry.cpp b/source/Engine/Math/Geometry.cpp index 629bd95b..997a45b3 100644 --- a/source/Engine/Math/Geometry.cpp +++ b/source/Engine/Math/Geometry.cpp @@ -1,12 +1,3 @@ -#if INTERFACE -#include -#include - -class Geometry { -public: -}; -#endif - #include #include @@ -15,7 +6,7 @@ class Geometry { #include #include -PRIVATE STATIC bool Geometry::CheckEar(vector& input, unsigned count, unsigned prev, unsigned curr, unsigned next) { +bool Geometry::CheckEar(vector& input, unsigned count, unsigned prev, unsigned curr, unsigned next) { FVector2& a = input[prev]; FVector2& b = input[curr]; FVector2& c = input[next]; @@ -46,7 +37,7 @@ PRIVATE STATIC bool Geometry::CheckEar(vector& input, unsigned count, return true; } -PRIVATE STATIC int Geometry::GetPointForTriangulation(int point, unsigned count) { +int Geometry::GetPointForTriangulation(int point, unsigned count) { if (point < 0) return point + count; else if (point >= count) @@ -69,7 +60,7 @@ static void FreeP2TPoints(std::vector& points) { delete points[i]; } -PUBLIC STATIC vector* Geometry::Triangulate(Polygon2D& input, vector holes) { +vector* Geometry::Triangulate(Polygon2D& input, vector holes) { vector points = input.Points; unsigned count = points.size(); @@ -151,7 +142,7 @@ static Clipper2Lib::FillRule GetFillRule(unsigned fillRule) { } } -PUBLIC STATIC vector* Geometry::Intersect(unsigned clipType, unsigned fillRule, vector inputSubjects, vector inputClips) { +vector* Geometry::Intersect(unsigned clipType, unsigned fillRule, vector inputSubjects, vector inputClips) { Clipper2Lib::PathsD subjects; Clipper2Lib::PathsD clips; diff --git a/source/Engine/Math/Math.cpp b/source/Engine/Math/Math.cpp index 056232c9..d5589328 100644 --- a/source/Engine/Math/Math.cpp +++ b/source/Engine/Math/Math.cpp @@ -1,10 +1,3 @@ -#if INTERFACE -#include -class Math { -public: -}; -#endif - int Sin1024LookupTable[0x400]; int Cos1024LookupTable[0x400]; int Tan1024LookupTable[0x400]; @@ -30,42 +23,42 @@ int randSeed = 0; #include #include -PUBLIC STATIC void Math::Init() { +void Math::Init() { srand((Uint32)time(NULL)); Math::ClearTrigLookupTables(); Math::CalculateTrigAngles(); } // Trig functions -PUBLIC STATIC float Math::Cos(float n) { +float Math::Cos(float n) { return std::cos(n); } -PUBLIC STATIC float Math::Sin(float n) { +float Math::Sin(float n) { return std::sin(n); } -PUBLIC STATIC float Math::Tan(float n) { +float Math::Tan(float n) { return std::tan(n); } -PUBLIC STATIC float Math::Asin(float x) { +float Math::Asin(float x) { return std::asin(x); } -PUBLIC STATIC float Math::Acos(float x) { +float Math::Acos(float x) { return std::acos(x); } -PUBLIC STATIC float Math::Atan(float x, float y) { +float Math::Atan(float x, float y) { if (x == 0.0f && y == 0.0f) return 0.0f; return std::atan2(y, x); } -PUBLIC STATIC float Math::Distance(float x1, float y1, float x2, float y2) { +float Math::Distance(float x1, float y1, float x2, float y2) { x2 -= x1; x2 *= x2; y2 -= y1; y2 *= y2; return (float)sqrt(x2 + y2); } -PUBLIC STATIC float Math::Hypot(float a, float b, float c) { +float Math::Hypot(float a, float b, float c) { return (float)sqrt(a * a + b * b + c * c); } -PUBLIC STATIC void Math::ClearTrigLookupTables() { +void Math::ClearTrigLookupTables() { memset(Sin256LookupTable, 0, sizeof(Sin256LookupTable)); memset(Cos256LookupTable, 0, sizeof(Cos256LookupTable)); memset(Tan256LookupTable, 0, sizeof(Tan256LookupTable)); @@ -84,7 +77,7 @@ PUBLIC STATIC void Math::ClearTrigLookupTables() { memset(ArcTan256LookupTable, 0, sizeof(ArcTan256LookupTable)); randSeed = 0; } -PUBLIC STATIC void Math::CalculateTrigAngles() { +void Math::CalculateTrigAngles() { randSeed = rand(); for (int i = 0; i < 0x400; i++) { @@ -131,69 +124,69 @@ PUBLIC STATIC void Math::CalculateTrigAngles() { ACos256LookupTable[i] = (int)((acosf(i / 255.0) * 128.0) / R_PI); } } -PUBLIC STATIC int Math::Sin1024(int angle) { +int Math::Sin1024(int angle) { return Sin1024LookupTable[angle & 0x3FF]; } -PUBLIC STATIC int Math::Cos1024(int angle) { +int Math::Cos1024(int angle) { return Cos1024LookupTable[angle & 0x3FF]; } -PUBLIC STATIC int Math::Tan1024(int angle) { +int Math::Tan1024(int angle) { return Tan1024LookupTable[angle & 0x3FF]; } -PUBLIC STATIC int Math::ASin1024(int angle) { +int Math::ASin1024(int angle) { if (angle > 0x3FF) return 0; if (angle < 0) return -ASin1024LookupTable[-angle]; return ASin1024LookupTable[angle]; } -PUBLIC STATIC int Math::ACos1024(int angle) { +int Math::ACos1024(int angle) { if (angle > 0x3FF) return 0; if (angle < 0) return -ACos1024LookupTable[-angle]; return ACos1024LookupTable[angle]; } -PUBLIC STATIC int Math::Sin512(int angle) { +int Math::Sin512(int angle) { return Sin512LookupTable[angle & 0x1FF]; } -PUBLIC STATIC int Math::Cos512(int angle) { +int Math::Cos512(int angle) { return Cos512LookupTable[angle & 0x1FF]; } -PUBLIC STATIC int Math::Tan512(int angle) { +int Math::Tan512(int angle) { return Tan512LookupTable[angle & 0x1FF]; } -PUBLIC STATIC int Math::ASin512(int angle) { +int Math::ASin512(int angle) { if (angle > 0x1FF) return 0; if (angle < 0) return -ASin512LookupTable[-angle]; return ASin512LookupTable[angle]; } -PUBLIC STATIC int Math::ACos512(int angle) { +int Math::ACos512(int angle) { if (angle > 0x1FF) return 0; if (angle < 0) return -ACos512LookupTable[-angle]; return ACos512LookupTable[angle]; } -PUBLIC STATIC int Math::Sin256(int angle) { +int Math::Sin256(int angle) { return Sin256LookupTable[angle & 0XFF]; } -PUBLIC STATIC int Math::Cos256(int angle) { +int Math::Cos256(int angle) { return Cos256LookupTable[angle & 0XFF]; } -PUBLIC STATIC int Math::Tan256(int angle) { +int Math::Tan256(int angle) { return Tan256LookupTable[angle & 0xFF]; } -PUBLIC STATIC int Math::ASin256(int angle) { +int Math::ASin256(int angle) { if (angle > 0xFF) return 0; if (angle < 0) return -ASin256LookupTable[-angle]; return ASin256LookupTable[angle]; } -PUBLIC STATIC int Math::ACos256(int angle) { +int Math::ACos256(int angle) { if (angle > 0XFF) return 0; if (angle < 0) @@ -202,7 +195,7 @@ PUBLIC STATIC int Math::ACos256(int angle) { } // help -PUBLIC STATIC int Math::CeilPOT(int n) { +int Math::CeilPOT(int n) { n--; n |= n >> 1; n |= n >> 2; @@ -214,39 +207,39 @@ PUBLIC STATIC int Math::CeilPOT(int n) { } // Deterministic functions -PUBLIC STATIC float Math::Abs(float n) { +float Math::Abs(float n) { return std::abs(n); } -PUBLIC STATIC float Math::Max(float a, float b) { +float Math::Max(float a, float b) { return a > b ? a : b; } -PUBLIC STATIC float Math::Min(float a, float b) { +float Math::Min(float a, float b) { return a < b ? a : b; } -PUBLIC STATIC float Math::Clamp(float v, float a, float b) { +float Math::Clamp(float v, float a, float b) { return Math::Max(a, Math::Min(v, b)); } -PUBLIC STATIC float Math::Sign(float a) { +float Math::Sign(float a) { return a < 0.0f ? -1.0f : a > 0.0f ? 1.0f : 0.0f; } // Random functions (non-inclusive) -PUBLIC STATIC float Math::Random() { +float Math::Random() { return rand() / (float)RAND_MAX; } -PUBLIC STATIC float Math::RandomMax(float max) { +float Math::RandomMax(float max) { return Math::Random() * max; } -PUBLIC STATIC float Math::RandomRange(float min, float max) { +float Math::RandomRange(float min, float max) { return (Math::Random() * (max - min)) + min; } -PUBLIC STATIC int Math::RSDK_GetRandSeed() { +int Math::RSDK_GetRandSeed() { return randSeed; } -PUBLIC STATIC void Math::RSDK_SetRandSeed(int key) { +void Math::RSDK_SetRandSeed(int key) { randSeed = key; } -PUBLIC STATIC int Math::RSDK_RandomInteger(int min, int max) { +int Math::RSDK_RandomInteger(int min, int max) { int seed1 = 1103515245 * randSeed + 12345; int seed2 = 1103515245 * seed1 + 12345; randSeed = 1103515245 * seed2 + 12345; @@ -261,7 +254,7 @@ PUBLIC STATIC int Math::RSDK_RandomInteger(int min, int max) { else return max; } -PUBLIC STATIC int Math::RSDK_RandomIntegerSeeded(int min, int max, int seed) { +int Math::RSDK_RandomIntegerSeeded(int min, int max, int seed) { if (!randSeed) return 0; diff --git a/source/Engine/Math/Matrix4x4.cpp b/source/Engine/Math/Matrix4x4.cpp index 4bab939b..a2fb1095 100644 --- a/source/Engine/Math/Matrix4x4.cpp +++ b/source/Engine/Math/Matrix4x4.cpp @@ -1,10 +1,3 @@ -#if INTERFACE -class Matrix4x4 { -public: - float Values[16]; -}; -#endif - #include #include @@ -15,12 +8,12 @@ class Matrix4x4 { #define EPSILON 0.000001 -PUBLIC STATIC Matrix4x4* Matrix4x4::Create() { +Matrix4x4* Matrix4x4::Create() { Matrix4x4* mat4 = new Matrix4x4; Matrix4x4::Identity(mat4); return mat4; } -PUBLIC STATIC void Matrix4x4::Identity(Matrix4x4* mat4) { +void Matrix4x4::Identity(Matrix4x4* mat4) { mat4->Values[0] = 1.0f; mat4->Values[1] = 0.0f; mat4->Values[2] = 0.0f; @@ -39,7 +32,7 @@ PUBLIC STATIC void Matrix4x4::Identity(Matrix4x4* mat4) { mat4->Values[15] = 1.0f; } -PUBLIC STATIC void Matrix4x4::Perspective(Matrix4x4* out, float fovy, float aspect, float near, float far) { +void Matrix4x4::Perspective(Matrix4x4* out, float fovy, float aspect, float near, float far) { float f = 1.0f / tan(fovy / 2.0f); float nf = 1.0f / (near - far); out->Values[0] = f / aspect; @@ -59,7 +52,7 @@ PUBLIC STATIC void Matrix4x4::Perspective(Matrix4x4* out, float fovy, floa out->Values[14] = 2.0f * far * near * nf; out->Values[15] = 0.0f; } -PUBLIC STATIC void Matrix4x4::Ortho(Matrix4x4* out, float left, float right, float bottom, float top, float near, float far) { +void Matrix4x4::Ortho(Matrix4x4* out, float left, float right, float bottom, float top, float near, float far) { float lr = 1.0f / (left - right); float bt = 1.0f / (bottom - top); float nf = 1.0f / (near - far); @@ -81,17 +74,17 @@ PUBLIC STATIC void Matrix4x4::Ortho(Matrix4x4* out, float left, float righ out->Values[15] = 1.0f; } -PUBLIC STATIC void Matrix4x4::Copy(Matrix4x4* out, Matrix4x4* a) { +void Matrix4x4::Copy(Matrix4x4* out, Matrix4x4* a) { memcpy(&out->Values[0], &a->Values[0], 16 * sizeof(float)); } -PUBLIC STATIC bool Matrix4x4::Equals(Matrix4x4* a, Matrix4x4* b) { +bool Matrix4x4::Equals(Matrix4x4* a, Matrix4x4* b) { if (!a && !b) return true; if (!a || !b) return false; return memcmp(&a->Values[0], &b->Values[0], 16 * sizeof(float)) == 0; } -PUBLIC STATIC void Matrix4x4::Multiply(Matrix4x4* out, Matrix4x4* a, Matrix4x4* b) { +void Matrix4x4::Multiply(Matrix4x4* out, Matrix4x4* a, Matrix4x4* b) { float a00 = a->Values[0], a01 = a->Values[1], a02 = a->Values[2], a03 = a->Values[3]; float a10 = a->Values[4], a11 = a->Values[5], a12 = a->Values[6], a13 = a->Values[7]; float a20 = a->Values[8], a21 = a->Values[9], a22 = a->Values[10], a23 = a->Values[11]; @@ -122,7 +115,7 @@ PUBLIC STATIC void Matrix4x4::Multiply(Matrix4x4* out, Matrix4x4* a, Matri out->Values[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; out->Values[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; } -PUBLIC STATIC void Matrix4x4::Multiply(Matrix4x4* mat, float* a) { +void Matrix4x4::Multiply(Matrix4x4* mat, float* a) { float a0 = a[0]; float a1 = a[1]; float a2 = a[2]; @@ -134,7 +127,7 @@ PUBLIC STATIC void Matrix4x4::Multiply(Matrix4x4* mat, float* a) { a[3] = mat->Values[3] * a0 + mat->Values[7] * a1 + mat->Values[11] * a2 + mat->Values[15] * a3; } -PUBLIC STATIC void Matrix4x4::Translate(Matrix4x4* out, Matrix4x4* a, float x, float y, float z) { +void Matrix4x4::Translate(Matrix4x4* out, Matrix4x4* a, float x, float y, float z) { float a00, a01, a02, a03; float a10, a11, a12, a13; float a20, a21, a22, a23; @@ -159,7 +152,7 @@ PUBLIC STATIC void Matrix4x4::Translate(Matrix4x4* out, Matrix4x4* a, floa out->Values[15] = a03 * x + a13 * y + a23 * z + a->Values[15]; } } -PUBLIC STATIC void Matrix4x4::Scale(Matrix4x4* out, Matrix4x4* a, float x, float y, float z) { +void Matrix4x4::Scale(Matrix4x4* out, Matrix4x4* a, float x, float y, float z) { out->Values[0] = a->Values[0] * x; out->Values[1] = a->Values[1] * x; out->Values[2] = a->Values[2] * x; @@ -177,7 +170,7 @@ PUBLIC STATIC void Matrix4x4::Scale(Matrix4x4* out, Matrix4x4* a, float x, out->Values[14] = a->Values[14]; out->Values[15] = a->Values[15]; } -PUBLIC STATIC void Matrix4x4::Rotate(Matrix4x4* out, Matrix4x4* a, float rad, float x, float y, float z) { +void Matrix4x4::Rotate(Matrix4x4* out, Matrix4x4* a, float rad, float x, float y, float z) { float len = sqrt(x * x + y * y + z * z); float s, c, t; float a00, a01, a02, a03; @@ -232,14 +225,14 @@ PUBLIC STATIC void Matrix4x4::Rotate(Matrix4x4* out, Matrix4x4* a, float r out->Values[15] = a->Values[15]; } } -PUBLIC STATIC void Matrix4x4::IdentityScale(Matrix4x4* out, float x, float y, float z) { +void Matrix4x4::IdentityScale(Matrix4x4* out, float x, float y, float z) { Matrix4x4::Identity(out); out->Values[0] = x; out->Values[5] = y; out->Values[10] = z; } -PUBLIC STATIC void Matrix4x4::IdentityRotationX(Matrix4x4* out, float x) { +void Matrix4x4::IdentityRotationX(Matrix4x4* out, float x) { Matrix4x4::Identity(out); float sinX = Math::Sin(x); @@ -249,7 +242,7 @@ PUBLIC STATIC void Matrix4x4::IdentityRotationX(Matrix4x4* out, float x) { out->Values[8] = -sinX; out->Values[9] = cosX; } -PUBLIC STATIC void Matrix4x4::IdentityRotationY(Matrix4x4* out, float y) { +void Matrix4x4::IdentityRotationY(Matrix4x4* out, float y) { Matrix4x4::Identity(out); float sinY = Math::Sin(y); @@ -259,7 +252,7 @@ PUBLIC STATIC void Matrix4x4::IdentityRotationY(Matrix4x4* out, float y) { out->Values[8] = -sinY; out->Values[10] = cosY; } -PUBLIC STATIC void Matrix4x4::IdentityRotationZ(Matrix4x4* out, float z) { +void Matrix4x4::IdentityRotationZ(Matrix4x4* out, float z) { Matrix4x4::Identity(out); float sinZ = Math::Sin(z); @@ -270,7 +263,7 @@ PUBLIC STATIC void Matrix4x4::IdentityRotationZ(Matrix4x4* out, float z) { out->Values[4] = -sinZ; out->Values[5] = cosZ; } -PUBLIC STATIC void Matrix4x4::IdentityRotationXYZ(Matrix4x4* out, float x, float y, float z) { +void Matrix4x4::IdentityRotationXYZ(Matrix4x4* out, float x, float y, float z) { float sinX = Math::Sin(x); float cosX = Math::Cos(x); float sinY = Math::Sin(y); @@ -297,7 +290,7 @@ PUBLIC STATIC void Matrix4x4::IdentityRotationXYZ(Matrix4x4* out, float x, out->Values[11] = 0.f; out->Values[15] = 1.f; } -PUBLIC STATIC void Matrix4x4::Transpose(Matrix4x4* out) { +void Matrix4x4::Transpose(Matrix4x4* out) { Matrix4x4 transposed; for (int i = 0; i < 4; i++) { @@ -307,7 +300,7 @@ PUBLIC STATIC void Matrix4x4::Transpose(Matrix4x4* out) { Matrix4x4::Copy(out, &transposed); } -PUBLIC STATIC void Matrix4x4::LookAt(Matrix4x4* out, float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) { +void Matrix4x4::LookAt(Matrix4x4* out, float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) { float x0, x1, x2, y0, y1, y2, z0, z1, z2, len; if (Math::Abs(eyex - centerx) < EPSILON && Math::Abs(eyey - centery) < EPSILON && @@ -375,7 +368,7 @@ PUBLIC STATIC void Matrix4x4::LookAt(Matrix4x4* out, float eyex, float eye return; } -PUBLIC STATIC void Matrix4x4::Invert(Matrix4x4* out, Matrix4x4* in) { +void Matrix4x4::Invert(Matrix4x4* out, Matrix4x4* in) { float *src = in->Values; float inv[16]; @@ -408,6 +401,6 @@ PUBLIC STATIC void Matrix4x4::Invert(Matrix4x4* out, Matrix4x4* in) { } } -PUBLIC STATIC void Matrix4x4::Print(Matrix4x4* out) { +void Matrix4x4::Print(Matrix4x4* out) { Log::Print(Log::LOG_INFO, "\n%6.2f %6.2f %6.2f %6.2f \n%6.2f %6.2f %6.2f %6.2f \n%6.2f %6.2f %6.2f %6.2f \n%6.2f %6.2f %6.2f %6.2f", out->Values[0], out->Values[1], out->Values[2], out->Values[3], out->Values[4], out->Values[5], out->Values[6], out->Values[7], out->Values[8], out->Values[9], out->Values[10], out->Values[11], out->Values[12], out->Values[13], out->Values[14], out->Values[15]); } diff --git a/source/Engine/Math/Random.cpp b/source/Engine/Math/Random.cpp index f3cb789d..31fe7529 100644 --- a/source/Engine/Math/Random.cpp +++ b/source/Engine/Math/Random.cpp @@ -1,34 +1,26 @@ -#if INTERFACE -#include -class Random { -public: - static Sint32 Seed; -}; -#endif - #include #define INITIAL_RANDOM_SEED 1938465012 Sint32 Random::Seed = INITIAL_RANDOM_SEED; -PUBLIC STATIC void Random::SetSeed(Sint32 seed) { +void Random::SetSeed(Sint32 seed) { if (!seed) seed = INITIAL_RANDOM_SEED; Seed = seed; } -PUBLIC STATIC float Random::Get() { +float Random::Get() { Sint32 nextSeed = (1103515245 * Seed + 12345) & 0x7FFFFFFF; Seed = nextSeed; return ((float)nextSeed) / 0x7FFFFFFF; } -PUBLIC STATIC float Random::Max(float max) { +float Random::Max(float max) { return Random::Get() * max; } -PUBLIC STATIC float Random::Range(float min, float max) { +float Random::Range(float min, float max) { return (Random::Get() * (max - min)) + min; } diff --git a/source/Engine/Math/Vector.cpp b/source/Engine/Math/Vector.cpp index ff0675e1..b63dfa62 100644 --- a/source/Engine/Math/Vector.cpp +++ b/source/Engine/Math/Vector.cpp @@ -1,17 +1,7 @@ -#if INTERFACE -#include -#include -#include - -class Vector { -public: -}; -#endif - #include #include -PUBLIC STATIC Vector4 Vector::Add(Vector4 v1, Vector4 v2) { +Vector4 Vector::Add(Vector4 v1, Vector4 v2) { Vector4 result; result.X = v1.X + v2.X; result.Y = v1.Y + v2.Y; @@ -20,7 +10,7 @@ PUBLIC STATIC Vector4 Vector::Add(Vector4 v1, Vector4 v2) { return result; } -PUBLIC STATIC Vector4 Vector::Subtract(Vector4 v1, Vector4 v2) { +Vector4 Vector::Subtract(Vector4 v1, Vector4 v2) { Vector4 result; result.X = v1.X - v2.X; result.Y = v1.Y - v2.Y; @@ -29,7 +19,7 @@ PUBLIC STATIC Vector4 Vector::Subtract(Vector4 v1, Vector4 v2) { return result; } -PUBLIC STATIC Vector4 Vector::Multiply(Vector4 v, Sint64 t) { +Vector4 Vector::Multiply(Vector4 v, Sint64 t) { Vector4 result; result.X = FP16_MULTIPLY(v.X, t); result.Y = FP16_MULTIPLY(v.Y, t); @@ -38,7 +28,7 @@ PUBLIC STATIC Vector4 Vector::Multiply(Vector4 v, Sint64 t) { return result; } -PUBLIC STATIC Vector3 Vector::Multiply(Vector3 v, Matrix4x4* m) { +Vector3 Vector::Multiply(Vector3 v, Matrix4x4* m) { Vector3 result; Sint64 mat11 = m->Values[0] * 0x10000; @@ -61,7 +51,7 @@ PUBLIC STATIC Vector3 Vector::Multiply(Vector3 v, Matrix4x4* m) { return result; } -PUBLIC STATIC Vector2 Vector::Interpolate(Vector2 v1, Vector2 v2, Sint64 t) { +Vector2 Vector::Interpolate(Vector2 v1, Vector2 v2, Sint64 t) { Vector2 result; result.X = v1.X + FP16_MULTIPLY(v2.X - v1.X, t); @@ -70,7 +60,7 @@ PUBLIC STATIC Vector2 Vector::Interpolate(Vector2 v1, Vector2 v2, Sint64 t) { return result; } -PUBLIC STATIC Vector3 Vector::Interpolate(Vector3 v1, Vector3 v2, Sint64 t) { +Vector3 Vector::Interpolate(Vector3 v1, Vector3 v2, Sint64 t) { Vector3 result; result.X = v1.X + FP16_MULTIPLY(v2.X - v1.X, t); @@ -80,7 +70,7 @@ PUBLIC STATIC Vector3 Vector::Interpolate(Vector3 v1, Vector3 v2, Sint64 t) { return result; } -PUBLIC STATIC Vector4 Vector::Interpolate(Vector4 v1, Vector4 v2, Sint64 t) { +Vector4 Vector::Interpolate(Vector4 v1, Vector4 v2, Sint64 t) { Vector4 result; result.X = v1.X + FP16_MULTIPLY(v2.X - v1.X, t); @@ -91,7 +81,7 @@ PUBLIC STATIC Vector4 Vector::Interpolate(Vector4 v1, Vector4 v2, Sint64 t) { return result; } -PUBLIC STATIC Sint64 Vector::DotProduct(Vector4 v1, Vector4 v2) { +Sint64 Vector::DotProduct(Vector4 v1, Vector4 v2) { Sint64 result = 0; result += FP16_MULTIPLY(v1.X, v2.X); result += FP16_MULTIPLY(v1.Y, v2.Y); @@ -100,13 +90,13 @@ PUBLIC STATIC Sint64 Vector::DotProduct(Vector4 v1, Vector4 v2) { return result; } -PUBLIC STATIC Sint64 Vector::Length(Vector4 v) { +Sint64 Vector::Length(Vector4 v) { float result = Vector::DotProduct(v, v); result = sqrtf(result / 0x10000); return result * 0x10000; } -PUBLIC STATIC Vector4 Vector::Normalize(Vector4 v) { +Vector4 Vector::Normalize(Vector4 v) { Vector4 result; Sint64 length = Vector::Length(v); @@ -122,7 +112,7 @@ PUBLIC STATIC Vector4 Vector::Normalize(Vector4 v) { return result; } -PUBLIC STATIC Sint64 Vector::IntersectWithPlane(Vector4 plane, Vector4 normal, Vector4 v1, Vector4 v2) { +Sint64 Vector::IntersectWithPlane(Vector4 plane, Vector4 normal, Vector4 v1, Vector4 v2) { Vector4 planeNormal = Vector::Normalize(normal); Sint64 dotProduct = Vector::DotProduct(v1, planeNormal); Sint64 t = Vector::DotProduct(planeNormal, plane) - dotProduct; @@ -133,7 +123,7 @@ PUBLIC STATIC Sint64 Vector::IntersectWithPlane(Vector4 plane, Vector4 normal, return FP16_DIVIDE(t, diff); } -PUBLIC STATIC Sint64 Vector::DistanceToPlane(Vector4 v, Vector4 plane, Vector4 normal) { +Sint64 Vector::DistanceToPlane(Vector4 v, Vector4 plane, Vector4 normal) { Sint64 dotProduct = Vector::DotProduct(normal, plane); Sint64 result = 0; diff --git a/source/Engine/Media/Decoder.cpp b/source/Engine/Media/Decoder.cpp index c4911146..ceb3ddb3 100644 --- a/source/Engine/Media/Decoder.cpp +++ b/source/Engine/Media/Decoder.cpp @@ -1,31 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include - -class Decoder { -public: - bool Successful; - int StreamIndex; - double ClockSync; - double ClockPos; - - PtrBuffer* Buffer[2]; - SDL_mutex* OutputLock; - AVCodecContext* CodecCtx; - AVFormatContext* FormatCtx; - - Uint32 Format; // SDL_Format - - int (*DecodeFunc)(void*, AVPacket*); - void (*CloseFunc)(void*); -}; -#endif - #include #include @@ -43,11 +15,11 @@ enum { typedef void (*FreePacketCallback)(void*); // void (*)(void*) -PUBLIC STATIC void Decoder::FreeInVideoPacketFunc(void* packet) { +void Decoder::FreeInVideoPacketFunc(void* packet) { av_packet_free((AVPacket**)&packet); } -PUBLIC void Decoder::Create(MediaSource* src, int stream_index, int outBufferLength, void (*freeOutFunc)(void*), int thread_count) { +void Decoder::Create(MediaSource* src, int stream_index, int outBufferLength, void (*freeOutFunc)(void*), int thread_count) { if (outBufferLength <= 0) { Log::Print(Log::LOG_ERROR, "Decoder::Create: outBufferLength <= 0"); exit(-1); @@ -160,7 +132,7 @@ PUBLIC void Decoder::Create(MediaSource* src, int stream_index, int exit_0: return; } -PUBLIC void Decoder::Close() { +void Decoder::Close() { if (CloseFunc) CloseFunc(this); @@ -171,10 +143,10 @@ PUBLIC void Decoder::Close() { avcodec_close(CodecCtx); avcodec_free_context(&CodecCtx); } -PUBLIC Decoder::~Decoder() { +Decoder::~Decoder() { Close(); } -PUBLIC int Decoder::Run() { +int Decoder::Run() { AVPacket* in_packet; int is_output_full = 1; @@ -201,48 +173,48 @@ PUBLIC int Decoder::Run() { return 0; } // ---- Information API ---- -PUBLIC int Decoder::GetCodecInfo(Codec* codec) { +int Decoder::GetCodecInfo(Codec* codec) { codec->Threads = CodecCtx->thread_count; strncpy(codec->Name, CodecCtx->codec->name, KIT_CODEC_NAME_MAX - 1); strncpy(codec->Description, CodecCtx->codec->long_name, KIT_CODEC_DESC_MAX - 1); return 0; } -PUBLIC int Decoder::GetOutputFormat(OutputFormat* output) { +int Decoder::GetOutputFormat(OutputFormat* output) { output->Format = Format; return 0; } -PUBLIC int Decoder::GetStreamIndex() { +int Decoder::GetStreamIndex() { return StreamIndex; } // ---- Clock handling ---- -PUBLIC void Decoder::SetClockSync(double sync) { +void Decoder::SetClockSync(double sync) { ClockSync = sync; } -PUBLIC void Decoder::ChangeClockSync(double sync) { +void Decoder::ChangeClockSync(double sync) { ClockSync += sync; } // ---- Input buffer handling ---- -PUBLIC int Decoder::WriteInput(AVPacket* packet) { +int Decoder::WriteInput(AVPacket* packet) { return Buffer[KIT_DEC_BUF_IN]->Write(packet); } -PUBLIC AVPacket* Decoder::PeekInput() { +AVPacket* Decoder::PeekInput() { return (AVPacket*)Buffer[KIT_DEC_BUF_IN]->Peek(); } -PUBLIC AVPacket* Decoder::ReadInput() { +AVPacket* Decoder::ReadInput() { return (AVPacket*)Buffer[KIT_DEC_BUF_IN]->Read(); } -PUBLIC bool Decoder::CanWriteInput() { +bool Decoder::CanWriteInput() { return !(Buffer[KIT_DEC_BUF_IN]->IsFull()); } -PUBLIC void Decoder::AdvanceInput() { +void Decoder::AdvanceInput() { Buffer[KIT_DEC_BUF_IN]->Advance(); } -PUBLIC void Decoder::ClearInput() { +void Decoder::ClearInput() { Buffer[KIT_DEC_BUF_IN]->Clear(); } // ---- Output buffer handling ---- // Kit_([A-z0-9_]+)Buffer([A-z0-9_]*)\((.*)\) -PUBLIC int Decoder::WriteOutput(void* packet) { +int Decoder::WriteOutput(void* packet) { int ret = 1; if (SDL_LockMutex(OutputLock) == 0) { ret = Buffer[KIT_DEC_BUF_OUT]->Write(packet); @@ -250,7 +222,7 @@ PUBLIC int Decoder::WriteOutput(void* packet) { } return ret; } -PUBLIC void* Decoder::PeekOutput() { +void* Decoder::PeekOutput() { void* ret = NULL; if (SDL_LockMutex(OutputLock) == 0) { ret = Buffer[KIT_DEC_BUF_OUT]->Peek(); @@ -258,7 +230,7 @@ PUBLIC void* Decoder::PeekOutput() { } return ret; } -PUBLIC void* Decoder::ReadOutput() { +void* Decoder::ReadOutput() { void* ret = NULL; if (SDL_LockMutex(OutputLock) == 0) { ret = Buffer[KIT_DEC_BUF_OUT]->Read(); @@ -266,7 +238,7 @@ PUBLIC void* Decoder::ReadOutput() { } return ret; } -PUBLIC bool Decoder::CanWriteOutput() { +bool Decoder::CanWriteOutput() { bool ret = false; if (SDL_LockMutex(OutputLock) == 0) { ret = !(Buffer[KIT_DEC_BUF_OUT]->IsFull()); @@ -274,29 +246,29 @@ PUBLIC bool Decoder::CanWriteOutput() { } return ret; } -PUBLIC void Decoder::AdvanceOutput() { +void Decoder::AdvanceOutput() { if (SDL_LockMutex(OutputLock) == 0) { Buffer[KIT_DEC_BUF_OUT]->Advance(); SDL_UnlockMutex(OutputLock); } } -PUBLIC void Decoder::ClearOutput() { +void Decoder::ClearOutput() { if (SDL_LockMutex(OutputLock) == 0) { Buffer[KIT_DEC_BUF_OUT]->Clear(); SDL_UnlockMutex(OutputLock); } } -PUBLIC void Decoder::ForEachOutput(void (*cb)(void*, void*), void* userdata) { +void Decoder::ForEachOutput(void (*cb)(void*, void*), void* userdata) { if (SDL_LockMutex(OutputLock) == 0) { Buffer[KIT_DEC_BUF_OUT]->ForEachItemInBuffer(cb, userdata); SDL_UnlockMutex(OutputLock); } } -PUBLIC Uint32 Decoder::GetInputLength() { +Uint32 Decoder::GetInputLength() { return Buffer[KIT_DEC_BUF_IN]->GetLength(); } -PUBLIC Uint32 Decoder::GetOutputLength() { +Uint32 Decoder::GetOutputLength() { Uint32 len = 0; if (SDL_LockMutex(OutputLock) == 0) { len = Buffer[KIT_DEC_BUF_OUT]->GetLength(); @@ -304,16 +276,16 @@ PUBLIC Uint32 Decoder::GetOutputLength() { } return len; } -PUBLIC void Decoder::ClearBuffers() { +void Decoder::ClearBuffers() { ClearInput(); ClearOutput(); avcodec_flush_buffers(CodecCtx); } -PUBLIC int Decoder::LockOutput() { +int Decoder::LockOutput() { return SDL_LockMutex(OutputLock); } -PUBLIC void Decoder::UnlockOutput() { +void Decoder::UnlockOutput() { SDL_UnlockMutex(OutputLock); } diff --git a/source/Engine/Media/Decoders/AudioDecoder.cpp b/source/Engine/Media/Decoders/AudioDecoder.cpp index e2b9b8fa..1a6a99d2 100644 --- a/source/Engine/Media/Decoders/AudioDecoder.cpp +++ b/source/Engine/Media/Decoders/AudioDecoder.cpp @@ -1,20 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class AudioDecoder : public Decoder { -public: - SwrContext* SWR; - AVFrame* ScratchFrame; - - int SampleRate; - int Channels; - int Bytes; - int IsSigned; -}; -#endif - #include #include @@ -33,7 +16,7 @@ struct AudioPacket { #define KIT_AUDIO_SYNC_THRESHOLD 0.05 // Lifecycle functions -PUBLIC AudioDecoder::AudioDecoder(MediaSource* src, int stream_index) { +AudioDecoder::AudioDecoder(MediaSource* src, int stream_index) { int ret; if (stream_index < 0) { Log::Print(Log::LOG_ERROR, "stream_index < 0"); @@ -128,7 +111,7 @@ PUBLIC AudioDecoder::AudioDecoder(MediaSource* src, int st // exit_0: return; } -PUBLIC void* AudioDecoder::CreateAudioPacket(const char* data, size_t len, double pts) { +void* AudioDecoder::CreateAudioPacket(const char* data, size_t len, double pts) { AudioPacket* packet = (AudioPacket*)calloc(1, sizeof(AudioPacket)); if (!packet) { Log::Print(Log::LOG_ERROR, "Something went horribly wrong. (Ran out of memory at AudioDecoder::CreateAudioPacket \"(AudioPacket*)calloc\")"); @@ -143,14 +126,14 @@ PUBLIC void* AudioDecoder::CreateAudioPacket(const char* data, s packet->pts = pts; return packet; } -PUBLIC STATIC void AudioDecoder::FreeAudioPacket(void* p) { +void AudioDecoder::FreeAudioPacket(void* p) { AudioPacket* packet = (AudioPacket*)p; delete packet->buffer; free(packet); } // Unique format info functions -PUBLIC AVSampleFormat AudioDecoder::FindAVSampleFormat(int format) { +AVSampleFormat AudioDecoder::FindAVSampleFormat(int format) { switch (format) { case AUDIO_U8: return AV_SAMPLE_FMT_U8; @@ -164,14 +147,14 @@ PUBLIC AVSampleFormat AudioDecoder::FindAVSampleFormat(int format) { return AV_SAMPLE_FMT_NONE; } } -PUBLIC Sint64 AudioDecoder::FindAVChannelLayout(int channels) { +Sint64 AudioDecoder::FindAVChannelLayout(int channels) { switch (channels) { case 1: return AV_CH_LAYOUT_MONO; case 2: return AV_CH_LAYOUT_STEREO; default: return AV_CH_LAYOUT_STEREO_DOWNMIX; } } -PUBLIC int AudioDecoder::FindChannelLayout(uint64_t channel_layout) { +int AudioDecoder::FindChannelLayout(uint64_t channel_layout) { switch (channel_layout) { case AV_CH_LAYOUT_MONO: return 1; case AV_CH_LAYOUT_STEREO: return 2; @@ -180,7 +163,7 @@ PUBLIC int AudioDecoder::FindChannelLayout(uint64_t channel_la } return 2; } -PUBLIC int AudioDecoder::FindBytes(AVSampleFormat fmt) { +int AudioDecoder::FindBytes(AVSampleFormat fmt) { switch (fmt) { case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: @@ -198,7 +181,7 @@ PUBLIC int AudioDecoder::FindBytes(AVSampleFormat fmt) { return 2; } } -PUBLIC int AudioDecoder::FindSignedness(AVSampleFormat fmt) { +int AudioDecoder::FindSignedness(AVSampleFormat fmt) { switch (fmt) { case AV_SAMPLE_FMT_U8P: case AV_SAMPLE_FMT_U8: @@ -207,7 +190,7 @@ PUBLIC int AudioDecoder::FindSignedness(AVSampleFormat fmt) { return 1; } } -PUBLIC int AudioDecoder::FindSDLSampleFormat(AVSampleFormat fmt) { +int AudioDecoder::FindSDLSampleFormat(AVSampleFormat fmt) { switch (fmt) { case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: @@ -227,7 +210,7 @@ PUBLIC int AudioDecoder::FindSDLSampleFormat(AVSampleFormat fm } // Common format info functions -PUBLIC int AudioDecoder::GetOutputFormat(OutputFormat* output) { +int AudioDecoder::GetOutputFormat(OutputFormat* output) { output->Format = Format; output->SampleRate = SampleRate; output->Channels = Channels; @@ -237,7 +220,7 @@ PUBLIC int AudioDecoder::GetOutputFormat(OutputFormat* output) } // Unique decoding functions -PUBLIC STATIC void AudioDecoder::ReadAudio(void* ptr) { +void AudioDecoder::ReadAudio(void* ptr) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) AudioDecoder* self = (AudioDecoder*)ptr; int len, dst_linesize, dst_nb_samples, dst_bufsize; @@ -291,7 +274,7 @@ PUBLIC STATIC void AudioDecoder::ReadAudio(void* ptr) { } #endif } -PUBLIC STATIC int AudioDecoder::DecodeFunction(void* ptr, AVPacket* in_packet) { +int AudioDecoder::DecodeFunction(void* ptr, AVPacket* in_packet) { if (in_packet == NULL) { return 0; } @@ -378,7 +361,7 @@ PUBLIC STATIC int AudioDecoder::DecodeFunction(void* ptr, AVPacket* i #endif return 0; } -PUBLIC STATIC void AudioDecoder::CloseFunction(void* ptr) { +void AudioDecoder::CloseFunction(void* ptr) { AudioDecoder* self = (AudioDecoder*)ptr; if (self->ScratchFrame != NULL) { @@ -390,14 +373,14 @@ PUBLIC STATIC void AudioDecoder::CloseFunction(void* ptr) { } // Data functions -PUBLIC double AudioDecoder::GetPTS() { +double AudioDecoder::GetPTS() { AudioPacket* packet = (AudioPacket*)PeekOutput(); if (packet == NULL) { return -1.0; } return packet->pts; } -PUBLIC int AudioDecoder::GetAudioDecoderData(Uint8* buf, int len) { +int AudioDecoder::GetAudioDecoderData(Uint8* buf, int len) { AudioPacket* packet = NULL; int ret = 0; int bytes_per_sample = 0; diff --git a/source/Engine/Media/Decoders/VideoDecoder.cpp b/source/Engine/Media/Decoders/VideoDecoder.cpp index 80df28ca..afd57e9d 100644 --- a/source/Engine/Media/Decoders/VideoDecoder.cpp +++ b/source/Engine/Media/Decoders/VideoDecoder.cpp @@ -1,19 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include - -class VideoDecoder : public Decoder { -public: - SwsContext* SWS; - AVFrame* ScratchFrame; - - int Width; - int Height; -}; -#endif - #include #include @@ -48,7 +32,7 @@ struct VideoPacket { }; // Lifecycle functions -PUBLIC VideoDecoder::VideoDecoder(MediaSource* src, int stream_index) { + VideoDecoder::VideoDecoder(MediaSource* src, int stream_index) { if (stream_index < 0) { Log::Print(Log::LOG_ERROR, "stream_index < 0"); return; @@ -110,7 +94,7 @@ PUBLIC VideoDecoder::VideoDecoder(MediaSource* src, int st // exit_0: return; } -PUBLIC void* VideoDecoder::CreateVideoPacket(AVFrame* frame, double pts) { +void* VideoDecoder::CreateVideoPacket(AVFrame* frame, double pts) { VideoPacket* packet = (VideoPacket*)calloc(1, sizeof(VideoPacket)); if (!packet) { Log::Print(Log::LOG_ERROR, "Something went horribly wrong. (Ran out of memory at VideoDecoder::CreateVideoPacket \"(VideoPacket*)calloc\")"); @@ -120,7 +104,7 @@ PUBLIC void* VideoDecoder::CreateVideoPacket(AVFrame* frame, dou packet->pts = pts; return packet; } -PUBLIC STATIC void VideoDecoder::FreeVideoPacket(void* p) { +void VideoDecoder::FreeVideoPacket(void* p) { VideoPacket* packet = (VideoPacket*)p; av_freep(&packet->frame->data[0]); av_frame_free(&packet->frame); @@ -128,7 +112,7 @@ PUBLIC STATIC void VideoDecoder::FreeVideoPacket(void* p) { } // Unique format info functions -PUBLIC AVPixelFormat VideoDecoder::FindAVPixelFormat(Uint32 format) { +AVPixelFormat VideoDecoder::FindAVPixelFormat(Uint32 format) { switch (format) { case SDL_PIXELFORMAT_YV12: return AV_PIX_FMT_YUV420P; case SDL_PIXELFORMAT_YUY2: return AV_PIX_FMT_YUYV422; @@ -146,7 +130,7 @@ PUBLIC AVPixelFormat VideoDecoder::FindAVPixelFormat(Uint32 format) { default: return AV_PIX_FMT_NONE; } } -PUBLIC int VideoDecoder::FindSDLPixelFormat(AVPixelFormat fmt) { +int VideoDecoder::FindSDLPixelFormat(AVPixelFormat fmt) { switch (fmt) { case AV_PIX_FMT_YUV420P: return SDL_PIXELFORMAT_YV12; @@ -164,7 +148,7 @@ PUBLIC int VideoDecoder::FindSDLPixelFormat(AVPixelFormat fmt) } // Common format info functions -PUBLIC int VideoDecoder::GetOutputFormat(OutputFormat* output) { +int VideoDecoder::GetOutputFormat(OutputFormat* output) { output->Format = Format; output->Width = Width; output->Height = Height; @@ -172,7 +156,7 @@ PUBLIC int VideoDecoder::GetOutputFormat(OutputFormat* output) } // Unique decoding functions -PUBLIC STATIC void VideoDecoder::ReadVideo(void* ptr) { +void VideoDecoder::ReadVideo(void* ptr) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) VideoDecoder* self = (VideoDecoder*)ptr; AVFrame* out_frame = NULL; @@ -213,7 +197,7 @@ PUBLIC STATIC void VideoDecoder::ReadVideo(void* ptr) { } #endif } -PUBLIC STATIC int VideoDecoder::DecodeFunction(void* ptr, AVPacket* in_packet) { +int VideoDecoder::DecodeFunction(void* ptr, AVPacket* in_packet) { if (in_packet == NULL) { return 0; } @@ -283,7 +267,7 @@ PUBLIC STATIC int VideoDecoder::DecodeFunction(void* ptr, AVPacket* i #endif return 0; } -PUBLIC STATIC void VideoDecoder::CloseFunction(void* ptr) { +void VideoDecoder::CloseFunction(void* ptr) { VideoDecoder* self = (VideoDecoder*)ptr; if (self->ScratchFrame != NULL) { av_frame_free(&self->ScratchFrame); @@ -294,14 +278,14 @@ PUBLIC STATIC void VideoDecoder::CloseFunction(void* ptr) { } // Data functions -PUBLIC double VideoDecoder::GetPTS() { +double VideoDecoder::GetPTS() { VideoPacket* packet = (VideoPacket*)PeekOutput(); if (packet == NULL) { return -1.0; } return packet->pts; } -PUBLIC int VideoDecoder::GetVideoDecoderData(Texture* texture) { +int VideoDecoder::GetVideoDecoderData(Texture* texture) { double sync_ts = 0.0; Uint32 limit_rounds = 0; VideoPacket* packet = NULL; diff --git a/source/Engine/Media/MediaPlayer.cpp b/source/Engine/Media/MediaPlayer.cpp index 7a030aab..37f1cd40 100644 --- a/source/Engine/Media/MediaPlayer.cpp +++ b/source/Engine/Media/MediaPlayer.cpp @@ -1,31 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include - -class MediaPlayer { -public: - enum { - KIT_WAITING_TO_BE_PLAYABLE = 0, ///< Playback stopped or has not started yet. - KIT_PLAYING, ///< Playback started & player is actively decoding. - KIT_PAUSED, ///< Playback paused; player is actively decoding but no new data is given out. - KIT_CLOSED, ///< Playback is stopped and player is closing. - KIT_STOPPED, - }; - - Uint32 State; - Decoder* Decoders[3]; - SDL_Thread* DecoderThread; - SDL_mutex* DecoderLock; - MediaSource* Source; - double PauseStarted; - double PausedPosition; - double SeekStarted; - Uint32 WaitState; -}; -#endif - #ifdef USING_LIBAV #include @@ -61,7 +33,7 @@ All of this is based on SDL_Kitchensink */ // Demux/decode running functions -PUBLIC STATIC int MediaPlayer::DemuxAllStreams(MediaPlayer* player) { +int MediaPlayer::DemuxAllStreams(MediaPlayer* player) { // Return 0 if stream is good but nothing else to do for now. // Return -1 if there may still work to be done. // Return 1 if there was an error or stream end. @@ -123,7 +95,7 @@ PUBLIC STATIC int MediaPlayer::DemuxAllStreams(MediaPlayer* player) { av_packet_free(&packet); return DEMUXER_KEEP_READING; } -PUBLIC STATIC int MediaPlayer::RunAllDecoders(MediaPlayer* player) { +int MediaPlayer::RunAllDecoders(MediaPlayer* player) { int got; bool has_room = true; @@ -161,7 +133,7 @@ PUBLIC STATIC int MediaPlayer::RunAllDecoders(MediaPlayer* player) { while (has_room); return DECODER_RUN_OKAY; } -PUBLIC STATIC int MediaPlayer::DecoderThreadFunc(void* ptr) { +int MediaPlayer::DecoderThreadFunc(void* ptr) { MediaPlayer* player = (MediaPlayer*)ptr; bool is_running = true; bool is_playing = true; @@ -212,7 +184,7 @@ PUBLIC STATIC int MediaPlayer::DecoderThreadFunc(void* ptr) { } // Lifecycle functions -PUBLIC STATIC MediaPlayer* MediaPlayer::Create(MediaSource* src, int video_stream_index, int audio_stream_index, int subtitle_stream_index, int screen_w, int screen_h) { +MediaPlayer* MediaPlayer::Create(MediaSource* src, int video_stream_index, int audio_stream_index, int subtitle_stream_index, int screen_w, int screen_h) { if (!src) { Log::Print(Log::LOG_ERROR, "MediaPlayer::Create: src == NULL"); exit(-1); @@ -336,7 +308,7 @@ PUBLIC STATIC MediaPlayer* MediaPlayer::Create(MediaSource* src, int video_strea exit_0: return NULL; } -PUBLIC void MediaPlayer::Close() { +void MediaPlayer::Close() { // Kill the decoder thread and mutex if (SDL_LockMutex(this->DecoderLock) == 0) { this->State = KIT_CLOSED; @@ -373,28 +345,28 @@ PUBLIC void MediaPlayer::Close() { } // Info functions -PUBLIC void MediaPlayer::SetScreenSize(int w, int h) { +void MediaPlayer::SetScreenSize(int w, int h) { // SubtitleDecoder* dec = (SubtitleDecoder*)Decoders[KIT_SUBTITLE_DEC]; // if (dec == NULL) // return; // dec->SetSize(w, h); } -PUBLIC int MediaPlayer::GetVideoStream() { +int MediaPlayer::GetVideoStream() { if (!Decoders[KIT_VIDEO_DEC]) return -1; return Decoders[KIT_VIDEO_DEC]->GetStreamIndex(); } -PUBLIC int MediaPlayer::GetAudioStream() { +int MediaPlayer::GetAudioStream() { if (!Decoders[KIT_AUDIO_DEC]) return -1; return Decoders[KIT_AUDIO_DEC]->GetStreamIndex(); } -PUBLIC int MediaPlayer::GetSubtitleStream() { +int MediaPlayer::GetSubtitleStream() { if (!Decoders[KIT_SUBTITLE_DEC]) return -1; return Decoders[KIT_SUBTITLE_DEC]->GetStreamIndex(); } -PUBLIC void MediaPlayer::GetInfo(PlayerInfo* info) { +void MediaPlayer::GetInfo(PlayerInfo* info) { if (!info) { Log::Print(Log::LOG_ERROR, "MediaPlayer::GetInfo: info == NULL"); exit(-1); @@ -427,11 +399,11 @@ PUBLIC void MediaPlayer::GetInfo(PlayerInfo* info) { } } } -PUBLIC double MediaPlayer::GetDuration() { +double MediaPlayer::GetDuration() { AVFormatContext* fmt_ctx = (AVFormatContext*)this->Source->FormatCtx; return (fmt_ctx->duration / AV_TIME_BASE); } -PUBLIC double MediaPlayer::GetPosition() { +double MediaPlayer::GetPosition() { if (State != KIT_PLAYING) return PausedPosition; @@ -445,7 +417,7 @@ PUBLIC double MediaPlayer::GetPosition() { } return 0; } -PUBLIC double MediaPlayer::GetBufferPosition() { +double MediaPlayer::GetBufferPosition() { double maxPTS = 0.0; for (int i = 0; i < KIT_DEC_COUNT; i++) { Decoder* dec = this->Decoders[i]; @@ -467,7 +439,7 @@ PUBLIC double MediaPlayer::GetBufferPosition() { } // Data functions -PUBLIC bool MediaPlayer::ManageWaiting() { +bool MediaPlayer::ManageWaiting() { if (IsOutputEmpty()) { return true; } @@ -502,7 +474,7 @@ PUBLIC bool MediaPlayer::ManageWaiting() { } return false; } -PUBLIC int MediaPlayer::GetVideoData(Texture* texture) { +int MediaPlayer::GetVideoData(Texture* texture) { Decoder* dec = (Decoder*)Decoders[KIT_VIDEO_DEC]; if (dec == NULL) { return 0; @@ -523,7 +495,7 @@ PUBLIC int MediaPlayer::GetVideoData(Texture* texture) { return ((VideoDecoder*)dec)->GetVideoDecoderData(texture); } -PUBLIC int MediaPlayer::GetVideoDataForPaused(Texture* texture) { +int MediaPlayer::GetVideoDataForPaused(Texture* texture) { Decoder* dec = (Decoder*)Decoders[KIT_VIDEO_DEC]; if (dec == NULL) { return 0; @@ -531,7 +503,7 @@ PUBLIC int MediaPlayer::GetVideoDataForPaused(Texture* texture) return ((VideoDecoder*)dec)->GetVideoDecoderData(texture); } -PUBLIC int MediaPlayer::GetAudioData(unsigned char* buffer, int length) { +int MediaPlayer::GetAudioData(unsigned char* buffer, int length) { if (!buffer) { Log::Print(Log::LOG_ERROR, "MediaPlayer::GetAudioData: buffer == NULL"); exit(-1); @@ -562,7 +534,7 @@ PUBLIC int MediaPlayer::GetAudioData(unsigned char* buffer, int return ((AudioDecoder*)dec)->GetAudioDecoderData(buffer, length); } -PUBLIC int MediaPlayer::GetSubtitleData(Texture* texture, SDL_Rect* sources, SDL_Rect* targets, int limit) { +int MediaPlayer::GetSubtitleData(Texture* texture, SDL_Rect* sources, SDL_Rect* targets, int limit) { /* // NOTE: All asserts need to be removed/replaced. assert(texture != NULL); @@ -600,21 +572,21 @@ PUBLIC int MediaPlayer::GetSubtitleData(Texture* texture, SDL_Re } // Clock functions -PUBLIC void MediaPlayer::SetClockSync() { +void MediaPlayer::SetClockSync() { double sync = MediaPlayerState::GetSystemTime(); for (int i = 0; i < KIT_DEC_COUNT; i++) { if (Decoders[i]) Decoders[i]->SetClockSync(sync); } } -PUBLIC void MediaPlayer::SetClockSyncOffset(double offset) { +void MediaPlayer::SetClockSyncOffset(double offset) { double sync = MediaPlayerState::GetSystemTime(); for (int i = 0; i < KIT_DEC_COUNT; i++) { if (Decoders[i]) Decoders[i]->SetClockSync(sync + offset); } } -PUBLIC void MediaPlayer::ChangeClockSync(double delta) { +void MediaPlayer::ChangeClockSync(double delta) { for (int i = 0; i < KIT_DEC_COUNT; i++) { if (Decoders[i]) Decoders[i]->ChangeClockSync(delta); @@ -622,7 +594,7 @@ PUBLIC void MediaPlayer::ChangeClockSync(double delta) { } // State functions -PUBLIC void MediaPlayer::Play() { +void MediaPlayer::Play() { double tmp; switch (this->State) { case KIT_WAITING_TO_BE_PLAYABLE: @@ -655,7 +627,7 @@ PUBLIC void MediaPlayer::Play() { break; } } -PUBLIC void MediaPlayer::Stop() { +void MediaPlayer::Stop() { MediaPlayer* player = this; if (SDL_LockMutex(player->DecoderLock) == 0) { switch (player->State) { @@ -675,7 +647,7 @@ PUBLIC void MediaPlayer::Stop() { SDL_UnlockMutex(player->DecoderLock); } } -PUBLIC void MediaPlayer::Pause() { +void MediaPlayer::Pause() { switch (this->State) { case KIT_WAITING_TO_BE_PLAYABLE: this->WaitState = KIT_PAUSED; @@ -687,7 +659,7 @@ PUBLIC void MediaPlayer::Pause() { this->State = KIT_PAUSED; this->PauseStarted = MediaPlayerState::GetSystemTime(); } -PUBLIC int MediaPlayer::Seek(double seek_set) { +int MediaPlayer::Seek(double seek_set) { MediaPlayer* player = this; double position; double duration = 1.0; @@ -760,12 +732,12 @@ PUBLIC int MediaPlayer::Seek(double seek_set) { return 0; } -PUBLIC Uint32 MediaPlayer::GetPlayerState() { +Uint32 MediaPlayer::GetPlayerState() { return this->State; } // Buffer checks -PUBLIC bool MediaPlayer::IsInputEmpty() { +bool MediaPlayer::IsInputEmpty() { for (int i = 0; i < KIT_DEC_COUNT; i++) { Decoder* dec = (Decoder*)this->Decoders[i]; if (dec == NULL) @@ -775,7 +747,7 @@ PUBLIC bool MediaPlayer::IsInputEmpty() { } return true; } -PUBLIC bool MediaPlayer::IsOutputEmpty() { +bool MediaPlayer::IsOutputEmpty() { for (int i = 0; i < KIT_DEC_COUNT; i++) { Decoder* dec = (Decoder*)this->Decoders[i]; if (dec == NULL) @@ -787,13 +759,13 @@ PUBLIC bool MediaPlayer::IsOutputEmpty() { } // ??? -PUBLIC STATIC Uint32 MediaPlayer::GetInputLength(MediaPlayer* player, int i) { +Uint32 MediaPlayer::GetInputLength(MediaPlayer* player, int i) { Decoder* dec = player->Decoders[i]; if (dec == NULL) return 0; return dec->GetInputLength(); } -PUBLIC STATIC Uint32 MediaPlayer::GetOutputLength(MediaPlayer* player, int i) { +Uint32 MediaPlayer::GetOutputLength(MediaPlayer* player, int i) { Decoder* dec = player->Decoders[i]; if (dec == NULL) return 0; diff --git a/source/Engine/Media/MediaSource.cpp b/source/Engine/Media/MediaSource.cpp index 939bd018..d20daf15 100644 --- a/source/Engine/Media/MediaSource.cpp +++ b/source/Engine/Media/MediaSource.cpp @@ -1,25 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class MediaSource { -public: - enum { - STREAMTYPE_UNKNOWN, - STREAMTYPE_VIDEO, - STREAMTYPE_AUDIO, - STREAMTYPE_DATA, - STREAMTYPE_SUBTITLE, - STREAMTYPE_ATTACHMENT - }; - - void* FormatCtx; - void* AvioCtx; - Stream* StreamPtr; -} -#endif - #include #include @@ -88,7 +66,7 @@ void _AVLogCallback(void *ptr, int level, const char* fmt, va_list vargs) { #endif -PUBLIC STATIC MediaSource* MediaSource::CreateSourceFromUrl(const char* url) { +MediaSource* MediaSource::CreateSourceFromUrl(const char* url) { if (!url) return NULL; @@ -122,7 +100,7 @@ PUBLIC STATIC MediaSource* MediaSource::CreateSourceFromUrl(const char* url) { return NULL; } -PUBLIC STATIC MediaSource* MediaSource::CreateSourceFromStream(Stream* stream) { +MediaSource* MediaSource::CreateSourceFromStream(Stream* stream) { #ifdef USING_LIBAV AVIOContext* avio_ctx = NULL; Uint8* avio_ctx_buffer = NULL; @@ -196,7 +174,7 @@ PUBLIC STATIC MediaSource* MediaSource::CreateSourceFromStream(Stream* stream) { return NULL; } -PUBLIC int MediaSource::GetStreamInfo(Uint32* info, int index) { +int MediaSource::GetStreamInfo(Uint32* info, int index) { if (!info) return 1; @@ -232,13 +210,13 @@ PUBLIC int MediaSource::GetStreamInfo(Uint32* info, int index) { return 0; } -PUBLIC int MediaSource::GetStreamCount() { +int MediaSource::GetStreamCount() { #ifdef USING_LIBAV return ((AVFormatContext*)FormatCtx)->nb_streams; #endif return 0; } -PUBLIC int MediaSource::GetBestStream(Uint32 type) { +int MediaSource::GetBestStream(Uint32 type) { #ifdef USING_LIBAV int avmedia_type = 0; switch (type) { @@ -260,7 +238,7 @@ PUBLIC int MediaSource::GetBestStream(Uint32 type) { return -1; } -PUBLIC void MediaSource::Close() { +void MediaSource::Close() { #ifdef USING_LIBAV AVFormatContext* format_ctx = (AVFormatContext*)this->FormatCtx; AVIOContext* avio_ctx = (AVIOContext*)this->AvioCtx; diff --git a/source/Engine/Media/Utils/MediaPlayerState.cpp b/source/Engine/Media/Utils/MediaPlayerState.cpp index c936e973..68b491ed 100644 --- a/source/Engine/Media/Utils/MediaPlayerState.cpp +++ b/source/Engine/Media/Utils/MediaPlayerState.cpp @@ -1,19 +1,3 @@ -#if INTERFACE -#include - -class MediaPlayerState { -public: - static Uint32 InitFlags; - static Uint32 ThreadCount; - static Uint32 FontHinting; - static Uint32 VideoBufFrames; - static Uint32 AudioBufFrames; - static Uint32 SubtitleBufFrames; - static void* LibassHandle; - static void* AssSharedObjectHandle; -}; -#endif - #include #include #include @@ -39,10 +23,10 @@ const char* const font_mime[] = { #ifdef USING_LIBAV -PUBLIC STATIC double MediaPlayerState::GetSystemTime() { +double MediaPlayerState::GetSystemTime() { return (double)av_gettime() / 1000000.0; } -PUBLIC STATIC bool MediaPlayerState::AttachmentIsFont(void* p) { +bool MediaPlayerState::AttachmentIsFont(void* p) { AVStream* stream = (AVStream*)p; AVDictionaryEntry *tag = av_dict_get(stream->metadata, "mimetype", NULL, AV_DICT_MATCH_CASE); if (tag) { diff --git a/source/Engine/Media/Utils/PtrBuffer.cpp b/source/Engine/Media/Utils/PtrBuffer.cpp index 00f02f17..d25406e3 100644 --- a/source/Engine/Media/Utils/PtrBuffer.cpp +++ b/source/Engine/Media/Utils/PtrBuffer.cpp @@ -1,22 +1,8 @@ -#if INTERFACE -#include -#include - -class PtrBuffer { -public: - Uint32 ReadPtr; - Uint32 WritePtr; - Uint32 Size; - void** Data; - void (*FreeFunc)(void*); -}; -#endif - #include #include -PUBLIC PtrBuffer::PtrBuffer(Uint32 size, void (*freeFunc)(void*)) { +PtrBuffer::PtrBuffer(Uint32 size, void (*freeFunc)(void*)) { this->ReadPtr = 0; this->WritePtr = 0; this->Size = size; @@ -28,15 +14,15 @@ PUBLIC PtrBuffer::PtrBuffer(Uint32 size, void (*freeFunc)(void*)) { exit(-1); } } -PUBLIC PtrBuffer::~PtrBuffer() { +PtrBuffer::~PtrBuffer() { Clear(); free(this->Data); } -PUBLIC Uint32 PtrBuffer::GetLength() { +Uint32 PtrBuffer::GetLength() { return this->WritePtr - this->ReadPtr; } -PUBLIC void PtrBuffer::Clear() { +void PtrBuffer::Clear() { if (FreeFunc == NULL) return; @@ -45,7 +31,7 @@ PUBLIC void PtrBuffer::Clear() { FreeFunc(data); } } -PUBLIC void* PtrBuffer::Read() { +void* PtrBuffer::Read() { if (ReadPtr < WritePtr) { void* out = Data[ReadPtr % Size]; Data[ReadPtr % Size] = NULL; @@ -58,13 +44,13 @@ PUBLIC void* PtrBuffer::Read() { } return NULL; } -PUBLIC void* PtrBuffer::Peek() { +void* PtrBuffer::Peek() { if (ReadPtr < WritePtr) { return Data[ReadPtr % Size]; } return NULL; } -PUBLIC void PtrBuffer::Advance() { +void PtrBuffer::Advance() { if (ReadPtr < WritePtr) { Data[ReadPtr % Size] = NULL; ReadPtr++; @@ -74,7 +60,7 @@ PUBLIC void PtrBuffer::Advance() { } } } -PUBLIC int PtrBuffer::Write(void* ptr) { +int PtrBuffer::Write(void* ptr) { if (!ptr) { Log::Print(Log::LOG_ERROR, "PtrBuffer::Write: ptr == NULL"); exit(-1); @@ -87,7 +73,7 @@ PUBLIC int PtrBuffer::Write(void* ptr) { } return 1; } -PUBLIC void PtrBuffer::ForEachItemInBuffer(void (*callback)(void*, void*), void* userdata) { +void PtrBuffer::ForEachItemInBuffer(void (*callback)(void*, void*), void* userdata) { Uint32 read_p = ReadPtr; Uint32 write_p = WritePtr; while (read_p < write_p) { @@ -98,7 +84,7 @@ PUBLIC void PtrBuffer::ForEachItemInBuffer(void (*callback)(void*, void*), voi } } } -PUBLIC void PtrBuffer::WithEachItemInBuffer(std::function callback, void* userdata) { +void PtrBuffer::WithEachItemInBuffer(std::function callback, void* userdata) { Uint32 read_p = ReadPtr; Uint32 write_p = WritePtr; while (read_p < write_p) { @@ -109,7 +95,7 @@ PUBLIC void PtrBuffer::WithEachItemInBuffer(std::function } } } -PUBLIC int PtrBuffer::IsFull() { +int PtrBuffer::IsFull() { int len = WritePtr - ReadPtr; int k = (len >= (int)Size); return k; diff --git a/source/Engine/Media/Utils/RingBuffer.cpp b/source/Engine/Media/Utils/RingBuffer.cpp index b7850f96..6952add4 100644 --- a/source/Engine/Media/Utils/RingBuffer.cpp +++ b/source/Engine/Media/Utils/RingBuffer.cpp @@ -1,21 +1,8 @@ -#if INTERFACE -#include - -class RingBuffer { -public: - int Size; - int Length; - int WritePos; - int ReadPos; - char* Data; -}; -#endif - #include #include -PUBLIC RingBuffer::RingBuffer(Uint32 size) { +RingBuffer::RingBuffer(Uint32 size) { this->Length = 0; this->WritePos = 0; this->ReadPos = 0; @@ -27,10 +14,10 @@ PUBLIC RingBuffer::RingBuffer(Uint32 size) { exit(-1); } } -PUBLIC RingBuffer::~RingBuffer() { +RingBuffer::~RingBuffer() { free(this->Data); } -PUBLIC int RingBuffer::Write(const char* data, int len) { +int RingBuffer::Write(const char* data, int len) { int k; len = (len > (this->Size - this->Length)) ? (this->Size - this->Length) : len; if (this->Length < this->Size) { @@ -52,7 +39,7 @@ PUBLIC int RingBuffer::Write(const char* data, int len) { return 0; } -PUBLIC void RingBuffer::ReadData(char* data, const int len) { +void RingBuffer::ReadData(char* data, const int len) { int k; if (len + this->ReadPos > this->Size) { k = (len + this->ReadPos) % this->Size; @@ -63,7 +50,7 @@ PUBLIC void RingBuffer::ReadData(char* data, const int len) { memcpy(data, this->Data + this->ReadPos, len); } } -PUBLIC int RingBuffer::Read(char* data, int len) { +int RingBuffer::Read(char* data, int len) { len = (len > this->Length) ? this->Length : len; if (this->Length > 0) { ReadData(data, len); @@ -76,7 +63,7 @@ PUBLIC int RingBuffer::Read(char* data, int len) { } return 0; } -PUBLIC int RingBuffer::Peek(char *data, int len) { +int RingBuffer::Peek(char *data, int len) { len = (len > this->Length) ? this->Length : len; if (this->Length > 0) { ReadData(data, len); @@ -84,7 +71,7 @@ PUBLIC int RingBuffer::Peek(char *data, int len) { } return 0; } -PUBLIC int RingBuffer::Advance(int len) { +int RingBuffer::Advance(int len) { len = (len > this->Length) ? this->Length : len; if (this->Length > 0) { this->Length -= len; @@ -96,12 +83,12 @@ PUBLIC int RingBuffer::Advance(int len) { } return 0; } -PUBLIC int RingBuffer::GetLength() { +int RingBuffer::GetLength() { return this->Length; } -PUBLIC int RingBuffer::GetSize() { +int RingBuffer::GetSize() { return this->Size; } -PUBLIC int RingBuffer::GetFree() { +int RingBuffer::GetFree() { return this->Size - this->Length; } diff --git a/source/Engine/Network/HTTP.cpp b/source/Engine/Network/HTTP.cpp index 8ea55f53..6a93cb9c 100644 --- a/source/Engine/Network/HTTP.cpp +++ b/source/Engine/Network/HTTP.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class HTTP { -public: - -}; -#endif - #include #include @@ -109,7 +98,7 @@ int _GET_FromThread(void* op) { #endif -PUBLIC STATIC bool HTTP::GET(const char* url, Uint8** outBuf, size_t* outLen, ObjBoundMethod* callback) { +bool HTTP::GET(const char* url, Uint8** outBuf, size_t* outLen, ObjBoundMethod* callback) { #ifdef USING_CURL if (!curl) { diff --git a/source/Engine/Network/WebSocketClient.cpp b/source/Engine/Network/WebSocketClient.cpp index 07bfdf1e..98493333 100644 --- a/source/Engine/Network/WebSocketClient.cpp +++ b/source/Engine/Network/WebSocketClient.cpp @@ -1,29 +1,3 @@ -#if INTERFACE -#include -#include - -#include - -class WebSocketClient { -public: - enum { - CLOSING = 0, - CLOSED = 1, - CONNECTING = 2, - OPEN = 3, - }; - - std::vector rxbuf; - std::vector txbuf; - std::vector receivedData; - - socket_t socket; - int readyState; - bool useMask; - bool isRxBad; -}; -#endif - #include const char* BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -239,7 +213,7 @@ size_t socket_send_string(socket_t sockfd, const char* str, ...) { // easywsclient -PUBLIC STATIC WebSocketClient* WebSocketClient::New(const char* url) { +WebSocketClient* WebSocketClient::New(const char* url) { #ifdef _WIN32 INT rc; WSADATA wsaData; @@ -358,7 +332,7 @@ PUBLIC STATIC WebSocketClient* WebSocketClient::New(const char* url) { delete socket; return NULL; } -PUBLIC void WebSocketClient::Poll(int timeout) { +void WebSocketClient::Poll(int timeout) { if (readyState == WebSocketClient::CLOSED) { if (timeout > 0) { timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; @@ -426,7 +400,7 @@ PUBLIC void WebSocketClient::Poll(int timeout) { printf("readyState = CLOSED 2\n"); } } -PUBLIC void WebSocketClient::Dispatch(void(*callback)(void* mem, size_t size)) { +void WebSocketClient::Dispatch(void(*callback)(void* mem, size_t size)) { // TODO: consider acquiring a lock on rxbuf... if (isRxBad) { printf("bad rx\n"); @@ -541,7 +515,7 @@ PUBLIC void WebSocketClient::Dispatch(void(*callback)(void* m } } -PUBLIC size_t WebSocketClient::BytesToRead() { +size_t WebSocketClient::BytesToRead() { if (readyState == WebSocketClient::CLOSED || readyState == WebSocketClient::CLOSING) return 0; @@ -661,27 +635,27 @@ PUBLIC size_t WebSocketClient::BytesToRead() { } return 0; } -PUBLIC size_t WebSocketClient::ReadBytes(void* data, size_t n) { +size_t WebSocketClient::ReadBytes(void* data, size_t n) { memcpy(data, receivedData.data(), n); receivedData.erase(receivedData.begin(), receivedData.begin() + n); return n; } -PUBLIC Uint32 WebSocketClient::ReadUint32() { +Uint32 WebSocketClient::ReadUint32() { Uint32 data; ReadBytes(&data, sizeof(data)); return data; } -PUBLIC Sint32 WebSocketClient::ReadSint32() { +Sint32 WebSocketClient::ReadSint32() { Sint32 data; ReadBytes(&data, sizeof(data)); return data; } -PUBLIC float WebSocketClient::ReadFloat() { +float WebSocketClient::ReadFloat() { float data; ReadBytes(&data, sizeof(data)); return data; } -PUBLIC char* WebSocketClient::ReadString() { +char* WebSocketClient::ReadString() { char* data = (char*)receivedData.data(); char* dataStart = data; char* dataEnd = data + receivedData.size(); @@ -698,7 +672,7 @@ PUBLIC char* WebSocketClient::ReadString() { return output; } -PUBLIC void WebSocketClient::SendData(int type, const void* message, int64_t message_size) { +void WebSocketClient::SendData(int type, const void* message, int64_t message_size) { // TODO: // Masking key should (must) be derived from a high quality random // number generator, to mitigate attacks on non-WebSocketClient friendly @@ -759,13 +733,13 @@ PUBLIC void WebSocketClient::SendData(int type, const void* m } } } -PUBLIC void WebSocketClient::SendBinary(const void* message, int64_t message_size) { +void WebSocketClient::SendBinary(const void* message, int64_t message_size) { SendData(opcode_type::BINARY_FRAME, message, message_size); } -PUBLIC void WebSocketClient::SendText(const char* message) { +void WebSocketClient::SendText(const char* message) { SendData(opcode_type::TEXT_FRAME, message, (int64_t)strlen(message)); } -PUBLIC void WebSocketClient::Close() { +void WebSocketClient::Close() { if (readyState == WebSocketClient::CLOSING || readyState == WebSocketClient::CLOSED) return; diff --git a/source/Engine/Rendering/D3D/D3DRenderer.cpp b/source/Engine/Rendering/D3D/D3DRenderer.cpp index 40347700..1418b368 100644 --- a/source/Engine/Rendering/D3D/D3DRenderer.cpp +++ b/source/Engine/Rendering/D3D/D3DRenderer.cpp @@ -1,17 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include - -#include - -class D3DRenderer { -public: -}; -#endif - #ifdef USING_DIRECT3D #include @@ -669,7 +655,7 @@ void D3D_EndDrawShape(Vertex* shapeBuffer, D3DPRIMITIVETYPE prim, int tri } // Initialization and disposal functions -PUBLIC STATIC void D3DRenderer::Init() { +void D3DRenderer::Init() { Graphics::PreferredPixelFormat = SDL_PIXELFORMAT_ARGB8888; D3D_MatrixIdentity = Matrix4x4::Create(); @@ -836,13 +822,13 @@ PUBLIC STATIC void D3DRenderer::Init() { Log::Print(Log::LOG_INFO, "Graphics Card: %s", indent.Description); } -PUBLIC STATIC Uint32 D3DRenderer::GetWindowFlags() { +Uint32 D3DRenderer::GetWindowFlags() { return 0; } -PUBLIC STATIC void D3DRenderer::SetVSync(bool enabled) { +void D3DRenderer::SetVSync(bool enabled) { } -PUBLIC STATIC void D3DRenderer::SetGraphicsFunctions() { +void D3DRenderer::SetGraphicsFunctions() { Graphics::PixelOffset = 0.5f; Graphics::Internal.Init = D3DRenderer::Init; @@ -912,7 +898,7 @@ PUBLIC STATIC void D3DRenderer::SetGraphicsFunctions() { Graphics::Internal.ClearScene3D = D3DRenderer::ClearScene3D; Graphics::Internal.DrawScene3D = D3DRenderer::DrawScene3D; } -PUBLIC STATIC void D3DRenderer::Dispose() { +void D3DRenderer::Dispose() { Memory::Free(D3D_BufferCircleFill); Memory::Free(D3D_BufferCircleStroke); Memory::Free(D3D_BufferSquareFill); @@ -924,7 +910,7 @@ PUBLIC STATIC void D3DRenderer::Dispose() { } // Texture management functions -PUBLIC STATIC Texture* D3DRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* D3DRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture = Texture::New(format, access, width, height); D3D_CreateTexture(texture); @@ -934,10 +920,10 @@ PUBLIC STATIC Texture* D3DRenderer::CreateTexture(Uint32 format, Uint32 access, return texture; } -PUBLIC STATIC int D3DRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { +int D3DRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { return 0; } -PUBLIC STATIC int D3DRenderer::UpdateTexture(Texture* texture, SDL_Rect* r, void* pixels, int pitch) { +int D3DRenderer::UpdateTexture(Texture* texture, SDL_Rect* r, void* pixels, int pitch) { int inputPixelsX = 0; int inputPixelsY = 0; int inputPixelsW = texture->Width; @@ -1011,10 +997,10 @@ PUBLIC STATIC int D3DRenderer::UpdateTexture(Texture* texture, SDL_Rect* r, return 0; } -PUBLIC STATIC void D3DRenderer::UnlockTexture(Texture* texture) { +void D3DRenderer::UnlockTexture(Texture* texture) { } -PUBLIC STATIC void D3DRenderer::DisposeTexture(Texture* texture) { +void D3DRenderer::DisposeTexture(Texture* texture) { D3D_TextureData* textureData = (D3D_TextureData*)texture->DriverData; if (!textureData) return; @@ -1035,15 +1021,15 @@ PUBLIC STATIC void D3DRenderer::DisposeTexture(Texture* texture) { } // Viewport and view-related functions -PUBLIC STATIC void D3DRenderer::SetRenderTarget(Texture* texture) { +void D3DRenderer::SetRenderTarget(Texture* texture) { D3D_Predraw(); D3D_SetRenderTarget(texture); } -PUBLIC STATIC void D3DRenderer::UpdateWindowSize(int width, int height) { +void D3DRenderer::UpdateWindowSize(int width, int height) { // D3D_UpdateViewport(0, 0, width, height); renderData->UpdateBackBufferSize = true; } -PUBLIC STATIC void D3DRenderer::UpdateViewport() { +void D3DRenderer::UpdateViewport() { Viewport* vp = &Graphics::CurrentViewport; D3DVIEWPORT9 viewport; @@ -1059,7 +1045,7 @@ PUBLIC STATIC void D3DRenderer::UpdateViewport() { // D3DRenderer::UpdateOrtho(vp->Width, vp->Height); D3DRenderer::UpdateProjectionMatrix(); } -PUBLIC STATIC void D3DRenderer::UpdateClipRect() { +void D3DRenderer::UpdateClipRect() { ClipArea clip = Graphics::CurrentClip; if (Graphics::CurrentClip.Enabled) { Viewport view = Graphics::CurrentViewport; @@ -1089,7 +1075,7 @@ PUBLIC STATIC void D3DRenderer::UpdateClipRect() { IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SCISSORTESTENABLE, FALSE); } } -PUBLIC STATIC void D3DRenderer::UpdateOrtho(float left, float top, float right, float bottom) { +void D3DRenderer::UpdateOrtho(float left, float top, float right, float bottom) { if (Scene::Views[Scene::ViewCurrent].Software) Matrix4x4::Ortho(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, left, right, bottom, top, 500.0f, -500.0f); else @@ -1101,27 +1087,27 @@ PUBLIC STATIC void D3DRenderer::UpdateOrtho(float left, float top, float rig D3D_RenderScaleY = Graphics::CurrentViewport.Height / top; } } -PUBLIC STATIC void D3DRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { +void D3DRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { MakePerspectiveMatrix(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, fovy, nearv, farv, aspect); Matrix4x4::Copy(Scene::Views[Scene::ViewCurrent].ProjectionMatrix, Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix); } -PUBLIC STATIC void D3DRenderer::UpdateProjectionMatrix() { +void D3DRenderer::UpdateProjectionMatrix() { D3DMATRIX matrix; memcpy(&matrix.m, Scene::Views[Scene::ViewCurrent].ProjectionMatrix->Values, sizeof(float) * 16); IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_PROJECTION, &matrix); } -PUBLIC STATIC void D3DRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { +void D3DRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { Matrix4x4::Perspective(out, fov, aspect, near, far); } // Shader-related functions -PUBLIC STATIC void D3DRenderer::UseShader(void* shader) { +void D3DRenderer::UseShader(void* shader) { // if (D3D_CurrentShader != (D3DShader*)shader) { // D3D_CurrentShader = (D3DShader*)shader; // D3D_CurrentShader->Use(); // } } -PUBLIC STATIC void D3DRenderer::SetUniformF(int location, int count, float* values) { +void D3DRenderer::SetUniformF(int location, int count, float* values) { // switch (count) { // case 1: glUniform1f(location, values[0]); CHECK_GL(); break; // case 2: glUniform2f(location, values[0], values[1]); CHECK_GL(); break; @@ -1129,15 +1115,15 @@ PUBLIC STATIC void D3DRenderer::SetUniformF(int location, int count, float* // case 4: glUniform4f(location, values[0], values[1], values[2], values[3]); CHECK_GL(); break; // } } -PUBLIC STATIC void D3DRenderer::SetUniformI(int location, int count, int* values) { +void D3DRenderer::SetUniformI(int location, int count, int* values) { // glUniform1iv(location, count, values); } -PUBLIC STATIC void D3DRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { +void D3DRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { } // These guys -PUBLIC STATIC void D3DRenderer::Clear() { +void D3DRenderer::Clear() { DWORD color; HRESULT result; int BackBufferWidth, BackBufferHeight; @@ -1201,7 +1187,7 @@ PUBLIC STATIC void D3DRenderer::Clear() { D3D_SetError("Clear()", result); } } -PUBLIC STATIC void D3DRenderer::Present() { +void D3DRenderer::Present() { HRESULT result; if (!renderData->BeginScene) { @@ -1226,34 +1212,34 @@ PUBLIC STATIC void D3DRenderer::Present() { } // Draw mode setting functions -PUBLIC STATIC void D3DRenderer::SetBlendColor(float r, float g, float b, float a) { +void D3DRenderer::SetBlendColor(float r, float g, float b, float a) { int ha = (int)(a * 0xFF) << 24; int hr = (int)(r * 0xFF) << 16; int hg = (int)(g * 0xFF) << 8; int hb = (int)(b * 0xFF); D3D_BlendColorsAsHex = ha | hr | hg | hb; } -PUBLIC STATIC void D3DRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { +void D3DRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { D3D_Blend_SRC_COLOR = D3D_GetBlendFactorFromHatch(srcC); D3D_Blend_DST_COLOR = D3D_GetBlendFactorFromHatch(dstC); D3D_Blend_SRC_ALPHA = D3D_GetBlendFactorFromHatch(srcA); D3D_Blend_DST_ALPHA = D3D_GetBlendFactorFromHatch(dstA); } -PUBLIC STATIC void D3DRenderer::SetTintColor(float r, float g, float b, float a) { +void D3DRenderer::SetTintColor(float r, float g, float b, float a) { } -PUBLIC STATIC void D3DRenderer::SetTintMode(int mode) { +void D3DRenderer::SetTintMode(int mode) { } -PUBLIC STATIC void D3DRenderer::SetTintEnabled(bool enabled) { +void D3DRenderer::SetTintEnabled(bool enabled) { } -PUBLIC STATIC void D3DRenderer::SetLineWidth(float n) { +void D3DRenderer::SetLineWidth(float n) { } // Primitive drawing functions -PUBLIC STATIC void D3DRenderer::StrokeLine(float x1, float y1, float x2, float y2) { +void D3DRenderer::StrokeLine(float x1, float y1, float x2, float y2) { // UseShader(D3D_SelectedShader ? D3D_SelectedShader : D3D_ShaderShape); Graphics::Save(); @@ -1268,7 +1254,7 @@ PUBLIC STATIC void D3DRenderer::StrokeLine(float x1, float y1, float x2, flo // glDrawArrays(GL_LINES, 0, 2); Graphics::Restore(); } -PUBLIC STATIC void D3DRenderer::StrokeCircle(float x, float y, float rad, float thickness) { +void D3DRenderer::StrokeCircle(float x, float y, float rad, float thickness) { D3D_BeginDrawShape(D3D_BufferCircleStroke, 361); Graphics::Save(); @@ -1281,7 +1267,7 @@ PUBLIC STATIC void D3DRenderer::StrokeCircle(float x, float y, float rad, fl D3D_EndDrawShape(D3D_BufferCircleStroke, D3DPT_LINESTRIP, 360); } -PUBLIC STATIC void D3DRenderer::StrokeEllipse(float x, float y, float w, float h) { +void D3DRenderer::StrokeEllipse(float x, float y, float w, float h) { // UseShader(D3D_SelectedShader ? D3D_SelectedShader : D3D_ShaderShape); Graphics::Save(); @@ -1294,14 +1280,14 @@ PUBLIC STATIC void D3DRenderer::StrokeEllipse(float x, float y, float w, flo // glDrawArrays(GL_LINE_STRIP, 0, 361); Graphics::Restore(); } -PUBLIC STATIC void D3DRenderer::StrokeRectangle(float x, float y, float w, float h) { +void D3DRenderer::StrokeRectangle(float x, float y, float w, float h) { StrokeLine(x, y, x + w, y); StrokeLine(x, y + h, x + w, y + h); StrokeLine(x, y, x, y + h); StrokeLine(x + w, y, x + w, y + h); } -PUBLIC STATIC void D3DRenderer::FillCircle(float x, float y, float rad) { +void D3DRenderer::FillCircle(float x, float y, float rad) { D3D_BeginDrawShape(D3D_BufferCircleFill, 362); Graphics::Save(); @@ -1314,7 +1300,7 @@ PUBLIC STATIC void D3DRenderer::FillCircle(float x, float y, float rad) { D3D_EndDrawShape(D3D_BufferCircleFill, D3DPT_TRIANGLEFAN, 360); } -PUBLIC STATIC void D3DRenderer::FillEllipse(float x, float y, float w, float h) { +void D3DRenderer::FillEllipse(float x, float y, float w, float h) { D3D_BeginDrawShape(D3D_BufferCircleFill, 362); w *= 0.5f; @@ -1330,7 +1316,7 @@ PUBLIC STATIC void D3DRenderer::FillEllipse(float x, float y, float w, float D3D_EndDrawShape(D3D_BufferCircleFill, D3DPT_TRIANGLEFAN, 360); } -PUBLIC STATIC void D3DRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void D3DRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { Vertex vertices[3]; vertices[0] = Vertex { x1, y1, 0.0f, D3D_BlendColorsAsHex, 0.0f, 0.0f }; vertices[1] = Vertex { x2, y2, 0.0f, D3D_BlendColorsAsHex, 0.0f, 0.0f }; @@ -1344,7 +1330,7 @@ PUBLIC STATIC void D3DRenderer::FillTriangle(float x1, float y1, float x2, f D3D_EndDrawShape(vertices, D3DPT_TRIANGLEFAN, 1); } -PUBLIC STATIC void D3DRenderer::FillRectangle(float x, float y, float w, float h) { +void D3DRenderer::FillRectangle(float x, float y, float w, float h) { D3D_BeginDrawShape(D3D_BufferSquareFill, 4); Graphics::Save(); @@ -1359,13 +1345,13 @@ PUBLIC STATIC void D3DRenderer::FillRectangle(float x, float y, float w, flo } // Texture drawing functions -PUBLIC STATIC void D3DRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { +void D3DRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { // UseShader(D3D_SelectedShader ? D3D_SelectedShader : D3D_ShaderTexturedShape); if (sx < 0) sx = 0.0, sy = 0.0, sw = texture->Width, sh = texture->Height; D3D_DrawTextureRaw(texture, sx, sy, sw, sh, x, y, w, h, false, texture->Access != SDL_TEXTUREACCESS_TARGET); } -PUBLIC STATIC void D3DRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void D3DRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; AnimFrame animframe = sprite->Animations[animation].Frames[frame]; @@ -1381,7 +1367,7 @@ PUBLIC STATIC void D3DRenderer::DrawSprite(ISprite* sprite, int animation, i D3D_DrawTextureRaw(sprite->Spritesheets[animframe.SheetNumber], animframe.X, animframe.Y, animframe.Width, animframe.Height, animframe.OffsetX, animframe.OffsetY, animframe.Width, animframe.Height, flipX, flipY); Graphics::Restore(); } -PUBLIC STATIC void D3DRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void D3DRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; AnimFrame animframe = sprite->Animations[animation].Frames[frame]; @@ -1410,40 +1396,40 @@ PUBLIC STATIC void D3DRenderer::DrawSpritePart(ISprite* sprite, int animatio Graphics::Restore(); } // 3D drawing functions -PUBLIC STATIC void D3DRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void D3DRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { } -PUBLIC STATIC void D3DRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void D3DRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { } -PUBLIC STATIC void D3DRenderer::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void D3DRenderer::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { } -PUBLIC STATIC void D3DRenderer::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void D3DRenderer::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { } -PUBLIC STATIC void D3DRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void D3DRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { } -PUBLIC STATIC void D3DRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { +void D3DRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { } -PUBLIC STATIC void D3DRenderer::UnbindVertexBuffer() { +void D3DRenderer::UnbindVertexBuffer() { } -PUBLIC STATIC void D3DRenderer::BindScene3D(Uint32 sceneIndex) { +void D3DRenderer::BindScene3D(Uint32 sceneIndex) { } -PUBLIC STATIC void D3DRenderer::ClearScene3D(Uint32 sceneIndex) { +void D3DRenderer::ClearScene3D(Uint32 sceneIndex) { } -PUBLIC STATIC void D3DRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { +void D3DRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { } /* // Draw buffering -PUBLIC STATIC Uint32 D3DRenderer::CreateTexturedShapeBuffer(float** data, int vertexCount) { +Uint32 D3DRenderer::CreateTexturedShapeBuffer(float** data, int vertexCount) { // x, y, z, u, v Uint32 bufferID; glGenBuffers(1, &bufferID); @@ -1455,7 +1441,7 @@ PUBLIC STATIC Uint32 D3DRenderer::CreateTexturedShapeBuffer(float** data, int return bufferID; } -PUBLIC STATIC void D3DRenderer::DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount) { +void D3DRenderer::DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount) { UseShader(D3D_SelectedShader ? D3D_SelectedShader : D3D_ShaderTexturedShape); GLTextureData* textureData = (GLTextureData*)texture->DriverData; diff --git a/source/Engine/Rendering/FaceInfo.cpp b/source/Engine/Rendering/FaceInfo.cpp index 306b2e95..3a14be5c 100644 --- a/source/Engine/Rendering/FaceInfo.cpp +++ b/source/Engine/Rendering/FaceInfo.cpp @@ -1,25 +1,6 @@ -#if INTERFACE -#include -#include -#include -#include - -class FaceInfo { -public: - Uint32 DrawMode; - Uint32 NumVertices; - Uint32 VerticesStartIndex; - bool UseMaterial; - FaceMaterial MaterialInfo; - BlendState Blend; - Uint8 CullMode; - int Depth; -}; -#endif - #include -PUBLIC void FaceInfo::SetMaterial(Material* material) { +void FaceInfo::SetMaterial(Material* material) { if (!material) { UseMaterial = false; return; @@ -39,7 +20,7 @@ PUBLIC void FaceInfo::SetMaterial(Material* material) { } } -PUBLIC void FaceInfo::SetMaterial(Texture* texture) { +void FaceInfo::SetMaterial(Texture* texture) { if (!texture) { UseMaterial = false; return; @@ -55,6 +36,6 @@ PUBLIC void FaceInfo::SetMaterial(Texture* texture) { } } -PUBLIC void FaceInfo::SetBlendState(BlendState blendState) { +void FaceInfo::SetBlendState(BlendState blendState) { Blend = blendState; } diff --git a/source/Engine/Rendering/GL/GLRenderer.cpp b/source/Engine/Rendering/GL/GLRenderer.cpp index d3978cc5..28d2994a 100644 --- a/source/Engine/Rendering/GL/GLRenderer.cpp +++ b/source/Engine/Rendering/GL/GLRenderer.cpp @@ -1,35 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class GLRenderer { -public: - static SDL_GLContext Context; - static GLShader* CurrentShader; - - static GLShaderContainer* ShaderShape; - static GLShaderContainer* ShaderShape3D; - static GLShaderContainer* ShaderFogLinear; - static GLShaderContainer* ShaderFogExp; - static GLShaderContainer* ShaderYUV; - - static GLint DefaultFramebuffer; - static GLint DefaultRenderbuffer; - - static GLuint BufferCircleFill; - static GLuint BufferCircleStroke; - static GLuint BufferSquareFill; -}; -#endif - #ifdef USING_OPENGL // #define HAVE_GL_PERFSTATS @@ -912,7 +880,7 @@ PolygonRenderer* GL_GetPolygonRenderer() { } // Initialization and disposal functions -PUBLIC STATIC void GLRenderer::Init() { +void GLRenderer::Init() { Graphics::SupportsBatching = true; Graphics::PreferredPixelFormat = SDL_PIXELFORMAT_ABGR8888; @@ -1031,7 +999,7 @@ PUBLIC STATIC void GLRenderer::Init() { glClearColor(0.0, 0.0, 0.0, 0.0); CHECK_GL(); } -PUBLIC STATIC Uint32 GLRenderer::GetWindowFlags() { +Uint32 GLRenderer::GetWindowFlags() { #ifdef GL_SUPPORTS_MULTISAMPLING if (Graphics::MultisamplingEnabled) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); CHECK_GL(); @@ -1041,7 +1009,7 @@ PUBLIC STATIC Uint32 GLRenderer::GetWindowFlags() { return SDL_WINDOW_OPENGL; } -PUBLIC STATIC void GLRenderer::SetVSync(bool enabled) { +void GLRenderer::SetVSync(bool enabled) { if (enabled) { if (SDL_GL_SetSwapInterval(-1) < 0) { CHECK_GL(); @@ -1058,7 +1026,7 @@ PUBLIC STATIC void GLRenderer::SetVSync(bool enabled) { } Graphics::VsyncEnabled = enabled; } -PUBLIC STATIC void GLRenderer::SetGraphicsFunctions() { +void GLRenderer::SetGraphicsFunctions() { Graphics::PixelOffset = 0.0f; Graphics::Internal.Init = GLRenderer::Init; @@ -1139,7 +1107,7 @@ PUBLIC STATIC void GLRenderer::SetGraphicsFunctions() { Graphics::Internal.SetDepthTesting = GLRenderer::SetDepthTesting; } -PUBLIC STATIC void GLRenderer::Dispose() { +void GLRenderer::Dispose() { glDeleteBuffers(1, &BufferCircleFill); CHECK_GL(); glDeleteBuffers(1, &BufferCircleStroke); CHECK_GL(); glDeleteBuffers(1, &BufferSquareFill); CHECK_GL(); @@ -1154,7 +1122,7 @@ PUBLIC STATIC void GLRenderer::Dispose() { } // Texture management functions -PUBLIC STATIC Texture* GLRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* GLRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture = Texture::New(format, access, width, height); texture->DriverData = Memory::TrackedCalloc("Texture::DriverData", 1, sizeof(GL_TextureData)); @@ -1277,10 +1245,10 @@ PUBLIC STATIC Texture* GLRenderer::CreateTexture(Uint32 format, Uint32 access, U return texture; } -PUBLIC STATIC int GLRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { +int GLRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { return 0; } -PUBLIC STATIC int GLRenderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { +int GLRenderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { Uint32 inputPixelsX = 0; Uint32 inputPixelsY = 0; Uint32 inputPixelsW = texture->Width; @@ -1311,7 +1279,7 @@ PUBLIC STATIC int GLRenderer::UpdateTexture(Texture* texture, SDL_Rect* src textureData->PixelDataFormat, textureData->PixelDataType, pixels); CHECK_GL(); return 0; } -PUBLIC STATIC int GLRenderer::UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV) { +int GLRenderer::UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV) { int inputPixelsX = 0; int inputPixelsY = 0; int inputPixelsW = texture->Width; @@ -1348,10 +1316,10 @@ PUBLIC STATIC int GLRenderer::UpdateTextureYUV(Texture* texture, SDL_Rect* textureData->PixelDataFormat, textureData->PixelDataType, pixelsV); CHECK_GL(); return 0; } -PUBLIC STATIC void GLRenderer::UnlockTexture(Texture* texture) { +void GLRenderer::UnlockTexture(Texture* texture) { } -PUBLIC STATIC void GLRenderer::DisposeTexture(Texture* texture) { +void GLRenderer::DisposeTexture(Texture* texture) { GL_TextureData* textureData = (GL_TextureData*)texture->DriverData; if (!textureData) return; @@ -1376,7 +1344,7 @@ PUBLIC STATIC void GLRenderer::DisposeTexture(Texture* texture) { } // Viewport and view-related functions -PUBLIC STATIC void GLRenderer::SetRenderTarget(Texture* texture) { +void GLRenderer::SetRenderTarget(Texture* texture) { if (texture == NULL) { glBindFramebuffer(GL_FRAMEBUFFER, DefaultFramebuffer); CHECK_GL(); @@ -1405,7 +1373,7 @@ PUBLIC STATIC void GLRenderer::SetRenderTarget(Texture* texture) { CHECK_GL(); } } -PUBLIC STATIC void GLRenderer::ReadFramebuffer(void* pixels, int width, int height) { +void GLRenderer::ReadFramebuffer(void* pixels, int width, int height) { glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); if (Graphics::CurrentRenderTarget) @@ -1423,10 +1391,10 @@ PUBLIC STATIC void GLRenderer::ReadFramebuffer(void* pixels, int width, int delete[] temp; } -PUBLIC STATIC void GLRenderer::UpdateWindowSize(int width, int height) { +void GLRenderer::UpdateWindowSize(int width, int height) { GLRenderer::UpdateViewport(); } -PUBLIC STATIC void GLRenderer::UpdateViewport() { +void GLRenderer::UpdateViewport() { Viewport* vp = &Graphics::CurrentViewport; if (Graphics::CurrentRenderTarget) { glViewport(vp->X * RetinaScale, vp->Y * RetinaScale, vp->Width * RetinaScale, vp->Height * RetinaScale); CHECK_GL(); @@ -1440,7 +1408,7 @@ PUBLIC STATIC void GLRenderer::UpdateViewport() { // GLRenderer::UpdateOrtho(vp->Width, vp->Height); GLRenderer::UpdateProjectionMatrix(); } -PUBLIC STATIC void GLRenderer::UpdateClipRect() { +void GLRenderer::UpdateClipRect() { ClipArea clip = Graphics::CurrentClip; if (Graphics::CurrentClip.Enabled) { Viewport view = Graphics::CurrentViewport; @@ -1465,7 +1433,7 @@ PUBLIC STATIC void GLRenderer::UpdateClipRect() { glDisable(GL_SCISSOR_TEST); CHECK_GL(); } } -PUBLIC STATIC void GLRenderer::UpdateOrtho(float left, float top, float right, float bottom) { +void GLRenderer::UpdateOrtho(float left, float top, float right, float bottom) { // if (Graphics::CurrentRenderTarget) // Matrix4x4::Ortho(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, left, right, bottom, top, -500.0f, 500.0f); // else @@ -1473,14 +1441,14 @@ PUBLIC STATIC void GLRenderer::UpdateOrtho(float left, float top, float righ Matrix4x4::Copy(Scene::Views[Scene::ViewCurrent].ProjectionMatrix, Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix); } -PUBLIC STATIC void GLRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { +void GLRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { MakePerspectiveMatrix(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, fovy, nearv, farv, aspect); Matrix4x4::Copy(Scene::Views[Scene::ViewCurrent].ProjectionMatrix, Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix); } -PUBLIC STATIC void GLRenderer::UpdateProjectionMatrix() { +void GLRenderer::UpdateProjectionMatrix() { } -PUBLIC STATIC void GLRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { +void GLRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { float f = 1.0f / tanf(fov / 2.0f); float delta = far - near; @@ -1508,7 +1476,7 @@ PUBLIC STATIC void GLRenderer::MakePerspectiveMatrix(Matrix4x4* out, float f } // Shader-related functions -PUBLIC STATIC void GLRenderer::UseShader(void* shader) { +void GLRenderer::UseShader(void* shader) { if (GLRenderer::CurrentShader != (GLShader*)shader) { GLRenderer::CurrentShader = (GLShader*)shader; GLRenderer::CurrentShader->Use(); @@ -1517,7 +1485,7 @@ PUBLIC STATIC void GLRenderer::UseShader(void* shader) { glUniform1i(GLRenderer::CurrentShader->LocTexture, 0); CHECK_GL(); } } -PUBLIC STATIC void GLRenderer::SetUniformF(int location, int count, float* values) { +void GLRenderer::SetUniformF(int location, int count, float* values) { switch (count) { case 1: glUniform1f(location, values[0]); CHECK_GL(); break; case 2: glUniform2f(location, values[0], values[1]); CHECK_GL(); break; @@ -1525,10 +1493,10 @@ PUBLIC STATIC void GLRenderer::SetUniformF(int location, int count, float* v case 4: glUniform4f(location, values[0], values[1], values[2], values[3]); CHECK_GL(); break; } } -PUBLIC STATIC void GLRenderer::SetUniformI(int location, int count, int* values) { +void GLRenderer::SetUniformI(int location, int count, int* values) { glUniform1iv(location, count, values); CHECK_GL(); } -PUBLIC STATIC void GLRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { +void GLRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { GL_TextureData* textureData = (GL_TextureData*)texture->DriverData; glActiveTexture(GL_TEXTURE0 + slot); CHECK_GL(); glUniform1i(uniform_index, slot); CHECK_GL(); @@ -1536,12 +1504,12 @@ PUBLIC STATIC void GLRenderer::SetUniformTexture(Texture* texture, int unifo } // Palette-related functions -PUBLIC STATIC void GLRenderer::UpdateGlobalPalette() { +void GLRenderer::UpdateGlobalPalette() { } // These guys -PUBLIC STATIC void GLRenderer::Clear() { +void GLRenderer::Clear() { if (UseDepthTesting) { #ifdef GL_ES glClearDepthf(1.0f); CHECK_GL(); @@ -1554,34 +1522,34 @@ PUBLIC STATIC void GLRenderer::Clear() { glClear(GL_COLOR_BUFFER_BIT); CHECK_GL(); } } -PUBLIC STATIC void GLRenderer::Present() { +void GLRenderer::Present() { SDL_GL_SwapWindow(Application::Window); CHECK_GL(); } // Draw mode setting functions -PUBLIC STATIC void GLRenderer::SetBlendColor(float r, float g, float b, float a) { +void GLRenderer::SetBlendColor(float r, float g, float b, float a) { } -PUBLIC STATIC void GLRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { +void GLRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { glBlendFuncSeparate( GL_GetBlendFactorFromHatchEnum(srcC), GL_GetBlendFactorFromHatchEnum(dstC), GL_GetBlendFactorFromHatchEnum(srcA), GL_GetBlendFactorFromHatchEnum(dstA)); CHECK_GL(); } -PUBLIC STATIC void GLRenderer::SetTintColor(float r, float g, float b, float a) { +void GLRenderer::SetTintColor(float r, float g, float b, float a) { } -PUBLIC STATIC void GLRenderer::SetTintMode(int mode) { +void GLRenderer::SetTintMode(int mode) { } -PUBLIC STATIC void GLRenderer::SetTintEnabled(bool enabled) { +void GLRenderer::SetTintEnabled(bool enabled) { } -PUBLIC STATIC void GLRenderer::SetLineWidth(float n) { +void GLRenderer::SetLineWidth(float n) { glLineWidth(n); CHECK_GL(); } // Primitive drawing functions -PUBLIC STATIC void GLRenderer::StrokeLine(float x1, float y1, float x2, float y2) { +void GLRenderer::StrokeLine(float x1, float y1, float x2, float y2) { // Graphics::Save(); GL_Predraw(NULL); @@ -1594,7 +1562,7 @@ PUBLIC STATIC void GLRenderer::StrokeLine(float x1, float y1, float x2, floa glDrawArrays(GL_LINES, 0, 2); CHECK_GL(); // Graphics::Restore(); } -PUBLIC STATIC void GLRenderer::StrokeCircle(float x, float y, float rad, float thickness) { +void GLRenderer::StrokeCircle(float x, float y, float rad, float thickness) { Graphics::Save(); Graphics::Translate(x, y, 0.0f); Graphics::Scale(rad, rad, 1.0f); @@ -1605,7 +1573,7 @@ PUBLIC STATIC void GLRenderer::StrokeCircle(float x, float y, float rad, flo glDrawArrays(GL_LINE_STRIP, 0, 361); CHECK_GL(); Graphics::Restore(); } -PUBLIC STATIC void GLRenderer::StrokeEllipse(float x, float y, float w, float h) { +void GLRenderer::StrokeEllipse(float x, float y, float w, float h) { Graphics::Save(); Graphics::Translate(x + w / 2, y + h / 2, 0.0f); Graphics::Scale(w / 2, h / 2, 1.0f); @@ -1616,14 +1584,14 @@ PUBLIC STATIC void GLRenderer::StrokeEllipse(float x, float y, float w, floa glDrawArrays(GL_LINE_STRIP, 0, 361); CHECK_GL(); Graphics::Restore(); } -PUBLIC STATIC void GLRenderer::StrokeRectangle(float x, float y, float w, float h) { +void GLRenderer::StrokeRectangle(float x, float y, float w, float h) { StrokeLine(x, y, x + w, y); StrokeLine(x, y + h, x + w, y + h); StrokeLine(x, y, x, y + h); StrokeLine(x + w, y, x + w, y + h); } -PUBLIC STATIC void GLRenderer::FillCircle(float x, float y, float rad) { +void GLRenderer::FillCircle(float x, float y, float rad) { #ifdef GL_SUPPORTS_SMOOTHING if (Graphics::SmoothFill) { glEnable(GL_POLYGON_SMOOTH); CHECK_GL(); @@ -1646,7 +1614,7 @@ PUBLIC STATIC void GLRenderer::FillCircle(float x, float y, float rad) { } #endif } -PUBLIC STATIC void GLRenderer::FillEllipse(float x, float y, float w, float h) { +void GLRenderer::FillEllipse(float x, float y, float w, float h) { #ifdef GL_SUPPORTS_SMOOTHING if (Graphics::SmoothFill) { glEnable(GL_POLYGON_SMOOTH); CHECK_GL(); @@ -1669,7 +1637,7 @@ PUBLIC STATIC void GLRenderer::FillEllipse(float x, float y, float w, float } #endif } -PUBLIC STATIC void GLRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void GLRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { #ifdef GL_SUPPORTS_SMOOTHING if (Graphics::SmoothFill) { glEnable(GL_POLYGON_SMOOTH); CHECK_GL(); @@ -1692,7 +1660,7 @@ PUBLIC STATIC void GLRenderer::FillTriangle(float x1, float y1, float x2, fl } #endif } -PUBLIC STATIC void GLRenderer::FillRectangle(float x, float y, float w, float h) { +void GLRenderer::FillRectangle(float x, float y, float w, float h) { #ifdef GL_SUPPORTS_SMOOTHING if (Graphics::SmoothFill) { glEnable(GL_POLYGON_SMOOTH); CHECK_GL(); @@ -1716,7 +1684,7 @@ PUBLIC STATIC void GLRenderer::FillRectangle(float x, float y, float w, floa } #endif } -PUBLIC STATIC Uint32 GLRenderer::CreateTexturedShapeBuffer(float* data, int vertexCount) { +Uint32 GLRenderer::CreateTexturedShapeBuffer(float* data, int vertexCount) { // x, y, z, u, v Uint32 bufferID; glGenBuffers(1, &bufferID); CHECK_GL(); @@ -1724,7 +1692,7 @@ PUBLIC STATIC Uint32 GLRenderer::CreateTexturedShapeBuffer(float* data, int ve glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexCount * 5, data, GL_STATIC_DRAW); CHECK_GL(); return bufferID; } -PUBLIC STATIC void GLRenderer::DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount) { +void GLRenderer::DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount) { GL_Predraw(texture); // glEnableVertexAttribArray(GLRenderer::CurrentShader->LocTexCoord); @@ -1738,14 +1706,14 @@ PUBLIC STATIC void GLRenderer::DrawTexturedShapeBuffer(Texture* texture, Uin } // Texture drawing functions -PUBLIC STATIC void GLRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { +void GLRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { x *= RetinaScale; y *= RetinaScale; w *= RetinaScale; h *= RetinaScale; GL_DrawTexture(texture, sx, sy, sw, sh, x, y, w, h); } -PUBLIC STATIC void GLRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void GLRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; // /* @@ -1768,7 +1736,7 @@ PUBLIC STATIC void GLRenderer::DrawSprite(ISprite* sprite, int animation, in // x + fX * animframe.OffsetX, // y + fY * animframe.OffsetY, fX * sw, fY * sh); } -PUBLIC STATIC void GLRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void GLRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; AnimFrame animframe = sprite->Animations[animation].Frames[frame]; @@ -1791,7 +1759,7 @@ PUBLIC STATIC void GLRenderer::DrawSpritePart(ISprite* sprite, int animation y + fY * (sy + animframe.OffsetY), fX * sw, fY * sh); } // 3D drawing functions -PUBLIC STATIC void GLRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void GLRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { PolygonRenderer *renderer = GL_GetPolygonRenderer(); if (renderer != nullptr) { renderer->ModelMatrix = modelMatrix; @@ -1799,7 +1767,7 @@ PUBLIC STATIC void GLRenderer::DrawPolygon3D(void* data, int vertexCount, in renderer->DrawPolygon3D((VertexAttribute*)data, vertexCount, vertexFlag, texture); } } -PUBLIC STATIC void GLRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void GLRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { PolygonRenderer *renderer = GL_GetPolygonRenderer(); if (renderer != nullptr) { renderer->ModelMatrix = modelMatrix; @@ -1807,7 +1775,7 @@ PUBLIC STATIC void GLRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, renderer->DrawSceneLayer3D((SceneLayer*)layer, sx, sy, sw, sh); } } -PUBLIC STATIC void GLRenderer::DrawModel(void* inModel, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void GLRenderer::DrawModel(void* inModel, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { PolygonRenderer *renderer = GL_GetPolygonRenderer(); if (renderer != nullptr) { renderer->ModelMatrix = modelMatrix; @@ -1815,7 +1783,7 @@ PUBLIC STATIC void GLRenderer::DrawModel(void* inModel, Uint16 animation, Ui renderer->DrawModel((IModel*)inModel, animation, frame); } } -PUBLIC STATIC void GLRenderer::DrawModelSkinned(void* inModel, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void GLRenderer::DrawModelSkinned(void* inModel, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { PolygonRenderer *renderer = GL_GetPolygonRenderer(); if (renderer != nullptr) { renderer->ModelMatrix = modelMatrix; @@ -1823,7 +1791,7 @@ PUBLIC STATIC void GLRenderer::DrawModelSkinned(void* inModel, Uint16 armatu renderer->DrawModelSkinned((IModel*)inModel, armature); } } -PUBLIC STATIC void GLRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void GLRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::CurrentScene3D < 0 || vertexBufferIndex < 0 || vertexBufferIndex >= MAX_VERTEX_BUFFERS) return; @@ -1852,18 +1820,18 @@ PUBLIC STATIC void GLRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Ma driverData = (GL_VertexBuffer*)scene->Buffer->DriverData; driverData->Changed = true; } -PUBLIC STATIC void GLRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { +void GLRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { } -PUBLIC STATIC void GLRenderer::UnbindVertexBuffer() { +void GLRenderer::UnbindVertexBuffer() { } -PUBLIC STATIC void GLRenderer::ClearScene3D(Uint32 sceneIndex) { +void GLRenderer::ClearScene3D(Uint32 sceneIndex) { Scene3D* scene = &Graphics::Scene3Ds[sceneIndex]; GL_VertexBuffer *driverData = (GL_VertexBuffer*)scene->Buffer->DriverData; driverData->Changed = true; } -PUBLIC STATIC void GLRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { +void GLRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -2047,7 +2015,7 @@ PUBLIC STATIC void GLRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMod GLRenderer::SetDepthTesting(Graphics::UseDepthTesting); } -PUBLIC STATIC void* GLRenderer::CreateVertexBuffer(Uint32 maxVertices) { +void* GLRenderer::CreateVertexBuffer(Uint32 maxVertices) { VertexBuffer* vtxBuf = new VertexBuffer(maxVertices); vtxBuf->DriverData = Memory::TrackedCalloc("VertexBuffer::DriverData", 1, sizeof(GL_VertexBuffer)); @@ -2061,7 +2029,7 @@ PUBLIC STATIC void* GLRenderer::CreateVertexBuffer(Uint32 maxVertices) { return (void*)vtxBuf; } -PUBLIC STATIC void GLRenderer::DeleteVertexBuffer(void* vtxBuf) { +void GLRenderer::DeleteVertexBuffer(void* vtxBuf) { VertexBuffer* vertexBuffer = (VertexBuffer*)vtxBuf; GL_VertexBuffer* driverData = (GL_VertexBuffer*)vertexBuffer->DriverData; if (driverData) { @@ -2081,7 +2049,7 @@ PUBLIC STATIC void GLRenderer::DeleteVertexBuffer(void* vtxBuf) { delete vertexBuffer; } -PUBLIC STATIC void GLRenderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { +void GLRenderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { frame->ID = 0; float fX[4], fY[4]; @@ -2124,13 +2092,13 @@ PUBLIC STATIC void GLRenderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* glBindBuffer(GL_ARRAY_BUFFER, frame->ID); CHECK_GL(); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); CHECK_GL(); } -PUBLIC STATIC void GLRenderer::DeleteFrameBufferID(AnimFrame* frame) { +void GLRenderer::DeleteFrameBufferID(AnimFrame* frame) { if (frame->ID) { glDeleteBuffers(1, (GLuint*)&frame->ID); CHECK_GL(); frame->ID = 0; } } -PUBLIC STATIC void GLRenderer::SetDepthTesting(bool enable) { +void GLRenderer::SetDepthTesting(bool enable) { if (UseDepthTesting) { if (enable) { glEnable(GL_DEPTH_TEST); CHECK_GL(); diff --git a/source/Engine/Rendering/GL/GLShader.cpp b/source/Engine/Rendering/GL/GLShader.cpp index 7e24ae08..415c8daa 100644 --- a/source/Engine/Rendering/GL/GLShader.cpp +++ b/source/Engine/Rendering/GL/GLShader.cpp @@ -1,42 +1,3 @@ -#if INTERFACE -#include -#include -#include - -#include - -class GLShader { -public: - GLuint ProgramID = 0; - GLuint VertexProgramID = 0; - GLuint FragmentProgramID = 0; - - GLint LocProjectionMatrix; - GLint LocModelViewMatrix; - GLint LocPosition; - GLint LocTexCoord; - GLint LocTexture; - GLint LocTextureU; - GLint LocTextureV; - GLint LocPalette; - GLint LocColor; - GLint LocVaryingColor; - GLint LocFogColor; - GLint LocFogLinearStart; - GLint LocFogLinearEnd; - GLint LocFogDensity; - GLint LocFogTable; - - char FilenameV[256]; - char FilenameF[256]; - - // Cache stuff - float CachedBlendColors[4]; - Matrix4x4* CachedProjectionMatrix = NULL; - Matrix4x4* CachedModelViewMatrix = NULL; -}; -#endif - #ifdef USING_OPENGL #include @@ -46,7 +7,7 @@ class GLShader { #define CHECK_GL() \ GLShader::CheckGLError(__LINE__) -PUBLIC GLShader::GLShader(std::string vertexShaderSource, std::string fragmentShaderSource) { +GLShader::GLShader(std::string vertexShaderSource, std::string fragmentShaderSource) { GLint compiled = GL_FALSE; ProgramID = glCreateProgram(); CHECK_GL(); @@ -76,7 +37,7 @@ PUBLIC GLShader::GLShader(std::string vertexShaderSource, std::string fra AttachAndLink(); } -PUBLIC GLShader::GLShader(Stream* streamVS, Stream* streamFS) { +GLShader::GLShader(Stream* streamVS, Stream* streamFS) { GLint compiled = GL_FALSE; ProgramID = glCreateProgram(); CHECK_GL(); @@ -150,7 +111,7 @@ PUBLIC GLShader::GLShader(Stream* streamVS, Stream* streamFS) { AttachAndLink(); } -PRIVATE void GLShader::AttachAndLink() { +void GLShader::AttachAndLink() { glAttachShader(ProgramID, VertexProgramID); CHECK_GL(); glAttachShader(ProgramID, FragmentProgramID); CHECK_GL(); @@ -189,7 +150,7 @@ PRIVATE void GLShader::AttachAndLink() { } -PUBLIC bool GLShader::CheckShaderError(GLuint shader) { +bool GLShader::CheckShaderError(GLuint shader) { int infoLogLength = 0; int maxLength = infoLogLength; @@ -205,7 +166,7 @@ PUBLIC bool GLShader::CheckShaderError(GLuint shader) { delete[] infoLog; return false; } -PUBLIC bool GLShader::CheckProgramError(GLuint prog) { +bool GLShader::CheckProgramError(GLuint prog) { int infoLogLength = 0; int maxLength = infoLogLength; @@ -222,23 +183,23 @@ PUBLIC bool GLShader::CheckProgramError(GLuint prog) { return false; } -PUBLIC GLuint GLShader::Use() { +GLuint GLShader::Use() { glUseProgram(ProgramID); CHECK_GL(); // glEnableVertexAttribArray(1); CHECK_GL(); return ProgramID; } -PUBLIC GLint GLShader::GetAttribLocation(const GLchar* identifier) { +GLint GLShader::GetAttribLocation(const GLchar* identifier) { GLint value = glGetAttribLocation(ProgramID, identifier); CHECK_GL(); return value; } -PUBLIC GLint GLShader::GetUniformLocation(const GLchar* identifier) { +GLint GLShader::GetUniformLocation(const GLchar* identifier) { GLint value = glGetUniformLocation(ProgramID, identifier); CHECK_GL(); return value; } -PUBLIC GLShader::~GLShader() { +GLShader::~GLShader() { if (CachedProjectionMatrix) { delete CachedProjectionMatrix; } @@ -256,7 +217,7 @@ PUBLIC GLShader::~GLShader() { } } -PUBLIC STATIC bool GLShader::CheckGLError(int line) { +bool GLShader::CheckGLError(int line) { const char* errstr = NULL; GLenum error = glGetError(); switch (error) { diff --git a/source/Engine/Rendering/GL/GLShaderBuilder.cpp b/source/Engine/Rendering/GL/GLShaderBuilder.cpp index 7845a986..f4a23c99 100644 --- a/source/Engine/Rendering/GL/GLShaderBuilder.cpp +++ b/source/Engine/Rendering/GL/GLShaderBuilder.cpp @@ -1,16 +1,6 @@ -#if INTERFACE -#include -#include - -class GLShaderBuilder { -public: - -}; -#endif - #include -PRIVATE STATIC void GLShaderBuilder::AddUniformsToShaderText(std::string& shaderText, GLShaderUniforms uniforms) { +void GLShaderBuilder::AddUniformsToShaderText(std::string& shaderText, GLShaderUniforms uniforms) { if (uniforms.u_matrix) { shaderText += "uniform mat4 u_projectionMatrix;\n"; shaderText += "uniform mat4 u_modelViewMatrix;\n"; @@ -41,7 +31,7 @@ PRIVATE STATIC void GLShaderBuilder::AddUniformsToShaderText(std::string& shader shaderText += "uniform float u_fogDensity;\n"; } } -PRIVATE STATIC void GLShaderBuilder::AddInputsToVertexShaderText(std::string& shaderText, GLShaderLinkage inputs) { +void GLShaderBuilder::AddInputsToVertexShaderText(std::string& shaderText, GLShaderLinkage inputs) { if (inputs.link_position) { shaderText += "attribute vec3 i_position;\n"; } @@ -52,7 +42,7 @@ PRIVATE STATIC void GLShaderBuilder::AddInputsToVertexShaderText(std::string& sh shaderText += "attribute vec4 i_color;\n"; } } -PRIVATE STATIC void GLShaderBuilder::AddOutputsToVertexShaderText(std::string& shaderText, GLShaderLinkage outputs) { +void GLShaderBuilder::AddOutputsToVertexShaderText(std::string& shaderText, GLShaderLinkage outputs) { if (outputs.link_position) { shaderText += "varying vec4 o_position;\n"; } @@ -63,10 +53,10 @@ PRIVATE STATIC void GLShaderBuilder::AddOutputsToVertexShaderText(std::string& s shaderText += "varying vec4 o_color;\n"; } } -PRIVATE STATIC void GLShaderBuilder::AddInputsToFragmentShaderText(std::string& shaderText, GLShaderLinkage& inputs) { +void GLShaderBuilder::AddInputsToFragmentShaderText(std::string& shaderText, GLShaderLinkage& inputs) { AddOutputsToVertexShaderText(shaderText, inputs); } -PRIVATE STATIC string GLShaderBuilder::BuildFragmentShaderMainFunc(GLShaderLinkage& inputs, GLShaderUniforms& uniforms) { +string GLShaderBuilder::BuildFragmentShaderMainFunc(GLShaderLinkage& inputs, GLShaderUniforms& uniforms) { std::string shaderText = ""; if (uniforms.u_fog_linear) { @@ -140,7 +130,7 @@ PRIVATE STATIC string GLShaderBuilder::BuildFragmentShaderMainFunc(GLShaderLinka return shaderText; } -PUBLIC STATIC string GLShaderBuilder::Vertex(GLShaderLinkage& inputs, GLShaderLinkage& outputs, GLShaderUniforms& uniforms) { +string GLShaderBuilder::Vertex(GLShaderLinkage& inputs, GLShaderLinkage& outputs, GLShaderUniforms& uniforms) { std::string shaderText = ""; #ifdef GL_ES @@ -166,7 +156,7 @@ PUBLIC STATIC string GLShaderBuilder::Vertex(GLShaderLinkage& inputs, GLShaderLi return shaderText; } -PUBLIC STATIC string GLShaderBuilder::Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms, std::string mainText) { +string GLShaderBuilder::Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms, std::string mainText) { std::string shaderText = ""; #ifdef GL_ES @@ -180,6 +170,6 @@ PUBLIC STATIC string GLShaderBuilder::Fragment(GLShaderLinkage& inputs, GLShader return shaderText; } -PUBLIC STATIC string GLShaderBuilder::Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms) { +string GLShaderBuilder::Fragment(GLShaderLinkage& inputs, GLShaderUniforms& uniforms) { return Fragment(inputs, uniforms, BuildFragmentShaderMainFunc(inputs, uniforms)); } diff --git a/source/Engine/Rendering/GL/GLShaderContainer.cpp b/source/Engine/Rendering/GL/GLShaderContainer.cpp index 39243743..dc91a4bf 100644 --- a/source/Engine/Rendering/GL/GLShaderContainer.cpp +++ b/source/Engine/Rendering/GL/GLShaderContainer.cpp @@ -1,24 +1,12 @@ -#if INTERFACE -#include -#include - -class GLShaderContainer { -public: - GLShader *Base = nullptr; - GLShader *Textured = nullptr; - GLShader *PalettizedTextured = nullptr; -}; -#endif - #include #include #include -PUBLIC GLShaderContainer::GLShaderContainer() { +GLShaderContainer::GLShaderContainer() { } -PUBLIC GLShaderContainer::GLShaderContainer(GLShaderLinkage vsIn, GLShaderLinkage vsOut, GLShaderLinkage fsIn, GLShaderUniforms vsUni, GLShaderUniforms fsUni) { +GLShaderContainer::GLShaderContainer(GLShaderLinkage vsIn, GLShaderLinkage vsOut, GLShaderLinkage fsIn, GLShaderUniforms vsUni, GLShaderUniforms fsUni) { std::string vs, fs; vsIn.link_position = true; @@ -43,7 +31,7 @@ PUBLIC GLShaderContainer::GLShaderContainer(GLShaderLinkage vsIn, GLShaderLinkag PalettizedTextured = new GLShader(vs, fs); } -PUBLIC GLShader* GLShaderContainer::Get(bool useTexturing, bool usePalette) { +GLShader* GLShaderContainer::Get(bool useTexturing, bool usePalette) { if (useTexturing) { if (usePalette) return PalettizedTextured; @@ -54,15 +42,15 @@ PUBLIC GLShader* GLShaderContainer::Get(bool useTexturing, bool usePalette) { return Base; } -PUBLIC GLShader* GLShaderContainer::Get(bool useTexturing) { +GLShader* GLShaderContainer::Get(bool useTexturing) { return Get(useTexturing, false); } -PUBLIC GLShader* GLShaderContainer::Get() { +GLShader* GLShaderContainer::Get() { return Get(false, false); } -PUBLIC STATIC GLShaderContainer* GLShaderContainer::Make(bool use_vertex_colors) { +GLShaderContainer* GLShaderContainer::Make(bool use_vertex_colors) { GLShaderLinkage vsIn = {0}; GLShaderLinkage vsOut = {0}; GLShaderLinkage fsIn = {0}; @@ -76,7 +64,7 @@ PUBLIC STATIC GLShaderContainer* GLShaderContainer::Make(bool use_vertex_colors) return new GLShaderContainer(vsIn, vsOut, fsIn, vsUni, fsUni); } -PUBLIC STATIC GLShaderContainer* GLShaderContainer::MakeFog(int fog_type) { +GLShaderContainer* GLShaderContainer::MakeFog(int fog_type) { GLShaderLinkage vsIn = {0}; GLShaderLinkage vsOut = {0}; GLShaderLinkage fsIn = {0}; @@ -97,7 +85,7 @@ PUBLIC STATIC GLShaderContainer* GLShaderContainer::MakeFog(int fog_type) { return new GLShaderContainer(vsIn, vsOut, fsIn, vsUni, fsUni); } -PUBLIC STATIC GLShaderContainer* GLShaderContainer::MakeYUV() { +GLShaderContainer* GLShaderContainer::MakeYUV() { GLShaderLinkage vsIn = {0}; GLShaderLinkage vsOut = {0}; GLShaderLinkage fsIn = {0}; @@ -140,7 +128,7 @@ PUBLIC STATIC GLShaderContainer* GLShaderContainer::MakeYUV() { return container; } -PUBLIC GLShaderContainer::~GLShaderContainer() { +GLShaderContainer::~GLShaderContainer() { if (Base) delete Base; if (Textured) diff --git a/source/Engine/Rendering/GameTexture.cpp b/source/Engine/Rendering/GameTexture.cpp index 133941e2..37b6c1fd 100644 --- a/source/Engine/Rendering/GameTexture.cpp +++ b/source/Engine/Rendering/GameTexture.cpp @@ -1,40 +1,28 @@ -#if INTERFACE -#include -#include - -class GameTexture { -public: - Texture* TexturePtr = nullptr; - int UnloadPolicy; - bool OwnsTexture = true; -}; -#endif - #include #include -PUBLIC GameTexture::GameTexture() { +GameTexture::GameTexture() { } -PUBLIC GameTexture::GameTexture(Uint32 width, Uint32 height, int unloadPolicy) { +GameTexture::GameTexture(Uint32 width, Uint32 height, int unloadPolicy) { TexturePtr = Texture::New(SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, width, height); UnloadPolicy = unloadPolicy; } -PUBLIC VIRTUAL Texture* GameTexture::GetTexture() { +Texture* GameTexture::GetTexture() { return TexturePtr; } -PUBLIC VIRTUAL int GameTexture::GetID() { +int GameTexture::GetID() { if (TexturePtr) return TexturePtr->ID; return 0; } -PUBLIC GameTexture::~GameTexture() { +GameTexture::~GameTexture() { if (TexturePtr && OwnsTexture) Graphics::DisposeTexture(TexturePtr); } diff --git a/source/Engine/Rendering/Material.cpp b/source/Engine/Rendering/Material.cpp index 522ba883..1c37596f 100644 --- a/source/Engine/Rendering/Material.cpp +++ b/source/Engine/Rendering/Material.cpp @@ -1,37 +1,8 @@ -#if INTERFACE -#include -#include - -class Material { -public: - char* Name = nullptr; - - float ColorDiffuse[4]; - float ColorSpecular[4]; - float ColorAmbient[4]; - float ColorEmissive[4]; - - float Shininess = 0.0f; - float ShininessStrength = 1.0f; - float Opacity = 1.0f; - - char* TextureDiffuseName = nullptr; - char* TextureSpecularName = nullptr; - char* TextureAmbientName = nullptr; - char* TextureEmissiveName = nullptr; - - Image* TextureDiffuse = nullptr; - Image* TextureSpecular = nullptr; - Image* TextureAmbient = nullptr; - Image* TextureEmissive = nullptr; -}; -#endif - #include #include -PUBLIC Material::Material() { +Material::Material() { for (int i = 0; i < 4; i++) { ColorDiffuse[i] = ColorSpecular[i] = @@ -40,7 +11,7 @@ PUBLIC Material::Material() { } } -PUBLIC void Material::Dispose() { +void Material::Dispose() { delete TextureDiffuse; delete TextureSpecular; delete TextureAmbient; @@ -54,6 +25,6 @@ PUBLIC void Material::Dispose() { Memory::Free(TextureEmissiveName); } -PUBLIC Material::~Material() { +Material::~Material() { Dispose(); } diff --git a/source/Engine/Rendering/Metal/MetalRenderer.cpp.unused b/source/Engine/Rendering/Metal/MetalRenderer.cpp.unused deleted file mode 100644 index b53c5933..00000000 --- a/source/Engine/Rendering/Metal/MetalRenderer.cpp.unused +++ /dev/null @@ -1,1418 +0,0 @@ -#if INTERFACE -#include -#include -#include -#include -#include - -#include - -class MetalRenderer { -public: -}; -#endif - -// Shader -// https://github.com/spurious/SDL-mirror/blob/master/src/render/metal/SDL_shaders_metal.metal -// Renderer -// https://github.com/spurious/SDL-mirror/blob/master/src/render/metal/SDL_render_metal.m - -#ifdef MACOSXAAAAAAAAAAAAAA - -#include - -#include -#include -#include - -struct Vertex { - float x, y, z; - int color; - float u, v; -}; -struct Metal_RenderData { - void* Metal_DLL; - IDirect3D9* D3D; - IDirect3DDevice9* Device; - UINT Adapter; - D3DPRESENT_PARAMETERS PresentParams; - bool UpdateBackBufferSize; - bool BeginScene; - bool EnableSeparateAlphaBlend; - IDirect3DSurface9* DefaultRenderTarget; - IDirect3DSurface9* CurrentRenderTarget; - void* D3Dx_DLL; - LPDIRECT3DPIXELSHADER9 Shaders[NUM_SHADERS]; -}; -struct Metal_TextureData { - bool Dirty; - DWORD Usage; - Uint32 Format; - D3DFORMAT D3DFormat; - IDirect3DTexture9* Texture; - IDirect3DTexture9* Staging; - D3DTEXTUREFILTERTYPE ScaleMode; -}; - -MetalShader* Metal_CurrentShader = NULL; -MetalShader* Metal_SelectedShader = NULL; -MetalShader* Metal_ShaderShape = NULL; -MetalShader* Metal_ShaderTexturedShape = NULL; - -int Metal_DefaultFramebuffer; -Vertex* Metal_BufferCircleFill; -Vertex* Metal_BufferCircleStroke; -Vertex* Metal_BufferSquareFill; - -Uint32 Metal_BlendColorsAsHex = 0; - -bool Metal_PixelPerfectScale = false; -float Metal_RenderScaleX = 1.0f; -float Metal_RenderScaleY = 1.0f; -Matrix4x4* Metal_MatrixIdentity = NULL; - -DWORD Metal_Blend_SRC_COLOR = D3DBLEND_SRCALPHA; -DWORD Metal_Blend_DST_COLOR = D3DBLEND_INVSRCALPHA; -DWORD Metal_Blend_SRC_ALPHA = D3DBLEND_SRCALPHA; -DWORD Metal_Blend_DST_ALPHA = D3DBLEND_INVSRCALPHA; - -Metal_RenderData* renderData = NULL; - -bool Metal_LoadDLL(void** pD3DDLL, IDirect3D9** pDirect3D9Interface) { - *pD3DDLL = SDL_LoadObject("D3D9.DLL"); - if (*pD3DDLL) { - typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion); - Direct3DCreate9_t Direct3DCreate9Func; - - #ifdef USE_D3D9EX - typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D); - Direct3DCreate9Ex_t Direct3DCreate9ExFunc; - - Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex"); - if (Direct3DCreate9ExFunc) { - IDirect3D9Ex *pDirect3D9ExInterface; - HRESULT hr = Direct3DCreate9ExFunc(Metal_SDK_VERSION, &pDirect3D9ExInterface); - if (SUCCEEDED(hr)) { - const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } }; - hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (void**)pDirect3D9Interface); - IDirect3D9Ex_Release(pDirect3D9ExInterface); - if (SUCCEEDED(hr)) { - return true; - } - } - } - #endif /* USE_D3D9EX */ - - Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9"); - if (Direct3DCreate9Func) { - *pDirect3D9Interface = Direct3DCreate9Func(Metal_SDK_VERSION); - if (*pDirect3D9Interface) { - return true; - } - } - - SDL_UnloadObject(*pD3DDLL); - *pD3DDLL = NULL; - } - *pDirect3D9Interface = NULL; - return false; -} -void Metal_InitRenderState() { - D3DMATRIX matrix; - - IDirect3DDevice9* device = renderData->Device; - - IDirect3DDevice9_SetVertexShader(device, NULL); - IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); - // IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); - IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE); - IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE); - IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); - - /* Enable color modulation by diffuse color */ - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - - /* Enable alpha modulation by diffuse alpha */ - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - /* Enable separate alpha blend function, if possible */ - if (renderData->EnableSeparateAlphaBlend) { - IDirect3DDevice9_SetRenderState(device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - } - - /* Disable second texture stage, since we're done */ - IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); - IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - - /* Set an identity world and view matrix */ - matrix.m[0][0] = 1.0f; - matrix.m[0][1] = 0.0f; - matrix.m[0][2] = 0.0f; - matrix.m[0][3] = 0.0f; - matrix.m[1][0] = 0.0f; - matrix.m[1][1] = 1.0f; - matrix.m[1][2] = 0.0f; - matrix.m[1][3] = 0.0f; - matrix.m[2][0] = 0.0f; - matrix.m[2][1] = 0.0f; - matrix.m[2][2] = 1.0f; - matrix.m[2][3] = 0.0f; - matrix.m[3][0] = 0.0f; - matrix.m[3][1] = 0.0f; - matrix.m[3][2] = 0.0f; - matrix.m[3][3] = 1.0f; - IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix); - IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix); - - /* Reset our current scale mode */ - // SDL_memset(renderData->ScaleMode, 0xFF, sizeof(renderData->ScaleMode)); - - /* Start the render with BeginScene */ - renderData->BeginScene = true; -} -void Metal_MakeShaders() { - // Metal_ShaderShape = new MetalShader(vertexShaderSource, sizeof(vertexShaderSource), fragmentShaderSource_Shape, sizeof(fragmentShaderSource_Shape)); - // Metal_ShaderTexturedShape = new MetalShader(vertexShaderSource, sizeof(vertexShaderSource), fragmentShaderSource_TexturedShape, sizeof(fragmentShaderSource_TexturedShape)); - // ShaderTexturedShapeBGRA = new MetalShader(vertexShaderSource, sizeof(vertexShaderSource), fragmentShaderSource_TexturedShapeBGRA, sizeof(fragmentShaderSource_TexturedShapeBGRA)); -} -void Metal_MakeShapeBuffers() { - Vertex* buffer; - - Metal_BufferCircleFill = (Vertex*)Memory::TrackedMalloc("MetalRenderer::Metal_BufferCircleFill", 362 * sizeof(Vertex)); - buffer = Metal_BufferCircleFill; - buffer[0] = Vertex { 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - for (int i = 0; i < 361; i++) { - buffer[i + 1] = Vertex { cos(i * M_PI / 180.0f), sin(i * M_PI / 180.0f), 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - } - - Metal_BufferCircleStroke = (Vertex*)Memory::TrackedMalloc("MetalRenderer::Metal_BufferCircleStroke", 361 * sizeof(Vertex)); - buffer = (Vertex*)Metal_BufferCircleStroke; - for (int i = 0; i < 361; i++) { - buffer[i + 0] = Vertex { cos(i * M_PI / 180.0f), sin(i * M_PI / 180.0f), 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - } - - Metal_BufferSquareFill = (Vertex*)Memory::TrackedMalloc("MetalRenderer::Metal_BufferSquareFill", 4 * sizeof(Vertex)); - buffer = (Vertex*)Metal_BufferSquareFill; - buffer[0] = Vertex { 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - buffer[1] = Vertex { 1.0f, 0.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - buffer[2] = Vertex { 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; - buffer[3] = Vertex { 0.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f }; -} -const char* Metal_GetResultString(HRESULT result) { - switch (result) { - case D3DERR_WRONGTEXTUREFORMAT: - return "WRONGTEXTUREFORMAT"; - case D3DERR_UNSUPPORTEDCOLOROPERATION: - return "UNSUPPORTEDCOLOROPERATION"; - case D3DERR_UNSUPPORTEDCOLORARG: - return "UNSUPPORTEDCOLORARG"; - case D3DERR_UNSUPPORTEDALPHAOPERATION: - return "UNSUPPORTEDALPHAOPERATION"; - case D3DERR_UNSUPPORTEDALPHAARG: - return "UNSUPPORTEDALPHAARG"; - case D3DERR_TOOMANYOPERATIONS: - return "TOOMANYOPERATIONS"; - case D3DERR_CONFLICTINGTEXTUREFILTER: - return "CONFLICTINGTEXTUREFILTER"; - case D3DERR_UNSUPPORTEDFACTORVALUE: - return "UNSUPPORTEDFACTORVALUE"; - case D3DERR_CONFLICTINGRENDERSTATE: - return "CONFLICTINGRENDERSTATE"; - case D3DERR_UNSUPPORTEDTEXTUREFILTER: - return "UNSUPPORTEDTEXTUREFILTER"; - case D3DERR_CONFLICTINGTEXTUREPALETTE: - return "CONFLICTINGTEXTUREPALETTE"; - case D3DERR_DRIVERINTERNALERROR: - return "DRIVERINTERNALERROR"; - case D3DERR_NOTFOUND: - return "NOTFOUND"; - case D3DERR_MOREDATA: - return "MOREDATA"; - case D3DERR_DEVICELOST: - return "DEVICELOST"; - case D3DERR_DEVICENOTRESET: - return "DEVICENOTRESET"; - case D3DERR_NOTAVAILABLE: - return "NOTAVAILABLE"; - case D3DERR_OUTOFVIDEOMEMORY: - return "OUTOFVIDEOMEMORY"; - case D3DERR_INVALIDDEVICE: - return "INVALIDDEVICE"; - case D3DERR_INVALIDCALL: - return "INVALIDCALL"; - case D3DERR_DRIVERINVALIDCALL: - return "DRIVERINVALIDCALL"; - case D3DERR_WASSTILLDRAWING: - return "WASSTILLDRAWING"; - default: - return "UNKNOWN"; - } - return NULL; -} -D3DFORMAT Metal_PixelFormatToD3DFORMAT(Uint32 format) { - switch (format) { - case SDL_PIXELFORMAT_RGB565: - return D3DFMT_R5G6B5; - case SDL_PIXELFORMAT_RGB888: - return D3DFMT_X8R8G8B8; - case SDL_PIXELFORMAT_ARGB8888: - return D3DFMT_A8R8G8B8; - case SDL_PIXELFORMAT_YV12: - case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: - case SDL_PIXELFORMAT_NV21: - return D3DFMT_L8; - default: - return D3DFMT_UNKNOWN; - } -} -Uint32 Metal_D3DFORMATToPixelFormat(D3DFORMAT format) { - switch (format) { - case D3DFMT_R5G6B5: - return SDL_PIXELFORMAT_RGB565; - case D3DFMT_X8R8G8B8: - return SDL_PIXELFORMAT_RGB888; - case D3DFMT_A8R8G8B8: - return SDL_PIXELFORMAT_ARGB8888; - default: - return SDL_PIXELFORMAT_UNKNOWN; - } - return SDL_PIXELFORMAT_UNKNOWN; -} -int Metal_SetError(const char* error, HRESULT result) { - Log::Print(Log::LOG_ERROR, "D3D: %s (%s)", error, Metal_GetResultString(result)); - exit(0); - return 0; -} - -void Metal_CreateTexture(Texture* texture) { - texture->DriverData = Memory::TrackedCalloc("Texture::DriverData", 1, sizeof(Metal_TextureData)); - - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - - textureData->ScaleMode = Graphics::TextureInterpolate ? D3DTEXF_LINEAR : D3DTEXF_POINT; - - DWORD usage = 0; - if (texture->Access == SDL_TEXTUREACCESS_TARGET) - usage = D3DUSAGE_RENDERTARGET; - - // Metal_CreateTextureRep - HRESULT result; - textureData->Dirty = false; - textureData->Usage = usage; - textureData->Format = texture->Format; - textureData->D3DFormat = Metal_PixelFormatToD3DFORMAT(texture->Format); - - result = IDirect3DDevice9_CreateTexture(renderData->Device, texture->Width, texture->Height, 1, usage, textureData->D3DFormat, D3DPOOL_DEFAULT, &textureData->Texture, NULL); - if (FAILED(result)) { - Log::Print(Log::LOG_ERROR, "CreateTextureD3DPOOL_DEFAULT() %s", Metal_GetResultString(result)); - Log::Print(Log::LOG_INFO, "IDirect3DDevice9_CreateTexture(%p, %u, %u, %u, %u", renderData->Device, texture->Width, texture->Height, 1, usage); - exit(0); - } -} -int Metal_RecreateTexture(Texture* texture) { - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - if (!textureData) - return 0; - - if (textureData->Texture) { - IDirect3DTexture9_Release(textureData->Texture); - textureData->Texture = NULL; - } - if (textureData->Staging) { - IDirect3DTexture9_AddDirtyRect(textureData->Staging, NULL); - textureData->Dirty = true; - } - return 0; -} - -int Metal_SetRenderTarget(Texture* texture) { - HRESULT result; - /* Release the previous render target if it wasn't the default one */ - if (renderData->CurrentRenderTarget != NULL) { - IDirect3DSurface9_Release(renderData->CurrentRenderTarget); - renderData->CurrentRenderTarget = NULL; - } - - if (texture == NULL) { - IDirect3DDevice9_SetRenderTarget(renderData->Device, 0, renderData->DefaultRenderTarget); - return 0; - } - - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - if (!textureData) { - SDL_SetError("Texture is not currently available"); - return -1; - } - - /* Make sure the render target is updated if it was locked and written to */ - if (textureData->Dirty && textureData->Staging) { - if (!textureData->Texture) { - result = IDirect3DDevice9_CreateTexture(renderData->Device, texture->Width, texture->Height, 1, textureData->Usage, Metal_PixelFormatToD3DFORMAT(textureData->Format), D3DPOOL_DEFAULT, &textureData->Texture, NULL); - if (FAILED(result)) { - return Metal_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); - } - } - - result = IDirect3DDevice9_UpdateTexture(renderData->Device, (IDirect3DBaseTexture9*)textureData->Staging, (IDirect3DBaseTexture9*)textureData->Texture); - if (FAILED(result)) { - return Metal_SetError("UpdateTexture()", result); - } - textureData->Dirty = false; - } - - result = IDirect3DTexture9_GetSurfaceLevel(textureData->Texture, 0, &renderData->CurrentRenderTarget); - if (FAILED(result)) { - return Metal_SetError("GetSurfaceLevel()", result); - } - - result = IDirect3DDevice9_SetRenderTarget(renderData->Device, 0, renderData->CurrentRenderTarget); - if (FAILED(result)) { - return Metal_SetError("SetRenderTarget()", result); - } - - return 0; -} -void Metal_Reset() { - HRESULT result; - - /* Release the default render target before reset */ - if (renderData->DefaultRenderTarget) { - IDirect3DSurface9_Release(renderData->DefaultRenderTarget); - renderData->DefaultRenderTarget = NULL; - } - if (renderData->CurrentRenderTarget) { - IDirect3DSurface9_Release(renderData->CurrentRenderTarget); - renderData->CurrentRenderTarget = NULL; - } - - /* Release application render targets */ - for (Texture* texture = Graphics::TextureHead; texture != NULL; texture = texture->Next) { - if (texture->Access == SDL_TEXTUREACCESS_TARGET) - MetalRenderer::DisposeTexture(texture); - else - Metal_RecreateTexture(texture); - } - - result = IDirect3DDevice9_Reset(renderData->Device, &renderData->PresentParams); - if (FAILED(result)) { - if (result == D3DERR_DEVICELOST) { - /* Don't worry about it, we'll reset later... */ - return; - } - else { - Metal_SetError("Reset() %s", result); - return; - } - } - - /* Allocate application render targets */ - for (Texture* texture = Graphics::TextureHead; texture != NULL; texture = texture->Next) { - if (texture->Access == SDL_TEXTUREACCESS_TARGET) - Metal_CreateTexture(texture); - } - - IDirect3DDevice9_GetRenderTarget(renderData->Device, 0, &renderData->DefaultRenderTarget); - Metal_InitRenderState(); - Metal_SetRenderTarget(Graphics::CurrentRenderTarget); - MetalRenderer::UpdateViewport(); -} -void Metal_Predraw() { - HRESULT result; - - if (renderData->UpdateBackBufferSize) { - SDL_Window* window = Application::Window; - int w, h; - Uint32 window_flags = SDL_GetWindowFlags(window); - SDL_GetWindowSize(window, &w, &h); - - renderData->PresentParams.BackBufferWidth = w; - renderData->PresentParams.BackBufferHeight = h; - if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) { - SDL_DisplayMode fullscreen_mode; - SDL_GetWindowDisplayMode(window, &fullscreen_mode); - renderData->PresentParams.Windowed = FALSE; - renderData->PresentParams.BackBufferFormat = Metal_PixelFormatToD3DFORMAT(fullscreen_mode.format); - renderData->PresentParams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; - } - else { - renderData->PresentParams.Windowed = TRUE; - renderData->PresentParams.BackBufferFormat = D3DFMT_UNKNOWN; - renderData->PresentParams.FullScreen_RefreshRateInHz = 0; - } - - Metal_Reset(); - // if (Metal_Reset(renderer) < 0) { - // return -1; - // } - - renderData->UpdateBackBufferSize = false; - } - if (renderData->BeginScene) { - result = IDirect3DDevice9_BeginScene(renderData->Device); - if (result == D3DERR_DEVICELOST) { - Metal_Reset(); - // if (Metal_Reset(renderer) < 0) { - // return -1; - // } - result = IDirect3DDevice9_BeginScene(renderData->Device); - } - if (FAILED(result)) { - Metal_SetError("BeginScene() %s", result); - } - renderData->BeginScene = false; - } -} - -void Metal_SetBlendMode() { - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_ALPHABLENDENABLE, TRUE); - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SRCBLEND, Metal_Blend_SRC_COLOR); - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_DESTBLEND, Metal_Blend_DST_COLOR); - if (renderData->EnableSeparateAlphaBlend) { - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SRCBLENDALPHA, Metal_Blend_SRC_ALPHA); - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_DESTBLENDALPHA, Metal_Blend_DST_ALPHA); - } - - // Enable multisample - if (Graphics::MultisamplingEnabled) { - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_MULTISAMPLEANTIALIAS, TRUE); - } -} -DWORD Metal_GetBlendFactorFromHatch(int factor) { - switch (factor) { - case BlendFactor_ZERO: - return D3DBLEND_ZERO; - case BlendFactor_ONE: - return D3DBLEND_ONE; - case BlendFactor_SRC_COLOR: - return D3DBLEND_SRCCOLOR; - case BlendFactor_INV_SRC_COLOR: - return D3DBLEND_INVSRCCOLOR; - case BlendFactor_SRC_ALPHA: - return D3DBLEND_SRCALPHA; - case BlendFactor_INV_SRC_ALPHA: - return D3DBLEND_INVSRCALPHA; - case BlendFactor_DST_COLOR: - return D3DBLEND_DESTCOLOR; - case BlendFactor_INV_DST_COLOR: - return D3DBLEND_INVDESTCOLOR; - case BlendFactor_DST_ALPHA: - return D3DBLEND_DESTALPHA; - case BlendFactor_INV_DST_ALPHA: - return D3DBLEND_INVDESTALPHA; - } - return 0; -} -void Metal_BindTexture(Texture* texture, int index) { - HRESULT result; - - if (!texture) { - result = IDirect3DDevice9_SetTexture(renderData->Device, index, NULL); - if (FAILED(result)) { - Metal_SetError("SetTexture() %s", result); - } - return; - } - - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - - IDirect3DDevice9_SetSamplerState(renderData->Device, index, D3DSAMP_MINFILTER, textureData->ScaleMode); - IDirect3DDevice9_SetSamplerState(renderData->Device, index, D3DSAMP_MAGFILTER, textureData->ScaleMode); - IDirect3DDevice9_SetSamplerState(renderData->Device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - IDirect3DDevice9_SetSamplerState(renderData->Device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - if (textureData->Dirty && textureData->Staging) { - if (!textureData->Texture) { - result = IDirect3DDevice9_CreateTexture(renderData->Device, texture->Width, texture->Height, 1, textureData->Usage, Metal_PixelFormatToD3DFORMAT(texture->Format), D3DPOOL_DEFAULT, &textureData->Texture, NULL); - if (FAILED(result)) { - Metal_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); - } - } - - result = IDirect3DDevice9_UpdateTexture(renderData->Device, (IDirect3DBaseTexture9*)textureData->Staging, (IDirect3DBaseTexture9*)textureData->Texture); - if (FAILED(result)) { - Metal_SetError("UpdateTexture()", result); - } - textureData->Dirty = false; - } - - result = IDirect3DDevice9_SetTexture(renderData->Device, index, (IDirect3DBaseTexture9*)textureData->Texture); - if (FAILED(result)) { - Metal_SetError("SetTexture() %s", result); - } -} - -void Metal_DrawTextureRaw(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h, bool flipX, bool flipY) { - HRESULT result; - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - - LPDIRECT3DPIXELSHADER9 shader = (LPDIRECT3DPIXELSHADER9)NULL; - - Metal_Predraw(); - - float minu = (sx) / texture->Width; - float maxu = (sx + sw) / texture->Width; - float minv = (sy) / texture->Height; - float maxv = (sy + sh) / texture->Height; - DWORD color = 0xFFFFFFFF; - if (Graphics::TextureBlend) - color = Metal_BlendColorsAsHex; - - float minx = x; - float maxx = x + w; - float miny = y; - float maxy = y + h; - - // NOTE: We do this because Direct3D9's origin for render targets is top-left, - // instead of the usual bottom-left. - if (texture->Access == SDL_TEXTUREACCESS_TARGET) { - // miny = y + h; - // maxy = y; - // if (Graphics::CurrentRenderTarget != NULL) - // flipY = !flipY; - maxv = (sy) / texture->Height; - minv = (sy + sh) / texture->Height; - } - - Vertex vertices[4]; - // vertices[0] = Vertex { minx, miny, 0.0f, color, minu, minv }; - // vertices[1] = Vertex { maxx, miny, 0.0f, color, maxu, minv }; - // vertices[2] = Vertex { maxx, maxy, 0.0f, color, maxu, maxv }; - // vertices[3] = Vertex { minx, maxy, 0.0f, color, minu, maxv }; - vertices[0] = Vertex { 0.0f, 0.0f, 0.0f, color, minu, minv }; - vertices[1] = Vertex { 1.0f, 0.0f, 0.0f, color, maxu, minv }; - vertices[2] = Vertex { 1.0f, 1.0f, 0.0f, color, maxu, maxv }; - vertices[3] = Vertex { 0.0f, 1.0f, 0.0f, color, minu, maxv }; - - if (Metal_PixelPerfectScale) { - Point points[4]; - for (int i = 0; i < 4; i++) { - points[i] = Graphics::ProjectToScreen(vertices[i].x, vertices[i].y, vertices[i].z); - vertices[i].x = points[i].X ; - vertices[i].y = points[i].Y; - vertices[i].z = points[i].Z; - } - } - - // NOTE: This is not necessary in D3D10 and onwards - float fx = flipX ? -1.0f : 1.0f; - float fy = flipY ? -1.0f : 1.0f; - // if (Graphics::CurrentRenderTarget) { - // for (int i = 0; i < 4; i++) { - // vertices[i].x -= 0.5f * fx; - // vertices[i].y += 0.5f * fy; // NOTE: Note the plus here, instead of minus - // } - // } - // else { - // for (int i = 0; i < 4; i++) { - // vertices[i].x -= 0.5f * fx; - // vertices[i].y -= 0.5f * fy; - // } - // } - - Metal_SetBlendMode(); - Metal_BindTexture(texture, 0); - - if (shader) { - // result = IDirect3DDevice9_SetPixelShader(renderData->Device, shader); - // if (FAILED(result)) { - // return Metal_SetError("SetShader()", result); - // } - } - - D3DMATRIX matrix; - if (Metal_PixelPerfectScale) { - memcpy(&matrix.m, Metal_MatrixIdentity->Values, sizeof(float) * 16); - } - else { - // memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - if (texture->Access != SDL_TEXTUREACCESS_TARGET) - Graphics::Translate(-0.5f * fx, 0.5f * fy, 0.0f); - else - Graphics::Translate(-0.5f * fx, -0.5f * fy, 0.0f); - Graphics::Scale(w, h, 1.0f); - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - Graphics::Restore(); - } - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - - result = IDirect3DDevice9_DrawPrimitiveUP(renderData->Device, D3DPT_TRIANGLEFAN, 2, vertices, sizeof(*vertices)); - if (FAILED(result)) { - Metal_SetError("DrawPrimitiveUP() %s", result); - } - - if (shader) { - // IDirect3DDevice9_SetPixelShader(renderData->Device, NULL); - } - // return FAILED(result) ? -1 : 0; -} - -void Metal_BeginDrawShape(Vertex* shapeBuffer, int vertexCount) { - Metal_Predraw(); - - Vertex* buffer = (Vertex*)shapeBuffer; - for (int i = 0; i < vertexCount; i++) { - buffer[i].color = Metal_BlendColorsAsHex; - } - - Metal_SetBlendMode(); - Metal_BindTexture(NULL, 0); -} -void Metal_EndDrawShape(Vertex* shapeBuffer, D3DPRIMITIVETYPE prim, int triangleCount) { - HRESULT result = IDirect3DDevice9_DrawPrimitiveUP(renderData->Device, prim, triangleCount, shapeBuffer, sizeof(Vertex)); - if (FAILED(result)) - Metal_SetError("DrawPrimitiveUP() %s", result); -} - -// Initialization and disposal functions -PUBLIC STATIC void MetalRenderer::Init() { - Graphics::PreferredPixelFormat = SDL_PIXELFORMAT_ARGB8888; - Metal_MatrixIdentity = Matrix4x4::Create(); - - renderData = (Metal_RenderData*)calloc(1, sizeof(Metal_RenderData)); - - // renderData->D3D = Direct3DCreate9(Metal_SDK_VERSION); - if (!Metal_LoadDLL(&renderData->Metal_DLL, &renderData->D3D)) { - Log::Print(Log::LOG_ERROR, "Unable to create Direct3D interface."); - return; - } - - Log::Print(Log::LOG_INFO, "Renderer: Direct3D 9"); - - D3DCAPS9 caps; - HRESULT result; - DWORD device_flags; - Uint32 window_flags; - SDL_SysWMinfo windowinfo; - IDirect3DSwapChain9* chain; - D3DPRESENT_PARAMETERS pparams; - SDL_DisplayMode fullscreen_mode; - int displayIndex, w, h, texture_max_w, texture_max_h; - - SDL_VERSION(&windowinfo.version); - SDL_GetWindowWMInfo(Application::Window, &windowinfo); - - window_flags = SDL_GetWindowFlags(Application::Window); - SDL_GetWindowSize(Application::Window, &w, &h); - SDL_GetWindowDisplayMode(Application::Window, &fullscreen_mode); - - memset(&pparams, 0, sizeof(pparams)); - pparams.hDeviceWindow = windowinfo.info.win.window; - pparams.BackBufferWidth = w; - pparams.BackBufferHeight = h; - pparams.BackBufferCount = 1; - pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; - - pparams.EnableAutoDepthStencil = TRUE; - pparams.AutoDepthStencilFormat = D3DFMT_D16; - - if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) { - pparams.Windowed = FALSE; - pparams.BackBufferFormat = Metal_PixelFormatToD3DFORMAT(fullscreen_mode.format); - pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; - } - else { - pparams.Windowed = TRUE; - pparams.BackBufferFormat = D3DFMT_UNKNOWN; - pparams.FullScreen_RefreshRateInHz = 0; - } - - if (Graphics::VsyncEnabled) { - pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; - } - else { - pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - } - - displayIndex = SDL_GetWindowDisplayIndex(Application::Window); - renderData->Adapter = SDL_Direct3D9GetAdapterIndex(displayIndex); - - // Check for full-scene antialiasing - if (Graphics::MultisamplingEnabled) { - pparams.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; - if (SUCCEEDED(result = IDirect3D9_CheckDeviceMultiSampleType(renderData->D3D, renderData->Adapter, - D3DDEVTYPE_HAL, - Metal_PixelFormatToD3DFORMAT(SDL_GetWindowPixelFormat(Application::Window)), - pparams.Windowed, - pparams.MultiSampleType, NULL))) { - pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; - } - else if (FAILED(result)) { - pparams.MultiSampleType = D3DMULTISAMPLE_NONE; - Graphics::MultisamplingEnabled = 0; - } - } - - IDirect3D9_GetDeviceCaps(renderData->D3D, renderData->Adapter, D3DDEVTYPE_HAL, &caps); - - device_flags = D3DCREATE_FPU_PRESERVE; - if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) - device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; - else - device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; - - if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) { - device_flags |= D3DCREATE_MULTITHREADED; - } - - result = IDirect3D9_CreateDevice( - renderData->D3D, renderData->Adapter, - D3DDEVTYPE_HAL, - pparams.hDeviceWindow, - device_flags, - &pparams, &renderData->Device); - if (FAILED(result)) { - MetalRenderer::Dispose(); - Log::Print(Log::LOG_ERROR, "CreateDevice() %s", Metal_GetResultString(result)); - exit(0); - } - - /* Get presentation parameters to fill info */ - result = IDirect3DDevice9_GetSwapChain(renderData->Device, 0, &chain); - if (FAILED(result)) { - MetalRenderer::Dispose(); - Log::Print(Log::LOG_ERROR, "GetSwapChain() %d", result); - return; - } - result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); - if (FAILED(result)) { - IDirect3DSwapChain9_Release(chain); - MetalRenderer::Dispose(); - Log::Print(Log::LOG_ERROR, "GetPresentParameters() %d", result); - return; - } - IDirect3DSwapChain9_Release(chain); - if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { - Graphics::VsyncEnabled = true; - } - renderData->PresentParams = pparams; - - IDirect3DDevice9_GetDeviceCaps(renderData->Device, &caps); - texture_max_w = caps.MaxTextureWidth; - texture_max_h = caps.MaxTextureHeight; - if (caps.NumSimultaneousRTs >= 2) { - // renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; - } - - if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) { - renderData->EnableSeparateAlphaBlend = SDL_TRUE; - } - - /* Store the default render target */ - IDirect3DDevice9_GetRenderTarget(renderData->Device, 0, &renderData->DefaultRenderTarget); - renderData->CurrentRenderTarget = NULL; - - /* Set up parameters for rendering */ - Metal_InitRenderState(); - - if (caps.MaxSimultaneousTextures >= 3) { - // int i; - // for (i = 0; i < SDL_arraysize(MetalRenderer::shaders); ++i) { - // result = D3D9_CreatePixelShader(renderData->Device, (D3D9_Shader)i, &MetalRenderer::shaders[i]); - // if (FAILED(result)) { - // Metal_SetError("CreatePixelShader()", result); - // } - // } - // if (MetalRenderer::shaders[SHADER_YUV_JPEG] && MetalRenderer::shaders[SHADER_YUV_BT601] && MetalRenderer::shaders[SHADER_YUV_BT709]) { - // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; - // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; - // } - } - - Metal_MakeShaders(); - Metal_MakeShapeBuffers(); - - UseShader(Metal_ShaderShape); - - Graphics::MaxTextureWidth = texture_max_w; - Graphics::MaxTextureHeight = texture_max_h; - - D3DADAPTER_IDENTIFIER9 indent; - IDirect3D9_GetAdapterIdentifier(renderData->D3D, renderData->Adapter, 0, &indent); - - Log::Print(Log::LOG_INFO, "Graphics Card: %s", indent.Description); -} -PUBLIC STATIC Uint32 MetalRenderer::GetWindowFlags() { - return SDL_WINDOW_METAL; -} -PUBLIC STATIC void MetalRenderer::SetGraphicsFunctions() { - Graphics::PixelOffset = 0.5f; - - Graphics::Internal.Init = MetalRenderer::Init; - Graphics::Internal.GetWindowFlags = MetalRenderer::GetWindowFlags; - Graphics::Internal.Dispose = MetalRenderer::Dispose; - - // Texture management functions - Graphics::Internal.CreateTexture = MetalRenderer::CreateTexture; - Graphics::Internal.LockTexture = MetalRenderer::LockTexture; - Graphics::Internal.UpdateTexture = MetalRenderer::UpdateTexture; - Graphics::Internal.UnlockTexture = MetalRenderer::UnlockTexture; - Graphics::Internal.DisposeTexture = MetalRenderer::DisposeTexture; - - // Viewport and view-related functions - Graphics::Internal.SetRenderTarget = MetalRenderer::SetRenderTarget; - Graphics::Internal.UpdateWindowSize = MetalRenderer::UpdateWindowSize; - Graphics::Internal.UpdateViewport = MetalRenderer::UpdateViewport; - Graphics::Internal.UpdateClipRect = MetalRenderer::UpdateClipRect; - Graphics::Internal.UpdateOrtho = MetalRenderer::UpdateOrtho; - Graphics::Internal.UpdatePerspective = MetalRenderer::UpdatePerspective; - Graphics::Internal.UpdateProjectionMatrix = MetalRenderer::UpdateProjectionMatrix; - - // Shader-related functions - Graphics::Internal.UseShader = MetalRenderer::UseShader; - Graphics::Internal.SetUniformF = MetalRenderer::SetUniformF; - Graphics::Internal.SetUniformI = MetalRenderer::SetUniformI; - Graphics::Internal.SetUniformTexture = MetalRenderer::SetUniformTexture; - - // These guys - Graphics::Internal.Clear = MetalRenderer::Clear; - Graphics::Internal.Present = MetalRenderer::Present; - - // Draw mode setting functions - Graphics::Internal.SetBlendColor = MetalRenderer::SetBlendColor; - Graphics::Internal.SetBlendMode = MetalRenderer::SetBlendMode; - Graphics::Internal.SetLineWidth = MetalRenderer::SetLineWidth; - - // Primitive drawing functions - Graphics::Internal.StrokeLine = MetalRenderer::StrokeLine; - Graphics::Internal.StrokeCircle = MetalRenderer::StrokeCircle; - Graphics::Internal.StrokeEllipse = MetalRenderer::StrokeEllipse; - Graphics::Internal.StrokeRectangle = MetalRenderer::StrokeRectangle; - Graphics::Internal.FillCircle = MetalRenderer::FillCircle; - Graphics::Internal.FillEllipse = MetalRenderer::FillEllipse; - Graphics::Internal.FillTriangle = MetalRenderer::FillTriangle; - Graphics::Internal.FillRectangle = MetalRenderer::FillRectangle; - - // Texture drawing functions - Graphics::Internal.DrawTexture = MetalRenderer::DrawTexture; - Graphics::Internal.DrawSprite = MetalRenderer::DrawSprite; - Graphics::Internal.DrawSpritePart = MetalRenderer::DrawSpritePart; -} -PUBLIC STATIC void MetalRenderer::Dispose() { - Memory::Free(Metal_BufferCircleFill); - Memory::Free(Metal_BufferCircleStroke); - Memory::Free(Metal_BufferSquareFill); - - // Metal_ShaderShape->Dispose(); delete Metal_ShaderShape; - // Metal_ShaderTexturedShape->Dispose(); delete Metal_ShaderTexturedShape; - // ShaderTexturedShapeYUV->Dispose(); delete ShaderTexturedShapeYUV; - // ShaderTexturedShapeBlur->Dispose(); delete ShaderTexturedShapeBlur; -} - -// Texture management functions -PUBLIC STATIC Texture* MetalRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { - Texture* texture = Texture::New(format, access, width, height); - - Metal_CreateTexture(texture); - - texture->ID = Graphics::TextureMap->Count + 1; - Graphics::TextureMap->Put(texture->ID, texture); - - return texture; -} -PUBLIC STATIC int MetalRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { - return 0; -} -PUBLIC STATIC int MetalRenderer::UpdateTexture(Texture* texture, SDL_Rect* r, void* pixels, int pitch) { - int inputPixelsX = 0; - int inputPixelsY = 0; - int inputPixelsW = texture->Width; - int inputPixelsH = texture->Height; - if (r) { - inputPixelsX = r->x; - inputPixelsY = r->y; - inputPixelsW = r->w; - inputPixelsH = r->h; - } - - if (Graphics::NoInternalTextures) { - if (inputPixelsW > Graphics::MaxTextureWidth) - inputPixelsW = Graphics::MaxTextureWidth; - if (inputPixelsH > Graphics::MaxTextureHeight) - inputPixelsH = Graphics::MaxTextureHeight; - } - - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - - RECT d3drect; - D3DLOCKED_RECT locked; - const Uint8 *src; - Uint8 *dst; - int row, length; - HRESULT result; - - d3drect.left = inputPixelsX; - d3drect.right = inputPixelsX + inputPixelsW; - d3drect.top = inputPixelsY; - d3drect.bottom = inputPixelsY + inputPixelsH; - - if (textureData->Staging == NULL) { - result = IDirect3DDevice9_CreateTexture(renderData->Device, texture->Width, texture->Height, 1, 0, textureData->D3DFormat, D3DPOOL_SYSTEMMEM, &textureData->Staging, NULL); - if (FAILED(result)) { - return Metal_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result); - } - } - - result = IDirect3DTexture9_LockRect(textureData->Staging, 0, &locked, &d3drect, 0); - if (FAILED(result)) { - Metal_SetError("LockRect() %s", result); - return -1; - } - - src = (const Uint8*)pixels; - dst = (Uint8*)locked.pBits; - length = inputPixelsW * SDL_BYTESPERPIXEL(texture->Format); - if (length == pitch && length == locked.Pitch) { - memcpy(dst, src, length * inputPixelsH); - } - else { - if (length > pitch) { - length = pitch; - } - if (length > locked.Pitch) { - length = locked.Pitch; - } - for (row = 0; row < inputPixelsH; ++row) { - memcpy(dst, src, length); - src += pitch; - dst += locked.Pitch; - } - } - result = IDirect3DTexture9_UnlockRect(textureData->Staging, 0); - if (FAILED(result)) { - Metal_SetError("UnlockRect() %s", result); - return -1; - } - textureData->Dirty = true; - - return 0; -} -PUBLIC STATIC void MetalRenderer::UnlockTexture(Texture* texture) { - -} -PUBLIC STATIC void MetalRenderer::DisposeTexture(Texture* texture) { - Metal_TextureData* textureData = (Metal_TextureData*)texture->DriverData; - if (!textureData) - return; - - if (textureData->Texture) { - IDirect3DTexture9_Release(textureData->Texture); - textureData->Texture = NULL; - } - if (textureData->Staging) { - IDirect3DTexture9_Release(textureData->Staging); - textureData->Staging = NULL; - } - - // free(texture->Pixels); - Memory::Free(texture->DriverData); - - texture->DriverData = NULL; -} - -// Viewport and view-related functions -PUBLIC STATIC void MetalRenderer::SetRenderTarget(Texture* texture) { - Metal_Predraw(); - Metal_SetRenderTarget(texture); -} -PUBLIC STATIC void MetalRenderer::UpdateWindowSize(int width, int height) { - // Metal_UpdateViewport(0, 0, width, height); - renderData->UpdateBackBufferSize = true; -} -PUBLIC STATIC void MetalRenderer::UpdateViewport() { - Viewport* vp = &Graphics::CurrentViewport; - - D3DVIEWPORT9 viewport; - viewport.X = vp->X; - viewport.Y = vp->Y; - viewport.Width = vp->Width; - viewport.Height = vp->Height; // * RetinaScale - viewport.MinZ = 0.0f; - viewport.MaxZ = 1.0f; - IDirect3DDevice9_SetViewport(renderData->Device, &viewport); - - // NOTE: According to SDL2 we should be setting projection matrix here. - // MetalRenderer::UpdateOrtho(vp->Width, vp->Height); - MetalRenderer::UpdateProjectionMatrix(); -} -PUBLIC STATIC void MetalRenderer::UpdateClipRect() { - ClipArea clip = Graphics::CurrentClip; - if (Graphics::CurrentClip.Enabled) { - Viewport view = Graphics::CurrentViewport; - - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SCISSORTESTENABLE, TRUE); - - - int w, h; - float scaleW = 1.0f, scaleH = 1.0f; - SDL_GetWindowSize(Application::Window, &w, &h); - View* currentView = &Scene::Views[Scene::ViewCurrent]; - scaleW *= w / currentView->Width; - scaleH *= h / currentView->Height; - - RECT r; - r.left = view.X + (int)((clip.X) * scaleW); - r.top = view.Y + (int)((clip.Y) * scaleH); - r.right = view.X + (int)((clip.X + clip.Width) * scaleW); - r.bottom = view.Y + (int)((clip.Y + clip.Height) * scaleH); - - HRESULT result = IDirect3DDevice9_SetScissorRect(renderData->Device, &r); - if (result != Metal_OK) { - Metal_SetError("SetScissor()", result); - } - } - else { - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SCISSORTESTENABLE, FALSE); - } -} -PUBLIC STATIC void MetalRenderer::UpdateOrtho(float left, float top, float right, float bottom) { - if (Scene::Views[Scene::ViewCurrent].Software) - Matrix4x4::Ortho(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, left, right, bottom, top, 500.0f, -500.0f); - else - Matrix4x4::Ortho(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, left, right, top, bottom, 500.0f, -500.0f); - Matrix4x4::Copy(Scene::Views[Scene::ViewCurrent].ProjectionMatrix, Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix); - - if (Metal_PixelPerfectScale) { - Metal_RenderScaleX = Graphics::CurrentViewport.Width / right; - Metal_RenderScaleY = Graphics::CurrentViewport.Height / top; - } -} -PUBLIC STATIC void MetalRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { - Matrix4x4::Perspective(Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix, fovy, aspect, nearv, farv); - Matrix4x4::Copy(Scene::Views[Scene::ViewCurrent].ProjectionMatrix, Scene::Views[Scene::ViewCurrent].BaseProjectionMatrix); -} -PUBLIC STATIC void MetalRenderer::UpdateProjectionMatrix() { - D3DMATRIX matrix; - memcpy(&matrix.m, Scene::Views[Scene::ViewCurrent].ProjectionMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_PROJECTION, &matrix); -} - -// Shader-related functions -PUBLIC STATIC void MetalRenderer::UseShader(void* shader) { - if (Metal_CurrentShader != (MetalShader*)shader) { - Metal_CurrentShader = (MetalShader*)shader; - Metal_CurrentShader->Use(); - } -} -PUBLIC STATIC void MetalRenderer::SetUniformF(int location, int count, float* values) { - // switch (count) { - // case 1: glUniform1f(location, values[0]); CHECK_GL(); break; - // case 2: glUniform2f(location, values[0], values[1]); CHECK_GL(); break; - // case 3: glUniform3f(location, values[0], values[1], values[2]); CHECK_GL(); break; - // case 4: glUniform4f(location, values[0], values[1], values[2], values[3]); CHECK_GL(); break; - // } -} -PUBLIC STATIC void MetalRenderer::SetUniformI(int location, int count, int* values) { - // glUniform1iv(location, count, values); -} -PUBLIC STATIC void MetalRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { - -} - -// These guys -PUBLIC STATIC void MetalRenderer::Clear() { - DWORD color; - HRESULT result; - int BackBufferWidth, BackBufferHeight; - - Metal_Predraw(); - - if (Graphics::CurrentRenderTarget) { - BackBufferWidth = Graphics::CurrentRenderTarget->Width; - BackBufferHeight = Graphics::CurrentRenderTarget->Height; - } - else { - BackBufferWidth = renderData->PresentParams.BackBufferWidth; - BackBufferHeight = renderData->PresentParams.BackBufferHeight; - } - - if (Graphics::CurrentClip.Enabled) - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SCISSORTESTENABLE, FALSE); - - DWORD clear_flags = D3DCLEAR_TARGET; - - clear_flags |= D3DCLEAR_ZBUFFER; - - color = 0x00000000; - - /* Don't reset the viewport if we don't have to! */ - Viewport* vp = &Graphics::CurrentViewport; - if (vp->X == 0.0 && - vp->Y == 0.0 && - vp->Width == BackBufferWidth && - vp->Height == BackBufferHeight) { - result = IDirect3DDevice9_Clear(renderData->Device, 0, NULL, clear_flags, color, 1.0f, 0); - } - else { - D3DVIEWPORT9 viewport; - - /* Clear is defined to clear the entire render target */ - viewport.X = 0.0; - viewport.Y = 0.0; - viewport.Width = BackBufferWidth; - viewport.Height = BackBufferHeight; - viewport.MinZ = 0.0f; - viewport.MaxZ = 1.0f; - IDirect3DDevice9_SetViewport(renderData->Device, &viewport); - - result = IDirect3DDevice9_Clear(renderData->Device, 0, NULL, clear_flags, color, 1.0f, 0); - - /* Reset the viewport */ - viewport.X = vp->X; - viewport.Y = vp->Y; - viewport.Width = vp->Width; - viewport.Height = vp->Height; - viewport.MinZ = 0.0f; - viewport.MaxZ = 1.0f; - IDirect3DDevice9_SetViewport(renderData->Device, &viewport); - } - - if (Graphics::CurrentClip.Enabled) - IDirect3DDevice9_SetRenderState(renderData->Device, D3DRS_SCISSORTESTENABLE, TRUE); - - if (FAILED(result)) { - Metal_SetError("Clear()", result); - } -} -PUBLIC STATIC void MetalRenderer::Present() { - HRESULT result; - - if (!renderData->BeginScene) { - IDirect3DDevice9_EndScene(renderData->Device); - renderData->BeginScene = true; - } - - result = IDirect3DDevice9_TestCooperativeLevel(renderData->Device); - if (result == D3DERR_DEVICELOST) { - /* We'll reset later */ - return; - } - if (result == D3DERR_DEVICENOTRESET) { - Metal_Reset(); - // Metal_Reset(renderer); - } - - result = IDirect3DDevice9_Present(renderData->Device, NULL, NULL, NULL, NULL); - if (FAILED(result)) { - Metal_SetError("Present()", result); - } -} - -// Draw mode setting functions -PUBLIC STATIC void MetalRenderer::SetBlendColor(float r, float g, float b, float a) { - int ha = (int)(a * 0xFF) << 24; - int hr = (int)(r * 0xFF) << 16; - int hg = (int)(g * 0xFF) << 8; - int hb = (int)(b * 0xFF); - Metal_BlendColorsAsHex = ha | hr | hg | hb; -} -PUBLIC STATIC void MetalRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { - Metal_Blend_SRC_COLOR = Metal_GetBlendFactorFromHatch(srcC); - Metal_Blend_DST_COLOR = Metal_GetBlendFactorFromHatch(dstC); - Metal_Blend_SRC_ALPHA = Metal_GetBlendFactorFromHatch(srcA); - Metal_Blend_DST_ALPHA = Metal_GetBlendFactorFromHatch(dstA); -} -PUBLIC STATIC void MetalRenderer::SetLineWidth(float n) { - // glLineWidth(n); -} - -// Primitive drawing functions -PUBLIC STATIC void MetalRenderer::StrokeLine(float x1, float y1, float x2, float y2) { - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderShape); - - Graphics::Save(); - // glUniformMatrix4fv(Metal_CurrentShader->LocModelViewMatrix, 1, false, Graphics::ModelViewMatrix->Values); - - float v[6]; - v[0] = x1; v[1] = y1; v[2] = 0.0f; - v[3] = x2; v[4] = y2; v[5] = 0.0f; - - // glBindBuffer(GL_ARRAY_BUFFER, 0); - // glVertexAttribPointer(Metal_CurrentShader->LocPosition, 3, GL_FLOAT, GL_FALSE, 0, v); - // glDrawArrays(GL_LINES, 0, 2); - Graphics::Restore(); -} -PUBLIC STATIC void MetalRenderer::StrokeCircle(float x, float y, float rad) { - Metal_BeginDrawShape(Metal_BufferCircleStroke, 361); - - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - Graphics::Scale(rad, rad, 1.0f); - D3DMATRIX matrix; - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - Graphics::Restore(); - - Metal_EndDrawShape(Metal_BufferCircleStroke, D3DPT_LINESTRIP, 360); -} -PUBLIC STATIC void MetalRenderer::StrokeEllipse(float x, float y, float w, float h) { - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderShape); - - Graphics::Save(); - Graphics::Translate(x + w / 2, y + h / 2, 0.0f); - Graphics::Scale(w / 2, h / 2, 1.0f); - // glUniformMatrix4fv(Metal_CurrentShader->LocModelViewMatrix, 1, false, Graphics::ModelViewMatrix->Values); - - // glBindBuffer(GL_ARRAY_BUFFER, Metal_BufferCircleStroke); - // glVertexAttribPointer(Metal_CurrentShader->LocPosition, 3, GL_FLOAT, GL_FALSE, 0, 0); - // glDrawArrays(GL_LINE_STRIP, 0, 361); - Graphics::Restore(); -} -PUBLIC STATIC void MetalRenderer::StrokeRectangle(float x, float y, float w, float h) { - StrokeLine(x, y, x + w, y); - StrokeLine(x, y + h, x + w, y + h); - - StrokeLine(x, y, x, y + h); - StrokeLine(x + w, y, x + w, y + h); -} -PUBLIC STATIC void MetalRenderer::FillCircle(float x, float y, float rad) { - Metal_BeginDrawShape(Metal_BufferCircleFill, 362); - - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - Graphics::Scale(rad, rad, 1.0f); - D3DMATRIX matrix; - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - Graphics::Restore(); - - Metal_EndDrawShape(Metal_BufferCircleFill, D3DPT_TRIANGLEFAN, 360); -} -PUBLIC STATIC void MetalRenderer::FillEllipse(float x, float y, float w, float h) { - Metal_BeginDrawShape(Metal_BufferCircleFill, 362); - - w *= 0.5f; - h *= 0.5f; - - Graphics::Save(); - Graphics::Translate(x + w, y + h, 0.0f); - Graphics::Scale(w, h, 1.0f); - D3DMATRIX matrix; - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - Graphics::Restore(); - - Metal_EndDrawShape(Metal_BufferCircleFill, D3DPT_TRIANGLEFAN, 360); -} -PUBLIC STATIC void MetalRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { - Vertex vertices[3]; - vertices[0] = Vertex { x1, y1, 0.0f, Metal_BlendColorsAsHex, 0.0f, 0.0f }; - vertices[1] = Vertex { x2, y2, 0.0f, Metal_BlendColorsAsHex, 0.0f, 0.0f }; - vertices[2] = Vertex { x3, y3, 0.0f, Metal_BlendColorsAsHex, 0.0f, 0.0f }; - - Metal_BeginDrawShape(vertices, 3); - - D3DMATRIX matrix; - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - - Metal_EndDrawShape(vertices, D3DPT_TRIANGLEFAN, 1); -} -PUBLIC STATIC void MetalRenderer::FillRectangle(float x, float y, float w, float h) { - Metal_BeginDrawShape(Metal_BufferSquareFill, 4); - - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - Graphics::Scale(w, h, 1.0f); - D3DMATRIX matrix; - memcpy(&matrix.m, Graphics::ModelViewMatrix->Values, sizeof(float) * 16); - IDirect3DDevice9_SetTransform(renderData->Device, D3DTS_VIEW, &matrix); - Graphics::Restore(); - - Metal_EndDrawShape(Metal_BufferSquareFill, D3DPT_TRIANGLEFAN, 2); -} - -// Texture drawing functions -PUBLIC STATIC void MetalRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderTexturedShape); - if (sx < 0) - sx = 0.0, sy = 0.0, sw = texture->Width, sh = texture->Height; - Metal_DrawTextureRaw(texture, sx, sy, sw, sh, x, y, w, h, false, texture->Access != SDL_TEXTUREACCESS_TARGET); -} -PUBLIC STATIC void MetalRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { - if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; - - AnimFrame animframe = sprite->Animations[animation].Frames[frame]; - - float fX = flipX ? -1.0 : 1.0; - float fY = flipY ? -1.0 : 1.0; - // DrawTexture(sprite->Spritesheets[animframe.SheetNumber], animframe.X, animframe.Y, animframe.W, animframe.H, x + fX * animframe.OffX, y + fY * animframe.OffY, fX * animframe.W, fY * animframe.H); - - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderTexturedShape); - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - Graphics::Scale(fX, fY, 1.0f); - Metal_DrawTextureRaw(sprite->Spritesheets[animframe.SheetNumber], animframe.X, animframe.Y, animframe.Width, animframe.Height, animframe.OffsetX, animframe.OffsetY, animframe.Width, animframe.Height, flipX, flipY); - Graphics::Restore(); -} -PUBLIC STATIC void MetalRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation) { - if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; - - AnimFrame animframe = sprite->Animations[animation].Frames[frame]; - if (sx == animframe.Width) - return; - if (sy == animframe.Height) - return; - - float fX = flipX ? -1.0 : 1.0; - float fY = flipY ? -1.0 : 1.0; - if (sw >= animframe.Width - sx) - sw = animframe.Width - sx; - if (sh >= animframe.Height - sy) - sh = animframe.Height - sy; - - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderTexturedShape); - Graphics::Save(); - Graphics::Translate(x, y, 0.0f); - Graphics::Scale(fX, fY, 1.0f); - Metal_DrawTextureRaw(sprite->Spritesheets[animframe.SheetNumber], - animframe.X + sx, animframe.Y + sy, - sw, sh, - sx + animframe.OffsetX, sy + animframe.OffsetY, - sw, sh, - flipX, flipY); - Graphics::Restore(); -} - -/* -// Draw buffering -PUBLIC STATIC Uint32 MetalRenderer::CreateTexturedShapeBuffer(float** data, int vertexCount) { - // x, y, z, u, v - Uint32 bufferID; - glGenBuffers(1, &bufferID); - glBindBuffer(GL_ARRAY_BUFFER, bufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexCount * 5, data, GL_STATIC_DRAW); - - *data = NULL; - - return bufferID; -} - -PUBLIC STATIC void MetalRenderer::DrawTexturedShapeBuffer(Texture* texture, Uint32 bufferID, int vertexCount) { - UseShader(Metal_SelectedShader ? Metal_SelectedShader : Metal_ShaderTexturedShape); - - GLTextureData* textureData = (GLTextureData*)texture->DriverData; - glUniformMatrix4fv(MetalRenderer::Metal_CurrentShader->LocModelViewMatrix, 1, false, MetalRenderer::Graphics::ModelViewMatrix->Values); - - glActiveTexture(GL_TEXTURE0); - glUniform1i(MetalRenderer::Metal_CurrentShader->LocTexture, 0); - glBindTexture(GL_TEXTURE_2D, textureData->TextureID); - - glEnableVertexAttribArray(MetalRenderer::Metal_CurrentShader->LocTexCoord); - - glBindBuffer(GL_ARRAY_BUFFER, bufferID); - glVertexAttribPointer(MetalRenderer::Metal_CurrentShader->LocPosition, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (GLvoid*)0); - glVertexAttribPointer(MetalRenderer::Metal_CurrentShader->LocTexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (GLvoid*)12); - glDrawArrays(GL_TRIANGLES, 0, vertexCount); - - glDisableVertexAttribArray(MetalRenderer::Metal_CurrentShader->LocTexCoord); -} -//*/ - -#endif diff --git a/source/Engine/Rendering/Metal/MetalRenderer.mm.unused b/source/Engine/Rendering/Metal/MetalRenderer.mm.unused deleted file mode 100644 index 4bcdbefc..00000000 --- a/source/Engine/Rendering/Metal/MetalRenderer.mm.unused +++ /dev/null @@ -1,443 +0,0 @@ - -#include - -#import -#import - -#ifdef __MACOSX__ - #import -#endif - -/* Regenerate these with build-metal-shaders.sh */ -// #ifdef __MACOSX__ -// #include "SDL_shaders_metal_osx.h" -// #elif defined(__TVOS__) -// #if TARGET_OS_SIMULATOR -// #include "SDL_shaders_metal_tvsimulator.h" -// #else -// #include "SDL_shaders_metal_tvos.h" -// #endif -// #else -// #if TARGET_OS_SIMULATOR -// #include "SDL_shaders_metal_iphonesimulator.h" -// #else -// #include "SDL_shaders_metal_ios.h" -// #endif -// #endif - -#include - -@interface METAL_TextureData : NSObject - @property (nonatomic, retain) id mtltexture; - @property (nonatomic, retain) id mtltexture_uv; - @property (nonatomic, retain) id mtlsampler; - @property (nonatomic, assign) SDL_MetalFragmentFunction fragmentFunction; - @property (nonatomic, assign) BOOL yuv; - @property (nonatomic, assign) BOOL nv12; - @property (nonatomic, assign) size_t conversionBufferOffset; - @property (nonatomic, assign) BOOL hasdata; - - @property (nonatomic, retain) id lockedbuffer; - @property (nonatomic, assign) SDL_Rect lockedrect; -@end - -@implementation METAL_TextureData -#if !__has_feature(objc_arc) - - (void)dealloc { - [_mtltexture release]; - [_mtltexture_uv release]; - [_mtlsampler release]; - [_lockedbuffer release]; - [super dealloc]; - } -#endif -@end - -static int IsMetalAvailable(const SDL_SysWMinfo* syswm) { - if (syswm->subsystem != SDL_SYSWM_COCOA && syswm->subsystem != SDL_SYSWM_UIKIT) { - Log::Print(Log::LOG_ERROR, "Metal render target only supports Cocoa and UIKit video targets at the moment."); - return -1; - } - // this checks a weak symbol. - #if (defined(__MACOSX__) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101100)) - if (MTLCreateSystemDefaultDevice == NULL) { // probably on 10.10 or lower. - Log::Print(Log::LOG_ERROR, "Metal framework not available on this system"); - return -1; - } - #endif - - return 0; -} - -void METAL_Init() { - @autoreleasepool { - Graphics::PreferredPixelFormat = SDL_PIXELFORMAT_ARGB8888; - Metal_MatrixIdentity = Matrix4x4::Create(); - - // renderData = (Metal_RenderData*)calloc(1, sizeof(Metal_RenderData)); - - Log::Print(Log::LOG_INFO, "Renderer: Metal"); - - SDL_SysWMinfo windowinfo; - SDL_DisplayMode fullscreen_mode; - int displayIndex, w, h, texture_max_w, texture_max_h; - - SDL_VERSION(&windowinfo.version); - SDL_GetWindowWMInfo(Application::Window, &windowinfo); - - SDL_GetWindowSize(Application::Window, &w, &h); - SDL_GetWindowDisplayMode(Application::Window, &fullscreen_mode); - - mtldevice = MTLCreateSystemDefaultDevice(); - - if (mtldevice == nil) { - SDL_free(renderer); - SDL_SetError("Failed to obtain Metal device"); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } - return NULL; - } - - view = SDL_Metal_CreateView(window); - - if (view == NULL) { - #if !__has_feature(objc_arc) - [mtldevice release]; - #endif - - SDL_free(renderer); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } - return NULL; - } - - // !!! FIXME: error checking on all of this. - data = [[METAL_RenderData alloc] init]; - - if (data == nil) { - #if !__has_feature(objc_arc) - [mtldevice release]; - #endif - SDL_Metal_DestroyView(view); - SDL_free(renderer); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } - return NULL; - } - - driverdata = (void*)CFBridgingRetain(data); - - data.mtlview = view; - - #ifdef __MACOSX__ - layer = (CAMetalLayer *)[(NSView *)view layer]; - #else - layer = (CAMetalLayer *)[(__bridge UIView *)view layer]; - #endif - - layer.device = mtldevice; - - /* Necessary for RenderReadPixels. */ - layer.framebufferOnly = NO; - - data.mtldevice = layer.device; - data.mtllayer = layer; - id mtlcmdqueue = [data.mtldevice newCommandQueue]; - data.mtlcmdqueue = mtlcmdqueue; - data.mtlcmdqueue.label = @"SDL Metal Renderer"; - data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor]; - - NSError *err = nil; - - // The compiled .metallib is embedded in a static array in a header file - // but the original shader source code is in SDL_shaders_metal.metal. - dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{}); - id mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err]; - data.mtllibrary = mtllibrary; - SDL_assert(err == nil); - #if !__has_feature(objc_arc) - dispatch_release(mtllibdata); - #endif - data.mtllibrary.label = @"SDL Metal renderer shader library"; - - /* Do some shader pipeline state loading up-front rather than on demand. */ - data.pipelinescount = 0; - data.allpipelines = NULL; - ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm); - - MTLSamplerDescriptor *samplerdesc = [[MTLSamplerDescriptor alloc] init]; - - samplerdesc.minFilter = MTLSamplerMinMagFilterNearest; - samplerdesc.magFilter = MTLSamplerMinMagFilterNearest; - id mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc]; - data.mtlsamplernearest = mtlsamplernearest; - - samplerdesc.minFilter = MTLSamplerMinMagFilterLinear; - samplerdesc.magFilter = MTLSamplerMinMagFilterLinear; - id mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc]; - data.mtlsamplerlinear = mtlsamplerlinear; - - /* Note: matrices are column major. */ - float identitytransform[16] = { - 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, - 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, - 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, - 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, - }; - float halfpixeltransform[16] = { - 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, - 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, - 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, - 0.500000000f, 0.500000000f, 0.000000000f, 1.000000000f, - }; - /* Metal pads float3s to 16 bytes. */ - float decodetransformJPEG[4*4] = { - 0.000000000, -0.501960814, -0.501960814, 0.000000000, /* offset */ - 1.000000000, 0.000000000, 1.402000000, 0.000000000, /* Rcoeff */ - 1.000000000, -0.344100000, -0.714100000, 0.000000000, /* Gcoeff */ - 1.000000000, 1.772000000, 0.000000000, 0.000000000, /* Bcoeff */ - }; - float decodetransformBT601[4*4] = { - -0.0627451017, -0.501960814, -0.501960814, 0.000000000, /* offset */ - 1.1644000000, 0.000000000, 1.596000000, 0.000000000, /* Rcoeff */ - 1.1644000000, -0.391800000, -0.813000000, 0.000000000, /* Gcoeff */ - 1.1644000000, 2.017200000, 0.000000000, 0.000000000, /* Bcoeff */ - }; - float decodetransformBT709[4*4] = { - 0.000000000, -0.501960814, -0.501960814, 0.000000000, /* offset */ - 1.000000000, 0.000000000, 1.402000000, 0.000000000, /* Rcoeff */ - 1.000000000, -0.344100000, -0.714100000, 0.000000000, /* Gcoeff */ - 1.000000000, 1.772000000, 0.000000000, 0.000000000, /* Bcoeff */ - }; - - id mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared]; - #if !__has_feature(objc_arc) - [mtlbufconstantstaging autorelease]; - #endif - - char *constantdata = [mtlbufconstantstaging contents]; - SDL_memcpy(constantdata + CONSTANTS_OFFSET_IDENTITY, identitytransform, sizeof(identitytransform)); - SDL_memcpy(constantdata + CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, halfpixeltransform, sizeof(halfpixeltransform)); - SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_JPEG, decodetransformJPEG, sizeof(decodetransformJPEG)); - SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT601, decodetransformBT601, sizeof(decodetransformBT601)); - SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709, decodetransformBT709, sizeof(decodetransformBT709)); - - int quadcount = UINT16_MAX / 4; - size_t indicessize = sizeof(UInt16) * quadcount * 6; - id mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared]; - #if !__has_feature(objc_arc) - [mtlbufquadindicesstaging autorelease]; - #endif - - /* Quads in the following vertex order (matches the FillRects vertices): - * 1---3 - * | \ | - * 0---2 - */ - UInt16 *indexdata = [mtlbufquadindicesstaging contents]; - for (int i = 0; i < quadcount; i++) { - indexdata[i * 6 + 0] = i * 4 + 0; - indexdata[i * 6 + 1] = i * 4 + 1; - indexdata[i * 6 + 2] = i * 4 + 2; - - indexdata[i * 6 + 3] = i * 4 + 2; - indexdata[i * 6 + 4] = i * 4 + 1; - indexdata[i * 6 + 5] = i * 4 + 3; - } - - id mtlbufconstants = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModePrivate]; - data.mtlbufconstants = mtlbufconstants; - data.mtlbufconstants.label = @"SDL constant data"; - - id mtlbufquadindices = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModePrivate]; - data.mtlbufquadindices = mtlbufquadindices; - data.mtlbufquadindices.label = @"SDL quad index buffer"; - - id cmdbuffer = [data.mtlcmdqueue commandBuffer]; - id blitcmd = [cmdbuffer blitCommandEncoder]; - - [blitcmd copyFromBuffer:mtlbufconstantstaging sourceOffset:0 toBuffer:mtlbufconstants destinationOffset:0 size:CONSTANTS_LENGTH]; - [blitcmd copyFromBuffer:mtlbufquadindicesstaging sourceOffset:0 toBuffer:mtlbufquadindices destinationOffset:0 size:indicessize]; - - [blitcmd endEncoding]; - [cmdbuffer commit]; - - // !!! FIXME: force more clears here so all the drawables are sane to start, and our static buffers are definitely flushed. - - // renderer->WindowEvent = METAL_WindowEvent; - // renderer->GetOutputSize = METAL_GetOutputSize; - // renderer->SupportsBlendMode = METAL_SupportsBlendMode; - // renderer->CreateTexture = METAL_CreateTexture; - // renderer->UpdateTexture = METAL_UpdateTexture; - // #if SDL_HAVE_YUV - // renderer->UpdateTextureYUV = METAL_UpdateTextureYUV; - // renderer->UpdateTextureNV = METAL_UpdateTextureNV; - // #endif - // renderer->LockTexture = METAL_LockTexture; - // renderer->UnlockTexture = METAL_UnlockTexture; - // renderer->SetTextureScaleMode = METAL_SetTextureScaleMode; - // renderer->SetRenderTarget = METAL_SetRenderTarget; - // renderer->QueueSetViewport = METAL_QueueSetViewport; - // renderer->QueueSetDrawColor = METAL_QueueSetDrawColor; - // renderer->QueueDrawPoints = METAL_QueueDrawPoints; - // renderer->QueueDrawLines = METAL_QueueDrawLines; - // renderer->QueueFillRects = METAL_QueueFillRects; - // renderer->QueueCopy = METAL_QueueCopy; - // renderer->QueueCopyEx = METAL_QueueCopyEx; - // renderer->RunCommandQueue = METAL_RunCommandQueue; - // renderer->RenderReadPixels = METAL_RenderReadPixels; - // renderer->RenderPresent = METAL_RenderPresent; - // renderer->DestroyTexture = METAL_DestroyTexture; - // renderer->DestroyRenderer = METAL_DestroyRenderer; - // renderer->GetMetalLayer = METAL_GetMetalLayer; - // renderer->GetMetalCommandEncoder = METAL_GetMetalCommandEncoder; - // - // renderer->info = METAL_RenderDriver.info; - // renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); - // - // renderer->always_batch = SDL_TRUE; - - #if (defined(__MACOSX__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST - if (@available(macOS 10.13, *)) { - data.mtllayer.displaySyncEnabled = (flags & SDL_RENDERER_PRESENTVSYNC) != 0; - if (data.mtllayer.displaySyncEnabled) { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } - } else - #endif - { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } - - /* https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */ - int maxtexsize = 4096; - #if defined(__MACOSX__) || TARGET_OS_MACCATALYST - maxtexsize = 16384; - #elif defined(__TVOS__) - maxtexsize = 8192; - #ifdef __TVOS_11_0 - if (@available(tvOS 11.0, *)) { - if ([mtldevice supportsFeatureSet:MTLFeatureSet_tvOS_GPUFamily2_v1]) { - maxtexsize = 16384; - } - } - #endif - #else - #ifdef __IPHONE_11_0 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunguarded-availability-new" - if ([mtldevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) { - maxtexsize = 16384; - } else - #pragma clang diagnostic pop - #endif - #ifdef __IPHONE_10_0 - if ([mtldevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) { - maxtexsize = 16384; - } else - #endif - if ([mtldevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v2] || [mtldevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v2]) { - maxtexsize = 8192; - } - else { - maxtexsize = 4096; - } - #endif - - renderer->info.max_texture_width = maxtexsize; - renderer->info.max_texture_height = maxtexsize; - - #if !__has_feature(objc_arc) - [mtlcmdqueue release]; - [mtllibrary release]; - [samplerdesc release]; - [mtlsamplernearest release]; - [mtlsamplerlinear release]; - [mtlbufconstants release]; - [mtlbufquadindices release]; - [data release]; - [mtldevice release]; - #endif - } -} -void METAL_Dispose() { - -} -Texture* METAL_CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { - -} -int METAL_LockTexture(Texture* texture, void** pixels, int* pitch) { - -} -int METAL_UpdateTexture(Texture* texture, SDL_Rect* r, void* pixels, int pitch) { - -} -void METAL_UnlockTexture(Texture* texture) { - -} -void METAL_DisposeTexture(Texture* texture) { - -} -void METAL_SetRenderTarget(Texture* texture) { - -} -void METAL_UpdateWindowSize(int width, int height) { - -} -void METAL_UpdateViewport() { - -} -void METAL_UpdateClipRect() { - -} -void METAL_UpdateOrtho(float left, float top, float right, float bottom) { - -} -void METAL_UpdatePerspective(float fovy, float aspect, float nearv, float farv) { - -} -void METAL_UpdateProjectionMatrix() { - -} -void METAL_Clear() { - -} -void METAL_Present() { - -} -void METAL_SetBlendColor(float r, float g, float b, float a) { - -} -void METAL_SetBlendMode(int srcC, int dstC, int srcA, int dstA) { - -} -void METAL_StrokeLine(float x1, float y1, float x2, float y2) { - -} -void METAL_StrokeCircle(float x, float y, float rad) { - -} -void METAL_StrokeEllipse(float x, float y, float w, float h) { - -} -void METAL_StrokeRectangle(float x, float y, float w, float h) { - -} -void METAL_FillCircle(float x, float y, float rad) { - -} -void METAL_FillEllipse(float x, float y, float w, float h) { - -} -void METAL_FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { - -} -void METAL_FillRectangle(float x, float y, float w, float h) { - -} -void METAL_DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { - -} diff --git a/source/Engine/Rendering/ModelRenderer.cpp b/source/Engine/Rendering/ModelRenderer.cpp index cf183117..30ea31c7 100644 --- a/source/Engine/Rendering/ModelRenderer.cpp +++ b/source/Engine/Rendering/ModelRenderer.cpp @@ -1,43 +1,8 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include - -class ModelRenderer { -public: - PolygonRenderer* PolyRenderer; - VertexBuffer* Buffer; - - VertexAttribute* AttribBuffer; - VertexAttribute* Vertex; - FaceInfo* FaceItem; - - Matrix4x4* ModelMatrix; - Matrix4x4* ViewMatrix; - Matrix4x4* ProjectionMatrix; - Matrix4x4* NormalMatrix; - - Matrix4x4 MVPMatrix; - - bool DoProjection; - bool ClipFaces; - Armature* ArmaturePtr; - - Uint32 DrawMode; - Uint8 FaceCullMode; - Uint32 CurrentColor; -}; -#endif - #include #include #include -PRIVATE void ModelRenderer::Init() { +void ModelRenderer::Init() { FaceItem = &Buffer->FaceInfoBuffer[Buffer->FaceCount]; AttribBuffer = Vertex = &Buffer->Vertices[Buffer->VertexCount]; @@ -45,28 +10,28 @@ PRIVATE void ModelRenderer::Init() { ArmaturePtr = nullptr; } -PUBLIC ModelRenderer::ModelRenderer(PolygonRenderer* polyRenderer) { +ModelRenderer::ModelRenderer(PolygonRenderer* polyRenderer) { PolyRenderer = polyRenderer; Buffer = PolyRenderer->VertexBuf; Init(); } -PUBLIC ModelRenderer::ModelRenderer(VertexBuffer* buffer) { +ModelRenderer::ModelRenderer(VertexBuffer* buffer) { PolyRenderer = nullptr; Buffer = buffer; Init(); } -PUBLIC void ModelRenderer::SetMatrices(Matrix4x4* model, Matrix4x4* view, Matrix4x4* projection, Matrix4x4* normal) { +void ModelRenderer::SetMatrices(Matrix4x4* model, Matrix4x4* view, Matrix4x4* projection, Matrix4x4* normal) { ModelMatrix = model; ViewMatrix = view; ProjectionMatrix = projection; NormalMatrix = normal; } -PRIVATE void ModelRenderer::AddFace(int faceVertexCount, Material* material) { +void ModelRenderer::AddFace(int faceVertexCount, Material* material) { FaceItem->DrawMode = DrawMode; FaceItem->CullMode = FaceCullMode; FaceItem->NumVertices = faceVertexCount; @@ -83,7 +48,7 @@ PRIVATE void ModelRenderer::AddFace(int faceVertexCount, Material* material) { Buffer->VertexCount += faceVertexCount; } -PRIVATE int ModelRenderer::ClipFace(int faceVertexCount) { +int ModelRenderer::ClipFace(int faceVertexCount) { if (!ClipFaces) return faceVertexCount; @@ -114,7 +79,7 @@ PRIVATE int ModelRenderer::ClipFace(int faceVertexCount) { return faceVertexCount; } -PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Skeleton* skeleton, Matrix4x4& mvpMatrix) { +void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Skeleton* skeleton, Matrix4x4& mvpMatrix) { Vector3* positionBuffer = mesh->PositionBuffer; Vector3* normalBuffer = mesh->NormalBuffer; Vector2* uvBuffer = mesh->UVBuffer; @@ -127,7 +92,7 @@ PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Skeleton* skelet DrawMesh(model, mesh, positionBuffer, normalBuffer, uvBuffer, mvpMatrix); } -PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Uint16 animation, Uint32 frame, Matrix4x4& mvpMatrix) { +void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Uint16 animation, Uint32 frame, Matrix4x4& mvpMatrix) { Vector3* positionBuffer = mesh->PositionBuffer; Vector3* normalBuffer = mesh->NormalBuffer; Vector2* uvBuffer = mesh->UVBuffer; @@ -143,7 +108,7 @@ PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Uint16 animation DrawMesh(model, mesh, positionBuffer, normalBuffer, uvBuffer, mvpMatrix); } -PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Vector3* positionBuffer, Vector3* normalBuffer, Vector2* uvBuffer, Matrix4x4& mvpMatrix) { +void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Vector3* positionBuffer, Vector3* normalBuffer, Vector2* uvBuffer, Matrix4x4& mvpMatrix) { Material* material = mesh->MaterialIndex != -1 ? model->Materials[mesh->MaterialIndex] : nullptr; Sint32* modelVertexIndexPtr = mesh->VertexIndexBuffer; @@ -370,7 +335,7 @@ PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Vector3* positio } } -PRIVATE void ModelRenderer::DrawNode(IModel* model, ModelNode* node, Matrix4x4* world) { +void ModelRenderer::DrawNode(IModel* model, ModelNode* node, Matrix4x4* world) { size_t numMeshes = node->Meshes.size(); size_t numChildren = node->Children.size(); @@ -403,7 +368,7 @@ PRIVATE void ModelRenderer::DrawNode(IModel* model, ModelNode* node, Matrix4x4* DrawNode(model, node->Children[i], world); } -PRIVATE void ModelRenderer::DrawModelInternal(IModel* model, Uint16 animation, Uint32 frame) { +void ModelRenderer::DrawModelInternal(IModel* model, Uint16 animation, Uint32 frame) { if (DoProjection) Graphics::CalculateMVPMatrix(&MVPMatrix, ModelMatrix, ViewMatrix, ProjectionMatrix); else @@ -422,7 +387,7 @@ PRIVATE void ModelRenderer::DrawModelInternal(IModel* model, Uint16 animation, U } } -PUBLIC void ModelRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 frame) { +void ModelRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 frame) { Uint16 numAnims = model->AnimationCount; if (numAnims > 0) { if (animation >= numAnims) diff --git a/source/Engine/Rendering/PolygonRenderer.cpp b/source/Engine/Rendering/PolygonRenderer.cpp index 2014b164..6e305395 100644 --- a/source/Engine/Rendering/PolygonRenderer.cpp +++ b/source/Engine/Rendering/PolygonRenderer.cpp @@ -1,34 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include -#include - -class PolygonRenderer { -public: - Scene3D* ScenePtr = nullptr; - VertexBuffer* VertexBuf = nullptr; - Matrix4x4* ModelMatrix = nullptr; - Matrix4x4* NormalMatrix = nullptr; - Matrix4x4* ViewMatrix = nullptr; - Matrix4x4* ProjectionMatrix = nullptr; - - Uint32 DrawMode = 0; - Uint8 FaceCullMode = 0; - Uint32 CurrentColor = 0; - - bool DoProjection = false; - bool DoClipping = false; - bool ClipPolygonsByFrustum = false; - int NumFrustumPlanes = 0; - Frustum ViewFrustum[NUM_FRUSTUM_PLANES]; -}; -#endif - #include #include #include @@ -36,13 +5,13 @@ class PolygonRenderer { #include #include -PUBLIC STATIC int PolygonRenderer::FaceSortFunction(const void *a, const void *b) { +int PolygonRenderer::FaceSortFunction(const void *a, const void *b) { const FaceInfo* faceA = (const FaceInfo *)a; const FaceInfo* faceB = (const FaceInfo *)b; return faceB->Depth - faceA->Depth; } -PUBLIC void PolygonRenderer::BuildFrustumPlanes(float nearClippingPlane, float farClippingPlane) { +void PolygonRenderer::BuildFrustumPlanes(float nearClippingPlane, float farClippingPlane) { // Near ViewFrustum[0].Plane.Z = nearClippingPlane * 0x10000; ViewFrustum[0].Normal.Z = 0x10000; @@ -54,7 +23,7 @@ PUBLIC void PolygonRenderer::BuildFrustumPlanes(float nearClippingPlane, float f NumFrustumPlanes = 2; } -PUBLIC bool PolygonRenderer::SetBuffers() { +bool PolygonRenderer::SetBuffers() { VertexBuf = nullptr; ScenePtr = nullptr; ViewMatrix = nullptr; @@ -82,7 +51,7 @@ PUBLIC bool PolygonRenderer::SetBuffers() { return true; } -PUBLIC void PolygonRenderer::DrawPolygon3D(VertexAttribute* data, int vertexCount, int vertexFlag, Texture* texture) { +void PolygonRenderer::DrawPolygon3D(VertexAttribute* data, int vertexCount, int vertexFlag, Texture* texture) { VertexBuffer* vertexBuffer = VertexBuf; Uint32 colRGB = CurrentColor; @@ -167,7 +136,7 @@ PUBLIC void PolygonRenderer::DrawPolygon3D(VertexAttribute* data, int vertexCoun vertexBuffer->VertexCount += vertexCount; vertexBuffer->FaceCount++; } -PUBLIC void PolygonRenderer::DrawSceneLayer3D(SceneLayer* layer, int sx, int sy, int sw, int sh) { +void PolygonRenderer::DrawSceneLayer3D(SceneLayer* layer, int sx, int sy, int sw, int sh) { int vertexCountPerFace = 4; int tileWidth = Scene::TileWidth; int tileHeight = Scene::TileHeight; @@ -340,7 +309,7 @@ PUBLIC void PolygonRenderer::DrawSceneLayer3D(SceneLayer* layer, int sx, int sy, vertexBuffer->VertexCount = arrayVertexCount; vertexBuffer->FaceCount = arrayFaceCount; } -PUBLIC void PolygonRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 frame) { +void PolygonRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 frame) { if (animation < 0 || frame < 0) return; else if (model->AnimationCount > 0 && animation >= model->AnimationCount) @@ -360,7 +329,7 @@ PUBLIC void PolygonRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 f rend.SetMatrices(ModelMatrix, ViewMatrix, ProjectionMatrix, NormalMatrix); rend.DrawModel(model, animation, frame); } -PUBLIC void PolygonRenderer::DrawModelSkinned(IModel* model, Uint16 armature) { +void PolygonRenderer::DrawModelSkinned(IModel* model, Uint16 armature) { if (model->UseVertexAnimation) { DrawModel(model, 0, 0); return; @@ -384,7 +353,7 @@ PUBLIC void PolygonRenderer::DrawModelSkinned(IModel* model, Uint16 armature) { rend.SetMatrices(ModelMatrix, ViewMatrix, ProjectionMatrix, NormalMatrix); rend.DrawModel(model, 0, 0); } -PUBLIC void PolygonRenderer::DrawVertexBuffer() { +void PolygonRenderer::DrawVertexBuffer() { Matrix4x4 mvpMatrix; if (DoProjection) Graphics::CalculateMVPMatrix(&mvpMatrix, ModelMatrix, ViewMatrix, ProjectionMatrix); @@ -473,7 +442,7 @@ PUBLIC void PolygonRenderer::DrawVertexBuffer() { destVertexBuffer->VertexCount = arrayVertexCount; destVertexBuffer->FaceCount = arrayFaceCount; } -PUBLIC int PolygonRenderer::ClipPolygon(PolygonClipBuffer& clipper, VertexAttribute* input, int numVertices) { +int PolygonRenderer::ClipPolygon(PolygonClipBuffer& clipper, VertexAttribute* input, int numVertices) { clipper.NumPoints = 0; clipper.MaxPoints = MAX_POLYGON_VERTICES; @@ -483,7 +452,7 @@ PUBLIC int PolygonRenderer::ClipPolygon(PolygonClipBuffer& clipper, VertexAttrib return numOutVertices; } -PUBLIC STATIC bool PolygonRenderer::CheckPolygonVisible(VertexAttribute* vertex, int vertexCount) { +bool PolygonRenderer::CheckPolygonVisible(VertexAttribute* vertex, int vertexCount) { int numBehind[3] = { 0, 0, 0 }; int numVertices = vertexCount; while (numVertices--) { @@ -502,7 +471,7 @@ PUBLIC STATIC bool PolygonRenderer::CheckPolygonVisible(VertexAttribute* vertex, return true; } -PUBLIC STATIC void PolygonRenderer::CopyVertices(VertexAttribute* buffer, VertexAttribute* output, int numVertices) { +void PolygonRenderer::CopyVertices(VertexAttribute* buffer, VertexAttribute* output, int numVertices) { while (numVertices--) { COPY_VECTOR(output->Position, buffer->Position); COPY_NORMAL(output->Normal, buffer->Normal); diff --git a/source/Engine/Rendering/SDL2/SDL2Renderer.cpp b/source/Engine/Rendering/SDL2/SDL2Renderer.cpp index 55262179..ded9034e 100644 --- a/source/Engine/Rendering/SDL2/SDL2Renderer.cpp +++ b/source/Engine/Rendering/SDL2/SDL2Renderer.cpp @@ -1,17 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include - -class SDL2Renderer { -public: - static float RenderScale; -}; -#endif - #include #include @@ -48,7 +34,7 @@ void FindTextureID(Texture* texture) { } // Initialization and disposal functions -PUBLIC STATIC void SDL2Renderer::Init() { +void SDL2Renderer::Init() { Log::Print(Log::LOG_INFO, "Renderer: SDL2"); Uint32 flags = SDL_RENDERER_ACCELERATED; @@ -74,14 +60,14 @@ PUBLIC STATIC void SDL2Renderer::Init() { if (h > wh) RenderScale = h / wh; } -PUBLIC STATIC Uint32 SDL2Renderer::GetWindowFlags() { +Uint32 SDL2Renderer::GetWindowFlags() { return 0; } -PUBLIC STATIC void SDL2Renderer::SetVSync(bool enabled) { +void SDL2Renderer::SetVSync(bool enabled) { Graphics::VsyncEnabled = enabled; SDL_RenderSetVSync(Renderer, enabled); } -PUBLIC STATIC void SDL2Renderer::SetGraphicsFunctions() { +void SDL2Renderer::SetGraphicsFunctions() { Graphics::PixelOffset = 0.0f; Graphics::Internal.Init = SDL2Renderer::Init; @@ -142,12 +128,12 @@ PUBLIC STATIC void SDL2Renderer::SetGraphicsFunctions() { Graphics::Internal.MakeFrameBufferID = SDL2Renderer::MakeFrameBufferID; } -PUBLIC STATIC void SDL2Renderer::Dispose() { +void SDL2Renderer::Dispose() { SDL_DestroyRenderer(Renderer); } // Texture management functions -PUBLIC STATIC Texture* SDL2Renderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* SDL2Renderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture = Texture::New(format, access, width, height); texture->DriverData = Memory::TrackedCalloc("Texture::DriverData", 1, sizeof(SDL_Texture*)); @@ -161,21 +147,21 @@ PUBLIC STATIC Texture* SDL2Renderer::CreateTexture(Uint32 format, Uint32 access, return texture; } -PUBLIC STATIC int SDL2Renderer::LockTexture(Texture* texture, void** pixels, int* pitch) { +int SDL2Renderer::LockTexture(Texture* texture, void** pixels, int* pitch) { return 0; } -PUBLIC STATIC int SDL2Renderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { +int SDL2Renderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { SDL_Texture* textureData = *(SDL_Texture**)texture->DriverData; return SDL_UpdateTexture(textureData, src, pixels, pitch); } -PUBLIC STATIC int SDL2Renderer::UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV) { +int SDL2Renderer::UpdateTextureYUV(Texture* texture, SDL_Rect* src, void* pixelsY, int pitchY, void* pixelsU, int pitchU, void* pixelsV, int pitchV) { // SDL_Texture* textureData = *(SDL_Texture**)texture->DriverData; return 0; } -PUBLIC STATIC void SDL2Renderer::UnlockTexture(Texture* texture) { +void SDL2Renderer::UnlockTexture(Texture* texture) { } -PUBLIC STATIC void SDL2Renderer::DisposeTexture(Texture* texture) { +void SDL2Renderer::DisposeTexture(Texture* texture) { SDL_Texture** textureData = (SDL_Texture**)texture->DriverData; if (!textureData) return; @@ -189,7 +175,7 @@ PUBLIC STATIC void SDL2Renderer::DisposeTexture(Texture* texture) { } // Viewport and view-related functions -PUBLIC STATIC void SDL2Renderer::SetRenderTarget(Texture* texture) { +void SDL2Renderer::SetRenderTarget(Texture* texture) { if (texture == NULL) { SDL_SetRenderTarget(Renderer, NULL); } @@ -197,7 +183,7 @@ PUBLIC STATIC void SDL2Renderer::SetRenderTarget(Texture* texture) { SDL_SetRenderTarget(Renderer, *(SDL_Texture**)texture->DriverData); } } -PUBLIC STATIC void SDL2Renderer::CopyScreen(void* pixels, int width, int height) { +void SDL2Renderer::CopyScreen(void* pixels, int width, int height) { Viewport* vp = &Graphics::CurrentViewport; SDL_Rect r = { @@ -209,10 +195,10 @@ PUBLIC STATIC void SDL2Renderer::CopyScreen(void* pixels, int width, int hei SDL_RenderReadPixels(Renderer, &r, Graphics::PreferredPixelFormat, pixels, width * SDL_BYTESPERPIXEL(Graphics::PreferredPixelFormat)); } -PUBLIC STATIC void SDL2Renderer::UpdateWindowSize(int width, int height) { +void SDL2Renderer::UpdateWindowSize(int width, int height) { SDL2Renderer::UpdateViewport(); } -PUBLIC STATIC void SDL2Renderer::UpdateViewport() { +void SDL2Renderer::UpdateViewport() { Viewport* vp = &Graphics::CurrentViewport; SDL_Rect r = { (int)(vp->X * RenderScale), @@ -224,7 +210,7 @@ PUBLIC STATIC void SDL2Renderer::UpdateViewport() { SDL2Renderer::UpdateProjectionMatrix(); } -PUBLIC STATIC void SDL2Renderer::UpdateClipRect() { +void SDL2Renderer::UpdateClipRect() { ClipArea clip = Graphics::CurrentClip; if (Graphics::CurrentClip.Enabled) { SDL_Rect r = { @@ -239,20 +225,20 @@ PUBLIC STATIC void SDL2Renderer::UpdateClipRect() { SDL_RenderSetClipRect(Renderer, NULL); } } -PUBLIC STATIC void SDL2Renderer::UpdateOrtho(float left, float top, float right, float bottom) { +void SDL2Renderer::UpdateOrtho(float left, float top, float right, float bottom) { } -PUBLIC STATIC void SDL2Renderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { +void SDL2Renderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { } -PUBLIC STATIC void SDL2Renderer::UpdateProjectionMatrix() { +void SDL2Renderer::UpdateProjectionMatrix() { } -PUBLIC STATIC void SDL2Renderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { +void SDL2Renderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { Matrix4x4::Perspective(out, fov, aspect, near, far); } -PUBLIC STATIC void SDL2Renderer::GetMetalSize(int* width, int* height) { +void SDL2Renderer::GetMetalSize(int* width, int* height) { // #ifdef IOS // SDL2MetalFunc_GetMetalSize(width, height, Renderer); // #endif @@ -260,21 +246,21 @@ PUBLIC STATIC void SDL2Renderer::GetMetalSize(int* width, int* height) { } // Shader-related functions -PUBLIC STATIC void SDL2Renderer::UseShader(void* shader) { +void SDL2Renderer::UseShader(void* shader) { } -PUBLIC STATIC void SDL2Renderer::SetUniformF(int location, int count, float* values) { +void SDL2Renderer::SetUniformF(int location, int count, float* values) { } -PUBLIC STATIC void SDL2Renderer::SetUniformI(int location, int count, int* values) { +void SDL2Renderer::SetUniformI(int location, int count, int* values) { } -PUBLIC STATIC void SDL2Renderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { +void SDL2Renderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { } // These guys -PUBLIC STATIC void SDL2Renderer::Clear() { +void SDL2Renderer::Clear() { SDL_RenderClear(Renderer); int w, h, ww, wh; @@ -285,15 +271,15 @@ PUBLIC STATIC void SDL2Renderer::Clear() { if (h > wh) RenderScale = h / wh; } -PUBLIC STATIC void SDL2Renderer::Present() { +void SDL2Renderer::Present() { SDL_RenderPresent(Renderer); } // Draw mode setting functions -PUBLIC STATIC void SDL2Renderer::SetBlendColor(float r, float g, float b, float a) { +void SDL2Renderer::SetBlendColor(float r, float g, float b, float a) { SDL_SetRenderDrawColor(Renderer, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); } -PRIVATE STATIC SDL_BlendMode SDL2Renderer::GetCustomBlendMode(int srcC, int dstC, int srcA, int dstA) { +SDL_BlendMode SDL2Renderer::GetCustomBlendMode(int srcC, int dstC, int srcA, int dstA) { SDL_BlendFactor blendFactorToSDL[] = { SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, @@ -312,7 +298,7 @@ PRIVATE STATIC SDL_BlendMode SDL2Renderer::GetCustomBlendMode(int srcC, int dstC blendFactorToSDL[srcA], blendFactorToSDL[srcA], SDL_BLENDOPERATION_ADD ); } -PUBLIC STATIC void SDL2Renderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { +void SDL2Renderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { SDL_BlendMode customBlendMode = GetCustomBlendMode(srcC, dstC, srcA, dstA); if (SDL_SetRenderDrawBlendMode(Renderer, customBlendMode) == 0) return; @@ -329,46 +315,46 @@ PUBLIC STATIC void SDL2Renderer::SetBlendMode(int srcC, int dstC, int srcA, SDL_SetRenderDrawBlendMode(Renderer, SDL_BLENDMODE_NONE); } } -PUBLIC STATIC void SDL2Renderer::SetTintColor(float r, float g, float b, float a) { +void SDL2Renderer::SetTintColor(float r, float g, float b, float a) { } -PUBLIC STATIC void SDL2Renderer::SetTintMode(int mode) { +void SDL2Renderer::SetTintMode(int mode) { } -PUBLIC STATIC void SDL2Renderer::SetTintEnabled(bool enabled) { +void SDL2Renderer::SetTintEnabled(bool enabled) { } -PUBLIC STATIC void SDL2Renderer::SetLineWidth(float n) { +void SDL2Renderer::SetLineWidth(float n) { } // Primitive drawing functions -PUBLIC STATIC void SDL2Renderer::StrokeLine(float x1, float y1, float x2, float y2) { +void SDL2Renderer::StrokeLine(float x1, float y1, float x2, float y2) { } -PUBLIC STATIC void SDL2Renderer::StrokeCircle(float x, float y, float rad, float thickness) { +void SDL2Renderer::StrokeCircle(float x, float y, float rad, float thickness) { } -PUBLIC STATIC void SDL2Renderer::StrokeEllipse(float x, float y, float w, float h) { +void SDL2Renderer::StrokeEllipse(float x, float y, float w, float h) { } -PUBLIC STATIC void SDL2Renderer::StrokeRectangle(float x, float y, float w, float h) { +void SDL2Renderer::StrokeRectangle(float x, float y, float w, float h) { } -PUBLIC STATIC void SDL2Renderer::FillCircle(float x, float y, float rad) { +void SDL2Renderer::FillCircle(float x, float y, float rad) { } -PUBLIC STATIC void SDL2Renderer::FillEllipse(float x, float y, float w, float h) { +void SDL2Renderer::FillEllipse(float x, float y, float w, float h) { } -PUBLIC STATIC void SDL2Renderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void SDL2Renderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { } -PUBLIC STATIC void SDL2Renderer::FillRectangle(float x, float y, float w, float h) { +void SDL2Renderer::FillRectangle(float x, float y, float w, float h) { } // Texture drawing functions -PUBLIC STATIC void SDL2Renderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { +void SDL2Renderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { x *= RenderScale; y *= RenderScale; w *= RenderScale; @@ -397,7 +383,7 @@ PUBLIC STATIC void SDL2Renderer::DrawTexture(Texture* texture, float sx, flo } SDL_RenderCopyEx(Renderer, *textureData, &src, &dst, 0.0, NULL, (SDL_RendererFlip)flip); } -PUBLIC STATIC void SDL2Renderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void SDL2Renderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; AnimFrame animframe = sprite->Animations[animation].Frames[frame]; @@ -411,7 +397,7 @@ PUBLIC STATIC void SDL2Renderer::DrawSprite(ISprite* sprite, int animation, x + fX * animframe.OffsetX, y + fY * animframe.OffsetY, fX * sw, fY * sh); } -PUBLIC STATIC void SDL2Renderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void SDL2Renderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; AnimFrame animframe = sprite->Animations[animation].Frames[frame]; @@ -434,6 +420,6 @@ PUBLIC STATIC void SDL2Renderer::DrawSpritePart(ISprite* sprite, int animati y + fY * (sy + animframe.OffsetY), fX * sw, fY * sh); } -PUBLIC STATIC void SDL2Renderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { +void SDL2Renderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { frame->ID = 0; } diff --git a/source/Engine/Rendering/Shader.cpp b/source/Engine/Rendering/Shader.cpp index 0dff11be..2e73bfb6 100644 --- a/source/Engine/Rendering/Shader.cpp +++ b/source/Engine/Rendering/Shader.cpp @@ -1,15 +1,7 @@ -#if INTERFACE -#include -class Shader { -public: - -}; -#endif - #include #include -PUBLIC STATIC Shader* Shader::New() { +Shader* Shader::New() { Shader* texture = (Shader*)Memory::TrackedCalloc("Shader::Shader", 1, sizeof(Shader)); return texture; } diff --git a/source/Engine/Rendering/Software/PolygonRasterizer.cpp b/source/Engine/Rendering/Software/PolygonRasterizer.cpp index 3169fc79..4c0a0b87 100644 --- a/source/Engine/Rendering/Software/PolygonRasterizer.cpp +++ b/source/Engine/Rendering/Software/PolygonRasterizer.cpp @@ -1,26 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include - -class PolygonRasterizer { -public: - static bool DepthTest; - static size_t DepthBufferSize; - static Uint32* DepthBuffer; - - static bool UseDepthBuffer; - - static bool UseFog; - static float FogStart; - static float FogEnd; - static float FogDensity; - static int FogColor; - static Uint16 FogTable[0x100 + 1]; -}; -#endif - #include #include #include @@ -210,7 +187,7 @@ static void GetPolygonBounds(T* positions, int count, int& minVal, int& maxVal) return // Draws a polygon -PUBLIC STATIC void PolygonRasterizer::DrawBasic(Vector2* positions, Uint32 color, int count, BlendState blendState) { +void PolygonRasterizer::DrawBasic(Vector2* positions, Uint32 color, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -277,7 +254,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBasic(Vector2* positions, Uint32 color } } // Draws a blended polygon -PUBLIC STATIC void PolygonRasterizer::DrawBasicBlend(Vector2* positions, int* colors, int count, BlendState blendState) { +void PolygonRasterizer::DrawBasicBlend(Vector2* positions, int* colors, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -345,7 +322,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBasicBlend(Vector2* positions, int* co } } // Draws a polygon with lighting -PUBLIC STATIC void PolygonRasterizer::DrawShaded(Vector3* positions, Uint32 color, int count, BlendState blendState) { +void PolygonRasterizer::DrawShaded(Vector3* positions, Uint32 color, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -443,7 +420,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawShaded(Vector3* positions, Uint32 colo #undef DRAW_POLYGONSHADED_FOG } // Draws a blended polygon with lighting -PUBLIC STATIC void PolygonRasterizer::DrawBlendShaded(Vector3* positions, int* colors, int count, BlendState blendState) { +void PolygonRasterizer::DrawBlendShaded(Vector3* positions, int* colors, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -536,7 +513,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBlendShaded(Vector3* positions, int* c #undef DRAW_POLYGONBLENDSHADED } // Draws an affine texture mapped polygon -PUBLIC STATIC void PolygonRasterizer::DrawAffine(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState) { +void PolygonRasterizer::DrawAffine(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -672,7 +649,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawAffine(Texture* texture, Vector3* posi #undef DRAW_POLYGONAFFINE } // Draws an affine texture mapped polygon with blending -PUBLIC STATIC void PolygonRasterizer::DrawBlendAffine(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState) { +void PolygonRasterizer::DrawBlendAffine(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -890,7 +867,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBlendAffine(Texture* texture, Vector3* DRAW_PERSP_STEP(); \ } #endif -PUBLIC STATIC void PolygonRasterizer::DrawPerspective(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState) { +void PolygonRasterizer::DrawPerspective(Texture* texture, Vector3* positions, Vector2* uvs, Uint32 color, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -1012,7 +989,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawPerspective(Texture* texture, Vector3* #undef DRAW_POLYGONPERSP } // Draws a perspective-correct texture mapped polygon with blending -PUBLIC STATIC void PolygonRasterizer::DrawBlendPerspective(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState) { +void PolygonRasterizer::DrawBlendPerspective(Texture* texture, Vector3* positions, Vector2* uvs, int* colors, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -1143,7 +1120,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBlendPerspective(Texture* texture, Vec #undef DRAW_POLYGONBLENDPERSP } // Draws a polygon with depth testing -PUBLIC STATIC void PolygonRasterizer::DrawDepth(Vector3* positions, Uint32 color, int count, BlendState blendState) { +void PolygonRasterizer::DrawDepth(Vector3* positions, Uint32 color, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -1237,7 +1214,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawDepth(Vector3* positions, Uint32 color #undef DRAW_POLYGONDEPTH } // Draws a blended polygon with depth testing -PUBLIC STATIC void PolygonRasterizer::DrawBlendDepth(Vector3* positions, int* colors, int count, BlendState blendState) { +void PolygonRasterizer::DrawBlendDepth(Vector3* positions, int* colors, int count, BlendState blendState) { if (!Graphics::CurrentRenderTarget) return; @@ -1340,7 +1317,7 @@ PUBLIC STATIC void PolygonRasterizer::DrawBlendDepth(Vector3* positions, int* co #undef DRAW_POLYGONBLENDDEPTH } -PUBLIC STATIC void PolygonRasterizer::SetDepthTest(bool enabled) { +void PolygonRasterizer::SetDepthTest(bool enabled) { DepthTest = enabled; if (!DepthTest) return; @@ -1353,19 +1330,19 @@ PUBLIC STATIC void PolygonRasterizer::SetDepthTest(bool enabled) { memset(DepthBuffer, 0xFF, dpSize * sizeof(*DepthBuffer)); } -PUBLIC STATIC void PolygonRasterizer::FreeDepthBuffer(void) { +void PolygonRasterizer::FreeDepthBuffer(void) { Memory::Free(DepthBuffer); DepthBuffer = NULL; } -PUBLIC STATIC void PolygonRasterizer::SetUseDepthBuffer(bool enabled) { +void PolygonRasterizer::SetUseDepthBuffer(bool enabled) { UseDepthBuffer = enabled; } -PUBLIC STATIC void PolygonRasterizer::SetUseFog(bool enabled) { +void PolygonRasterizer::SetUseFog(bool enabled) { UseFog = enabled; } -PUBLIC STATIC void PolygonRasterizer::SetFogEquation(FogEquation equation) { +void PolygonRasterizer::SetFogEquation(FogEquation equation) { switch (equation) { case FogEquation_Exp: FogEquationFunc = FogEquationFunc_Exp; @@ -1375,16 +1352,16 @@ PUBLIC STATIC void PolygonRasterizer::SetFogEquation(FogEquation equation) { break; } } -PUBLIC STATIC void PolygonRasterizer::SetFogStart(float start) { +void PolygonRasterizer::SetFogStart(float start) { FogStart = start; } -PUBLIC STATIC void PolygonRasterizer::SetFogEnd(float end) { +void PolygonRasterizer::SetFogEnd(float end) { FogEnd = end; } -PUBLIC STATIC void PolygonRasterizer::SetFogDensity(float density) { +void PolygonRasterizer::SetFogDensity(float density) { FogDensity = density; } -PUBLIC STATIC void PolygonRasterizer::SetFogColor(float r, float g, float b) { +void PolygonRasterizer::SetFogColor(float r, float g, float b) { Uint8 colorR = (Uint32)(r * 0xFF); Uint8 colorG = (Uint32)(g * 0xFF); Uint8 colorB = (Uint32)(b * 0xFF); @@ -1392,7 +1369,7 @@ PUBLIC STATIC void PolygonRasterizer::SetFogColor(float r, float g, float b) Graphics::ConvertFromARGBtoNative(&result, 1); FogColor = result; } -PUBLIC STATIC void PolygonRasterizer::SetFogSmoothness(float smoothness) { +void PolygonRasterizer::SetFogSmoothness(float smoothness) { float value = Math::Clamp(1.0f - smoothness, 0.0f, 1.0f); if (value <= 0.0) { for (size_t i = 0; i <= 0x100; i++) diff --git a/source/Engine/Rendering/Software/Scanline.cpp b/source/Engine/Rendering/Software/Scanline.cpp index 46546938..005d61ae 100644 --- a/source/Engine/Rendering/Software/Scanline.cpp +++ b/source/Engine/Rendering/Software/Scanline.cpp @@ -1,15 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include - -class Scanline { -public: - -}; -#endif - #include #include #include @@ -38,7 +26,7 @@ class Scanline { y2 = (int)Graphics::CurrentRenderTarget->Height; \ } -PUBLIC STATIC void Scanline::Prepare(int y1, int y2) { +void Scanline::Prepare(int y1, int y2) { int scanLineCount = y2 - y1; Contour* contourPtr = &SoftwareRenderer::ContourBuffer[y1]; while (scanLineCount--) { @@ -49,7 +37,7 @@ PUBLIC STATIC void Scanline::Prepare(int y1, int y2) { } // Simple -PUBLIC STATIC void Scanline::Process(int x1, int y1, int x2, int y2) { +void Scanline::Process(int x1, int y1, int x2, int y2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -107,7 +95,7 @@ PUBLIC STATIC void Scanline::Process(int x1, int y1, int x2, int y2) { } // Blended -PUBLIC STATIC void Scanline::Process(int color1, int color2, int x1, int y1, int x2, int y2) { +void Scanline::Process(int color1, int color2, int x1, int y1, int x2, int y2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -209,7 +197,7 @@ PUBLIC STATIC void Scanline::Process(int color1, int color2, int x1, int y1, int } // With depth -PUBLIC STATIC void Scanline::ProcessDepth(int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessDepth(int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -291,7 +279,7 @@ PUBLIC STATIC void Scanline::ProcessDepth(int x1, int y1, int z1, int x2, int y2 } // With depth and blending -PUBLIC STATIC void Scanline::ProcessDepth(int color1, int color2, int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessDepth(int color1, int color2, int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -408,7 +396,7 @@ PUBLIC STATIC void Scanline::ProcessDepth(int color1, int color2, int x1, int y1 } // Textured affine -PUBLIC STATIC void Scanline::ProcessUVAffine(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessUVAffine(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -516,7 +504,7 @@ PUBLIC STATIC void Scanline::ProcessUVAffine(Vector2 uv1, Vector2 uv2, int x1, i } // Textured affine with blending -PUBLIC STATIC void Scanline::ProcessUVAffine(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessUVAffine(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -662,7 +650,7 @@ PUBLIC STATIC void Scanline::ProcessUVAffine(int color1, int color2, Vector2 uv1 } // Perspective correct -PUBLIC STATIC void Scanline::ProcessUV(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessUV(Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; @@ -776,7 +764,7 @@ PUBLIC STATIC void Scanline::ProcessUV(Vector2 uv1, Vector2 uv2, int x1, int y1, } // Perspective correct with blending -PUBLIC STATIC void Scanline::ProcessUV(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { +void Scanline::ProcessUV(int color1, int color2, Vector2 uv1, Vector2 uv2, int x1, int y1, int z1, int x2, int y2, int z2) { int xStart = x1 / 0x10000; int xEnd = x2 / 0x10000; int yStart = y1 / 0x10000; diff --git a/source/Engine/Rendering/Software/SoftwareRenderer.cpp b/source/Engine/Rendering/Software/SoftwareRenderer.cpp index af3e3908..60ee9c8b 100644 --- a/source/Engine/Rendering/Software/SoftwareRenderer.cpp +++ b/source/Engine/Rendering/Software/SoftwareRenderer.cpp @@ -1,31 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class SoftwareRenderer { -public: - static GraphicsFunctions BackendFunctions; - static Uint32 CompareColor; - static TileScanLine TileScanLineBuffer[MAX_FRAMEBUFFER_HEIGHT]; - static Sint32 SpriteDeformBuffer[MAX_FRAMEBUFFER_HEIGHT]; - static bool UseSpriteDeform; - static Contour ContourBuffer[MAX_FRAMEBUFFER_HEIGHT]; - static int MultTable[0x10000]; - static int MultTableInv[0x10000]; - static int MultSubTable[0x10000]; -}; -#endif - #include #include #include @@ -112,7 +84,7 @@ int FilterInvert[0x8000]; int FilterBlackAndWhite[0x8000]; // Initialization and disposal functions -PUBLIC STATIC void SoftwareRenderer::Init() { +void SoftwareRenderer::Init() { SoftwareRenderer::BackendFunctions.Init(); UseStencil = false; @@ -122,10 +94,10 @@ PUBLIC STATIC void SoftwareRenderer::Init() { SetDotMaskOffsetH(0); SetDotMaskOffsetV(0); } -PUBLIC STATIC Uint32 SoftwareRenderer::GetWindowFlags() { +Uint32 SoftwareRenderer::GetWindowFlags() { return Graphics::Internal.GetWindowFlags(); } -PUBLIC STATIC void SoftwareRenderer::SetGraphicsFunctions() { +void SoftwareRenderer::SetGraphicsFunctions() { for (int alpha = 0; alpha < 0x100; alpha++) { for (int color = 0; color < 0x100; color++) { MultTable[alpha << 8 | color] = (alpha * color) >> 8; @@ -231,64 +203,64 @@ PUBLIC STATIC void SoftwareRenderer::SetGraphicsFunctions() { SoftwareRenderer::BackendFunctions.MakeFrameBufferID = SoftwareRenderer::MakeFrameBufferID; } -PUBLIC STATIC void SoftwareRenderer::Dispose() { +void SoftwareRenderer::Dispose() { } -PUBLIC STATIC void SoftwareRenderer::RenderStart() { +void SoftwareRenderer::RenderStart() { for (int i = 0; i < MAX_PALETTE_COUNT; i++) Graphics::PaletteColors[i][0] &= 0xFFFFFF; } -PUBLIC STATIC void SoftwareRenderer::RenderEnd() { +void SoftwareRenderer::RenderEnd() { } // Texture management functions -PUBLIC STATIC Texture* SoftwareRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* SoftwareRenderer::CreateTexture(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture = NULL; // Texture::New(format, access, width, height); return texture; } -PUBLIC STATIC int SoftwareRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { +int SoftwareRenderer::LockTexture(Texture* texture, void** pixels, int* pitch) { return 0; } -PUBLIC STATIC int SoftwareRenderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { +int SoftwareRenderer::UpdateTexture(Texture* texture, SDL_Rect* src, void* pixels, int pitch) { return 0; } -PUBLIC STATIC void SoftwareRenderer::UnlockTexture(Texture* texture) { +void SoftwareRenderer::UnlockTexture(Texture* texture) { } -PUBLIC STATIC void SoftwareRenderer::DisposeTexture(Texture* texture) { +void SoftwareRenderer::DisposeTexture(Texture* texture) { } // Viewport and view-related functions -PUBLIC STATIC void SoftwareRenderer::SetRenderTarget(Texture* texture) { +void SoftwareRenderer::SetRenderTarget(Texture* texture) { } -PUBLIC STATIC void SoftwareRenderer::ReadFramebuffer(void* pixels, int width, int height) { +void SoftwareRenderer::ReadFramebuffer(void* pixels, int width, int height) { if (Graphics::Internal.ReadFramebuffer) Graphics::Internal.ReadFramebuffer(pixels, width, height); } -PUBLIC STATIC void SoftwareRenderer::UpdateWindowSize(int width, int height) { +void SoftwareRenderer::UpdateWindowSize(int width, int height) { Graphics::Internal.UpdateWindowSize(width, height); } -PUBLIC STATIC void SoftwareRenderer::UpdateViewport() { +void SoftwareRenderer::UpdateViewport() { Graphics::Internal.UpdateViewport(); } -PUBLIC STATIC void SoftwareRenderer::UpdateClipRect() { +void SoftwareRenderer::UpdateClipRect() { Graphics::Internal.UpdateClipRect(); } -PUBLIC STATIC void SoftwareRenderer::UpdateOrtho(float left, float top, float right, float bottom) { +void SoftwareRenderer::UpdateOrtho(float left, float top, float right, float bottom) { Graphics::Internal.UpdateOrtho(left, top, right, bottom); } -PUBLIC STATIC void SoftwareRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { +void SoftwareRenderer::UpdatePerspective(float fovy, float aspect, float nearv, float farv) { Graphics::Internal.UpdatePerspective(fovy, aspect, nearv, farv); } -PUBLIC STATIC void SoftwareRenderer::UpdateProjectionMatrix() { +void SoftwareRenderer::UpdateProjectionMatrix() { Graphics::Internal.UpdateProjectionMatrix(); } -PUBLIC STATIC void SoftwareRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { +void SoftwareRenderer::MakePerspectiveMatrix(Matrix4x4* out, float fov, float near, float far, float aspect) { float f = 1.0f / tanf(fov / 2.0f); float diff = near - far; @@ -343,7 +315,7 @@ bool CheckClipRegion(int clip_x1, int clip_y1, int clip_x2, int clip_y2) { } // Shader-related functions -PUBLIC STATIC void SoftwareRenderer::UseShader(void* shader) { +void SoftwareRenderer::UseShader(void* shader) { if (!shader) { CurrentBlendState.FilterTable = nullptr; return; @@ -367,17 +339,17 @@ PUBLIC STATIC void SoftwareRenderer::UseShader(void* shader) { } CurrentBlendState.FilterTable = &FilterCurrent[0]; } -PUBLIC STATIC void SoftwareRenderer::SetUniformF(int location, int count, float* values) { +void SoftwareRenderer::SetUniformF(int location, int count, float* values) { } -PUBLIC STATIC void SoftwareRenderer::SetUniformI(int location, int count, int* values) { +void SoftwareRenderer::SetUniformI(int location, int count, int* values) { } -PUBLIC STATIC void SoftwareRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { +void SoftwareRenderer::SetUniformTexture(Texture* texture, int uniform_index, int slot) { } -PUBLIC STATIC void SoftwareRenderer::SetFilter(int filter) { +void SoftwareRenderer::SetFilter(int filter) { switch (filter) { case Filter_NONE: CurrentBlendState.FilterTable = nullptr; @@ -392,12 +364,12 @@ PUBLIC STATIC void SoftwareRenderer::SetFilter(int filter) { } // These guys -PUBLIC STATIC void SoftwareRenderer::Clear() { +void SoftwareRenderer::Clear() { Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; memset(dstPx, 0, dstStride * Graphics::CurrentRenderTarget->Height * 4); } -PUBLIC STATIC void SoftwareRenderer::Present() { +void SoftwareRenderer::Present() { } @@ -405,14 +377,14 @@ PUBLIC STATIC void SoftwareRenderer::Present() { #define GET_R(color) ((color >> 16) & 0xFF) #define GET_G(color) ((color >> 8) & 0xFF) #define GET_B(color) ((color) & 0xFF) -PRIVATE STATIC void SoftwareRenderer::SetColor(Uint32 color) { +void SoftwareRenderer::SetColor(Uint32 color) { ColRGB = color; ColR = GET_R(color); ColG = GET_G(color); ColB = GET_B(color); Graphics::ConvertFromARGBtoNative(&ColRGB, 1); } -PUBLIC STATIC void SoftwareRenderer::SetBlendColor(float r, float g, float b, float a) { +void SoftwareRenderer::SetBlendColor(float r, float g, float b, float a) { ColR = (Uint8)(r * 0xFF); ColG = (Uint8)(g * 0xFF); ColB = (Uint8)(b * 0xFF); @@ -423,10 +395,10 @@ PUBLIC STATIC void SoftwareRenderer::SetBlendColor(float r, float g, float b CLAMP_VAL(opacity, 0x00, 0xFF); CurrentBlendState.Opacity = opacity; } -PUBLIC STATIC void SoftwareRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { +void SoftwareRenderer::SetBlendMode(int srcC, int dstC, int srcA, int dstA) { CurrentBlendState.Mode = Graphics::BlendMode; } -PUBLIC STATIC void SoftwareRenderer::SetTintColor(float r, float g, float b, float a) { +void SoftwareRenderer::SetTintColor(float r, float g, float b, float a) { int red = (int)(r * 0xFF); int green = (int)(g * 0xFF); int blue = (int)(b * 0xFF); @@ -442,45 +414,45 @@ PUBLIC STATIC void SoftwareRenderer::SetTintColor(float r, float g, float b, Graphics::ConvertFromARGBtoNative(&CurrentBlendState.Tint.Color, 1); } -PUBLIC STATIC void SoftwareRenderer::SetTintMode(int mode) { +void SoftwareRenderer::SetTintMode(int mode) { CurrentBlendState.Tint.Mode = mode; } -PUBLIC STATIC void SoftwareRenderer::SetTintEnabled(bool enabled) { +void SoftwareRenderer::SetTintEnabled(bool enabled) { CurrentBlendState.Tint.Enabled = enabled; } -PUBLIC STATIC void SoftwareRenderer::Resize(int width, int height) { +void SoftwareRenderer::Resize(int width, int height) { } -PUBLIC STATIC void SoftwareRenderer::SetClip(float x, float y, float width, float height) { +void SoftwareRenderer::SetClip(float x, float y, float width, float height) { } -PUBLIC STATIC void SoftwareRenderer::ClearClip() { +void SoftwareRenderer::ClearClip() { } -PUBLIC STATIC void SoftwareRenderer::Save() { +void SoftwareRenderer::Save() { } -PUBLIC STATIC void SoftwareRenderer::Translate(float x, float y, float z) { +void SoftwareRenderer::Translate(float x, float y, float z) { } -PUBLIC STATIC void SoftwareRenderer::Rotate(float x, float y, float z) { +void SoftwareRenderer::Rotate(float x, float y, float z) { } -PUBLIC STATIC void SoftwareRenderer::Scale(float x, float y, float z) { +void SoftwareRenderer::Scale(float x, float y, float z) { } -PUBLIC STATIC void SoftwareRenderer::Restore() { +void SoftwareRenderer::Restore() { } -PRIVATE STATIC Uint32 SoftwareRenderer::GetBlendColor() { +Uint32 SoftwareRenderer::GetBlendColor() { return ColorUtils::ToRGB(ColR, ColG, ColB); } -PUBLIC STATIC int SoftwareRenderer::ConvertBlendMode(int blendMode) { +int SoftwareRenderer::ConvertBlendMode(int blendMode) { switch (blendMode) { case BlendMode_NORMAL: return BlendFlag_TRANSPARENT; @@ -495,10 +467,10 @@ PUBLIC STATIC int SoftwareRenderer::ConvertBlendMode(int blendMode) { } return BlendFlag_OPAQUE; } -PUBLIC STATIC BlendState SoftwareRenderer::GetBlendState() { +BlendState SoftwareRenderer::GetBlendState() { return CurrentBlendState; } -PUBLIC STATIC bool SoftwareRenderer::AlterBlendState(BlendState& state) { +bool SoftwareRenderer::AlterBlendState(BlendState& state) { int blendMode = ConvertBlendMode(state.Mode); int opacity = state.Opacity; @@ -528,17 +500,17 @@ PUBLIC STATIC bool SoftwareRenderer::AlterBlendState(BlendState& state) { #define ISOLATE_G(color) (color & 0x00FF00) #define ISOLATE_B(color) (color & 0x0000FF) -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { *dst = *src; } -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { int* multInvTableAt = &MultTableInv[state.Opacity << 8]; *dst = 0xFF000000U | (multTableAt[GET_R(*src)] + multInvTableAt[GET_R(*dst)]) << 16 | (multTableAt[GET_G(*src)] + multInvTableAt[GET_G(*dst)]) << 8 | (multTableAt[GET_B(*src)] + multInvTableAt[GET_B(*dst)]); } -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { Uint32 R = (multTableAt[GET_R(*src)] << 16) + ISOLATE_R(*dst); Uint32 G = (multTableAt[GET_G(*src)] << 8) + ISOLATE_G(*dst); Uint32 B = (multTableAt[GET_B(*src)]) + ISOLATE_B(*dst); @@ -547,7 +519,7 @@ PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetAdditive(Uint32* src, Uint32* if (B > 0x0000FF) B = 0x0000FF; *dst = 0xFF000000U | R | G | B; } -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { Sint32 R = (multSubTableAt[GET_R(*src)] << 16) + ISOLATE_R(*dst); Sint32 G = (multSubTableAt[GET_G(*src)] << 8) + ISOLATE_G(*dst); Sint32 B = (multSubTableAt[GET_B(*src)]) + ISOLATE_B(*dst); @@ -556,11 +528,11 @@ PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetSubtract(Uint32* src, Uint32* if (B < 0) B = 0; *dst = 0xFF000000U | R | G | B; } -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { if ((*dst & 0xFCFCFC) == (SoftwareRenderer::CompareColor & 0xFCFCFC)) *dst = *src; } -PUBLIC STATIC void SoftwareRenderer::PixelNoFiltSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelNoFiltSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { if ((*dst & 0xFCFCFC) != (SoftwareRenderer::CompareColor & 0xFCFCFC)) *dst = *src; } @@ -575,26 +547,26 @@ static PixelFunction PixelNoFiltFunctions[] = { }; // Tinted versions -PUBLIC STATIC void SoftwareRenderer::PixelTintSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetOpaque(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { *dst = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); } -PUBLIC STATIC void SoftwareRenderer::PixelTintSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetTransparent(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { Uint32 col = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); PixelNoFiltSetTransparent(&col, dst, state, multTableAt, multSubTableAt); } -PUBLIC STATIC void SoftwareRenderer::PixelTintSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetAdditive(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { Uint32 col = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); PixelNoFiltSetAdditive(&col, dst, state, multTableAt, multSubTableAt); } -PUBLIC STATIC void SoftwareRenderer::PixelTintSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetSubtract(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { Uint32 col = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); PixelNoFiltSetSubtract(&col, dst, state, multTableAt, multSubTableAt); } -PUBLIC STATIC void SoftwareRenderer::PixelTintSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetMatchEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { if ((*dst & 0xFCFCFC) == (SoftwareRenderer::CompareColor & 0xFCFCFC)) *dst = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); } -PUBLIC STATIC void SoftwareRenderer::PixelTintSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelTintSetMatchNotEqual(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { if ((*dst & 0xFCFCFC) != (SoftwareRenderer::CompareColor & 0xFCFCFC)) *dst = 0xFF000000 | CurrentTintFunction(src, dst, state.Tint.Color, state.Tint.Amount); } @@ -629,7 +601,7 @@ static Uint32 TintFilterDest(Uint32* src, Uint32* dst, Uint32 tintColor, Uint32 return CurrentBlendState.FilterTable[GET_FILTER_COLOR(*dst)]; } -PUBLIC STATIC void SoftwareRenderer::SetTintFunction(int blendFlags) { +void SoftwareRenderer::SetTintFunction(int blendFlags) { TintFunction tintFunctions[] = { TintNormalSource, TintNormalDest, @@ -727,16 +699,16 @@ StencilTestFunction StencilFuncTest = StencilTestAlways; StencilOpFunction StencilFuncPass = StencilOpKeep; StencilOpFunction StencilFuncFail = StencilOpKeep; -PUBLIC STATIC void SoftwareRenderer::SetStencilEnabled(bool enabled) { +void SoftwareRenderer::SetStencilEnabled(bool enabled) { if (Scene::ViewCurrent >= 0) { UseStencil = enabled; Scene::Views[Scene::ViewCurrent].SetStencilEnabled(enabled); } } -PUBLIC STATIC bool SoftwareRenderer::IsStencilEnabled() { +bool SoftwareRenderer::IsStencilEnabled() { return UseStencil; } -PUBLIC STATIC void SoftwareRenderer::SetStencilTestFunc(int stencilTest) { +void SoftwareRenderer::SetStencilTestFunc(int stencilTest) { StencilTestFunction funcList[] = { StencilTestNever, StencilTestAlways, @@ -751,26 +723,26 @@ PUBLIC STATIC void SoftwareRenderer::SetStencilTestFunc(int stencilTest) { if (stencilTest >= StencilTest_Never && stencilTest <= StencilTest_GEqual) StencilFuncTest = funcList[stencilTest]; } -PUBLIC STATIC void SoftwareRenderer::SetStencilPassFunc(int stencilOp) { +void SoftwareRenderer::SetStencilPassFunc(int stencilOp) { if (stencilOp >= StencilOp_Keep && stencilOp <= StencilOp_DecrWrap) StencilFuncPass = StencilOpFunctionList[stencilOp]; } -PUBLIC STATIC void SoftwareRenderer::SetStencilFailFunc(int stencilOp) { +void SoftwareRenderer::SetStencilFailFunc(int stencilOp) { if (stencilOp >= StencilOp_Keep && stencilOp <= StencilOp_DecrWrap) StencilFuncFail = StencilOpFunctionList[stencilOp]; } -PUBLIC STATIC void SoftwareRenderer::SetStencilValue(int value) { +void SoftwareRenderer::SetStencilValue(int value) { StencilValue = value; } -PUBLIC STATIC void SoftwareRenderer::SetStencilMask(int mask) { +void SoftwareRenderer::SetStencilMask(int mask) { StencilMask = mask; } -PUBLIC STATIC void SoftwareRenderer::ClearStencil() { +void SoftwareRenderer::ClearStencil() { if (UseStencil && Graphics::CurrentView) Graphics::CurrentView->ClearStencil(); } -PUBLIC STATIC void SoftwareRenderer::PixelStencil(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelStencil(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { size_t pos = dst - (Uint32*)Graphics::CurrentRenderTarget->Pixels; View* currentView = Graphics::CurrentView; @@ -783,11 +755,11 @@ PUBLIC STATIC void SoftwareRenderer::PixelStencil(Uint32* src, Uint32* dst, Blen StencilFuncFail(buffer, StencilValue); } -PUBLIC STATIC void SoftwareRenderer::SetDotMask(int mask) { +void SoftwareRenderer::SetDotMask(int mask) { SetDotMaskH(mask); SetDotMaskV(mask); } -PUBLIC STATIC void SoftwareRenderer::SetDotMaskH(int mask) { +void SoftwareRenderer::SetDotMaskH(int mask) { if (mask < 0) mask = 0; else if (mask > 255) @@ -795,7 +767,7 @@ PUBLIC STATIC void SoftwareRenderer::SetDotMaskH(int mask) { DotMaskH = mask; } -PUBLIC STATIC void SoftwareRenderer::SetDotMaskV(int mask) { +void SoftwareRenderer::SetDotMaskV(int mask) { if (mask < 0) mask = 0; else if (mask > 255) @@ -803,14 +775,14 @@ PUBLIC STATIC void SoftwareRenderer::SetDotMaskV(int mask) { DotMaskV = mask; } -PUBLIC STATIC void SoftwareRenderer::SetDotMaskOffsetH(int offset) { +void SoftwareRenderer::SetDotMaskOffsetH(int offset) { DotMaskOffsetH = offset; } -PUBLIC STATIC void SoftwareRenderer::SetDotMaskOffsetV(int offset) { +void SoftwareRenderer::SetDotMaskOffsetV(int offset) { DotMaskOffsetV = offset; } -PUBLIC STATIC void SoftwareRenderer::PixelDotMaskH(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelDotMaskH(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { size_t pos = dst - (Uint32*)Graphics::CurrentRenderTarget->Pixels; int x = (pos % Graphics::CurrentRenderTarget->Width) + DotMaskOffsetH; @@ -822,7 +794,7 @@ PUBLIC STATIC void SoftwareRenderer::PixelDotMaskH(Uint32* src, Uint32* dst, Ble else CurrentPixelFunction(src, dst, state, multTableAt, multSubTableAt); } -PUBLIC STATIC void SoftwareRenderer::PixelDotMaskV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelDotMaskV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { size_t pos = dst - (Uint32*)Graphics::CurrentRenderTarget->Pixels; int y = (pos / Graphics::CurrentRenderTarget->Width) + DotMaskOffsetV; @@ -834,7 +806,7 @@ PUBLIC STATIC void SoftwareRenderer::PixelDotMaskV(Uint32* src, Uint32* dst, Ble else CurrentPixelFunction(src, dst, state, multTableAt, multSubTableAt); } -PUBLIC STATIC void SoftwareRenderer::PixelDotMaskHV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { +void SoftwareRenderer::PixelDotMaskHV(Uint32* src, Uint32* dst, BlendState& state, int* multTableAt, int* multSubTableAt) { size_t pos = dst - (Uint32*)Graphics::CurrentRenderTarget->Pixels; int x = (pos % Graphics::CurrentRenderTarget->Width) + DotMaskOffsetH; @@ -914,13 +886,13 @@ static int CalcVertexColor(Scene3D* scene, VertexAttribute *vertex, int normalY) } // Drawing 3D -PUBLIC STATIC void SoftwareRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { +void SoftwareRenderer::BindVertexBuffer(Uint32 vertexBufferIndex) { } -PUBLIC STATIC void SoftwareRenderer::UnbindVertexBuffer() { +void SoftwareRenderer::UnbindVertexBuffer() { } -PUBLIC STATIC void SoftwareRenderer::BindScene3D(Uint32 sceneIndex) { +void SoftwareRenderer::BindScene3D(Uint32 sceneIndex) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -932,7 +904,7 @@ PUBLIC STATIC void SoftwareRenderer::BindScene3D(Uint32 sceneIndex) { else polygonRenderer.ClipPolygonsByFrustum = false; } -PUBLIC STATIC void SoftwareRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { +void SoftwareRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 drawMode) { if (sceneIndex < 0 || sceneIndex >= MAX_3D_SCENES) return; @@ -1373,7 +1345,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawScene3D(Uint32 sceneIndex, Uint32 d #undef ORTHO_Y } -PRIVATE STATIC bool SoftwareRenderer::SetupPolygonRenderer(Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +bool SoftwareRenderer::SetupPolygonRenderer(Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (!polygonRenderer.SetBuffers()) return false; @@ -1387,23 +1359,23 @@ PRIVATE STATIC bool SoftwareRenderer::SetupPolygonRenderer(Matrix4x4* modelM return true; } -PUBLIC STATIC void SoftwareRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void SoftwareRenderer::DrawPolygon3D(void* data, int vertexCount, int vertexFlag, Texture* texture, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (SetupPolygonRenderer(modelMatrix, normalMatrix)) polygonRenderer.DrawPolygon3D((VertexAttribute*)data, vertexCount, vertexFlag, texture); } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void SoftwareRenderer::DrawSceneLayer3D(void* layer, int sx, int sy, int sw, int sh, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (SetupPolygonRenderer(modelMatrix, normalMatrix)) polygonRenderer.DrawSceneLayer3D((SceneLayer*)layer, sx, sy, sw, sh); } -PUBLIC STATIC void SoftwareRenderer::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void SoftwareRenderer::DrawModel(void* model, Uint16 animation, Uint32 frame, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (SetupPolygonRenderer(modelMatrix, normalMatrix)) polygonRenderer.DrawModel((IModel*)model, animation, frame); } -PUBLIC STATIC void SoftwareRenderer::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void SoftwareRenderer::DrawModelSkinned(void* model, Uint16 armature, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (SetupPolygonRenderer(modelMatrix, normalMatrix)) polygonRenderer.DrawModelSkinned((IModel*)model, armature); } -PUBLIC STATIC void SoftwareRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { +void SoftwareRenderer::DrawVertexBuffer(Uint32 vertexBufferIndex, Matrix4x4* modelMatrix, Matrix4x4* normalMatrix) { if (Graphics::CurrentScene3D < 0 || vertexBufferIndex < 0 || vertexBufferIndex >= MAX_VERTEX_BUFFERS) return; @@ -1429,7 +1401,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawVertexBuffer(Uint32 vertexBufferInd rend.DrawVertexBuffer(); } -PUBLIC STATIC PixelFunction SoftwareRenderer::GetPixelFunction(int blendFlag) { +PixelFunction SoftwareRenderer::GetPixelFunction(int blendFlag) { if (blendFlag & BlendFlag_TINT_BIT) CurrentPixelFunction = PixelTintFunctions[blendFlag & BlendFlag_MODE_MASK]; else @@ -1495,10 +1467,10 @@ static void DoLineStrokeBounded(int dst_x1, int dst_y1, int dst_x2, int dst_y2, } } -PUBLIC STATIC void SoftwareRenderer::SetLineWidth(float n) { +void SoftwareRenderer::SetLineWidth(float n) { } -PUBLIC STATIC void SoftwareRenderer::StrokeLine(float x1, float y1, float x2, float y2) { +void SoftwareRenderer::StrokeLine(float x1, float y1, float x2, float y2) { int x = 0, y = 0; Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; @@ -1543,7 +1515,7 @@ PUBLIC STATIC void SoftwareRenderer::StrokeLine(float x1, float y1, float x2 DoLineStrokeBounded(dst_x1, dst_y1, dst_x2, dst_y2, minX, maxX, minY, maxY, pixelFunction, ColRGB, blendState, multTableAt, multSubTableAt, dstPx, dstStride); } -PUBLIC STATIC void SoftwareRenderer::StrokeCircle(float x, float y, float rad, float thickness) { +void SoftwareRenderer::StrokeCircle(float x, float y, float rad, float thickness) { Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; @@ -1636,7 +1608,7 @@ PUBLIC STATIC void SoftwareRenderer::StrokeCircle(float x, float y, float ra #undef DRAW_POINT } -PRIVATE STATIC void SoftwareRenderer::InitContour(Contour *contourBuffer, int dst_y1, int scanLineCount) { +void SoftwareRenderer::InitContour(Contour *contourBuffer, int dst_y1, int scanLineCount) { Contour* contourPtr = &contourBuffer[dst_y1]; while (scanLineCount--) { contourPtr->MinX = 0x7FFFFFFF; @@ -1644,7 +1616,7 @@ PRIVATE STATIC void SoftwareRenderer::InitContour(Contour *contourBuffer, in contourPtr++; } } -PRIVATE STATIC void SoftwareRenderer::RasterizeCircle(int ccx, int ccy, int dst_x1, int dst_y1, int dst_x2, int dst_y2, float rad, Contour *contourBuffer) { +void SoftwareRenderer::RasterizeCircle(int ccx, int ccy, int dst_x1, int dst_y1, int dst_x2, int dst_y2, float rad, Contour *contourBuffer) { #define SEEK_MIN(our_x, our_y) if (our_y >= dst_y1 && our_y < dst_y2 && our_x < (cont = &contourBuffer[our_y])->MinX) \ cont->MinX = our_x < dst_x1 ? dst_x1 : our_x > (dst_x2 - 1) ? dst_x2 - 1 : our_x; #define SEEK_MAX(our_x, our_y) if (our_y >= dst_y1 && our_y < dst_y2 && our_x > (cont = &contourBuffer[our_y])->MaxX) \ @@ -1677,7 +1649,7 @@ PRIVATE STATIC void SoftwareRenderer::RasterizeCircle(int ccx, int ccy, int #undef SEEK_MIN #undef SEEK_MAX } -PRIVATE STATIC void SoftwareRenderer::StrokeThickCircle(float x, float y, float rad, float thickness) { +void SoftwareRenderer::StrokeThickCircle(float x, float y, float rad, float thickness) { Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; @@ -1828,10 +1800,10 @@ PRIVATE STATIC void SoftwareRenderer::StrokeThickCircle(float x, float y, fl } } } -PUBLIC STATIC void SoftwareRenderer::StrokeEllipse(float x, float y, float w, float h) { +void SoftwareRenderer::StrokeEllipse(float x, float y, float w, float h) { } -PUBLIC STATIC void SoftwareRenderer::StrokeRectangle(float x, float y, float w, float h) { +void SoftwareRenderer::StrokeRectangle(float x, float y, float w, float h) { Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; @@ -1899,7 +1871,7 @@ PUBLIC STATIC void SoftwareRenderer::StrokeRectangle(float x, float y, float DoLineStroke(dst_x2 - 1, dst_y1 + 1, dst_x2 - 1, dst_y2 - 1, pixelFunction, col, blendState, multTableAt, multSubTableAt, dstPx, dstStride); } -PUBLIC STATIC void SoftwareRenderer::FillCircle(float x, float y, float rad) { +void SoftwareRenderer::FillCircle(float x, float y, float rad) { // just checks to see if the pixel is within a radius range, uses a bounding box constructed by the diameter Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; @@ -2002,10 +1974,10 @@ PUBLIC STATIC void SoftwareRenderer::FillCircle(float x, float y, float rad) #undef SEEK_MIN #undef SEEK_MAX } -PUBLIC STATIC void SoftwareRenderer::FillEllipse(float x, float y, float w, float h) { +void SoftwareRenderer::FillEllipse(float x, float y, float w, float h) { } -PUBLIC STATIC void SoftwareRenderer::FillRectangle(float x, float y, float w, float h) { +void SoftwareRenderer::FillRectangle(float x, float y, float w, float h) { Uint32* dstPx = (Uint32*)Graphics::CurrentRenderTarget->Pixels; Uint32 dstStride = Graphics::CurrentRenderTarget->Width; @@ -2076,7 +2048,7 @@ PUBLIC STATIC void SoftwareRenderer::FillRectangle(float x, float y, float w } } } -PUBLIC STATIC void SoftwareRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { +void SoftwareRenderer::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2102,7 +2074,7 @@ PUBLIC STATIC void SoftwareRenderer::FillTriangle(float x1, float y1, float vectors[2].X = ((int)x3 + x) << 16; vectors[2].Y = ((int)y3 + y) << 16; PolygonRasterizer::DrawBasic(vectors, ColRGB, 3, blendState); } -PUBLIC STATIC void SoftwareRenderer::FillTriangleBlend(float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3) { +void SoftwareRenderer::FillTriangleBlend(float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2129,7 +2101,7 @@ PUBLIC STATIC void SoftwareRenderer::FillTriangleBlend(float x1, float y1, f vectors[2].X = ((int)x3 + x) << 16; vectors[2].Y = ((int)y3 + y) << 16; colors[2] = ColorUtils::Multiply(c3, GetBlendColor()); PolygonRasterizer::DrawBasicBlend(vectors, colors, 3, blendState); } -PUBLIC STATIC void SoftwareRenderer::FillQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { +void SoftwareRenderer::FillQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2156,7 +2128,7 @@ PUBLIC STATIC void SoftwareRenderer::FillQuad(float x1, float y1, float x2, vectors[3].X = ((int)x4 + x) << 16; vectors[3].Y = ((int)y4 + y) << 16; PolygonRasterizer::DrawBasic(vectors, ColRGB, 4, blendState); } -PUBLIC STATIC void SoftwareRenderer::FillQuadBlend(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4) { +void SoftwareRenderer::FillQuadBlend(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2184,7 +2156,7 @@ PUBLIC STATIC void SoftwareRenderer::FillQuadBlend(float x1, float y1, float vectors[3].X = ((int)x4 + x) << 16; vectors[3].Y = ((int)y4 + y) << 16; colors[3] = ColorUtils::Multiply(c4, GetBlendColor()); PolygonRasterizer::DrawBasicBlend(vectors, colors, 4, blendState); } -PRIVATE STATIC void SoftwareRenderer::DrawShapeTextured(Texture* texturePtr, unsigned numPoints, float* px, float* py, int* pc, float* pu, float* pv) { +void SoftwareRenderer::DrawShapeTextured(Texture* texturePtr, unsigned numPoints, float* px, float* py, int* pc, float* pu, float* pv) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2222,7 +2194,7 @@ PRIVATE STATIC void SoftwareRenderer::DrawShapeTextured(Texture* texturePtr, PolygonRasterizer::DrawBlendPerspective(texturePtr, vectors, uv, colors, numPoints, blendState); } -PUBLIC STATIC void SoftwareRenderer::DrawTriangleTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3, float u1, float v1, float u2, float v2, float u3, float v3) { +void SoftwareRenderer::DrawTriangleTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, int c1, int c2, int c3, float u1, float v1, float u2, float v2, float u3, float v3) { float px[3]; float py[3]; float pu[3]; @@ -2249,7 +2221,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawTriangleTextured(Texture* texturePt DrawShapeTextured(texturePtr, 3, px, py, pc, pu, pv); } -PUBLIC STATIC void SoftwareRenderer::DrawQuadTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4, float u1, float v1, float u2, float v2, float u3, float v3, float u4, float v4) { +void SoftwareRenderer::DrawQuadTextured(Texture* texturePtr, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int c1, int c2, int c3, int c4, float u1, float v1, float u2, float v2, float u3, float v3, float u4, float v4) { float px[4]; float py[4]; float pu[4]; @@ -2820,7 +2792,7 @@ void DrawSpriteImageTransformed(Texture* texture, int x, int y, int offx, int of #undef DRAW_FLIPXY } -PUBLIC STATIC void SoftwareRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { +void SoftwareRenderer::DrawTexture(Texture* texture, float sx, float sy, float sw, float sh, float x, float y, float w, float h) { View* currentView = Graphics::CurrentView; if (!currentView) return; @@ -2848,7 +2820,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawTexture(Texture* texture, float sx, else DrawSpriteImage(texture, x, y, sw, sh, sx, sy, 0, 0, blendState); } -PUBLIC STATIC void SoftwareRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void SoftwareRenderer::DrawSprite(ISprite* sprite, int animation, int frame, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; View* currentView = Graphics::CurrentView; @@ -2909,7 +2881,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawSprite(ISprite* sprite, int animati break; } } -PUBLIC STATIC void SoftwareRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { +void SoftwareRenderer::DrawSpritePart(ISprite* sprite, int animation, int frame, int sx, int sy, int sw, int sh, int x, int y, bool flipX, bool flipY, float scaleW, float scaleH, float rotation, unsigned paletteID) { if (Graphics::SpriteRangeCheck(sprite, animation, frame)) return; View* currentView = Graphics::CurrentView; @@ -2977,10 +2949,10 @@ PUBLIC STATIC void SoftwareRenderer::DrawSpritePart(ISprite* sprite, int ani } // Default Tile Display Line setup -PUBLIC STATIC void SoftwareRenderer::DrawTile(int tile, int x, int y, bool flipX, bool flipY) { +void SoftwareRenderer::DrawTile(int tile, int x, int y, bool flipX, bool flipY) { } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_InitTileScanLines(SceneLayer* layer, View* currentView) { +void SoftwareRenderer::DrawSceneLayer_InitTileScanLines(SceneLayer* layer, View* currentView) { switch (layer->DrawBehavior) { case DrawBehavior_PGZ1_BG: case DrawBehavior_HorizontalParallax: { @@ -3107,7 +3079,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_InitTileScanLines(SceneL } } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView) { +void SoftwareRenderer::DrawSceneLayer_HorizontalParallax(SceneLayer* layer, View* currentView) { int dst_x1 = 0; int dst_y1 = 0; int dst_x2 = (int)Graphics::CurrentRenderTarget->Width; @@ -3578,10 +3550,10 @@ PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_HorizontalParallax(Scene } } } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView) { +void SoftwareRenderer::DrawSceneLayer_VerticalParallax(SceneLayer* layer, View* currentView) { } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_CustomTileScanLines(SceneLayer* layer, View* currentView) { +void SoftwareRenderer::DrawSceneLayer_CustomTileScanLines(SceneLayer* layer, View* currentView) { int dst_x1 = 0; int dst_y1 = 0; int dst_x2 = (int)Graphics::CurrentRenderTarget->Width; @@ -3736,7 +3708,7 @@ PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer_CustomTileScanLines(Scen dst_strideY += dstStride; } } -PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction) { +void SoftwareRenderer::DrawSceneLayer(SceneLayer* layer, View* currentView, int layerIndex, bool useCustomFunction) { if (layer->UsingCustomRenderFunction && useCustomFunction) { Graphics::RunCustomSceneLayerFunction(&layer->CustomRenderFunction, layerIndex); return; @@ -3763,6 +3735,6 @@ PUBLIC STATIC void SoftwareRenderer::DrawSceneLayer(SceneLayer* layer, View* } } -PUBLIC STATIC void SoftwareRenderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { +void SoftwareRenderer::MakeFrameBufferID(ISprite* sprite, AnimFrame* frame) { frame->ID = 0; } diff --git a/source/Engine/Rendering/Texture.cpp b/source/Engine/Rendering/Texture.cpp index 5e4df7f2..f161262b 100644 --- a/source/Engine/Rendering/Texture.cpp +++ b/source/Engine/Rendering/Texture.cpp @@ -1,36 +1,9 @@ -#if INTERFACE -#include - -need_t Texture; - -class Texture { -public: - Uint32 Format; - Uint32 Access; - Uint32 Width; - Uint32 Height; - - void* Pixels; - int Pitch; - - Uint32 ID; - void* DriverData; - - Texture* Prev; - Texture* Next; - - bool Paletted; - Uint32* PaletteColors; - unsigned NumPaletteColors; -}; -#endif - #include #include #include #include -PUBLIC STATIC Texture* Texture::New(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { +Texture* Texture::New(Uint32 format, Uint32 access, Uint32 width, Uint32 height) { Texture* texture = (Texture*)Memory::TrackedCalloc("Texture::Texture", 1, sizeof(Texture)); texture->Format = format; texture->Access = access; @@ -40,7 +13,7 @@ PUBLIC STATIC Texture* Texture::New(Uint32 format, Uint32 access, Uint32 width, return texture; } -PUBLIC void Texture::SetPalette(Uint32* palette, unsigned numPaletteColors) { +void Texture::SetPalette(Uint32* palette, unsigned numPaletteColors) { Memory::Free(PaletteColors); if (palette && numPaletteColors) { @@ -55,7 +28,7 @@ PUBLIC void Texture::SetPalette(Uint32* palette, unsigned numPaletteC } } -PUBLIC bool Texture::ConvertToRGBA() { + bool Texture::ConvertToRGBA() { if (!Paletted) return false; @@ -70,7 +43,7 @@ PUBLIC bool Texture::ConvertToRGBA() { return true; } -PUBLIC bool Texture::ConvertToPalette(Uint32 *palColors, unsigned numPaletteColors) { + bool Texture::ConvertToPalette(Uint32 *palColors, unsigned numPaletteColors) { ConvertToRGBA(); Uint32 *pixels = (Uint32*)Pixels; @@ -101,7 +74,7 @@ PUBLIC bool Texture::ConvertToPalette(Uint32 *palColors, unsigned numPa return true; } -PUBLIC void Texture::Copy(Texture* source) { +void Texture::Copy(Texture* source) { if (!Pixels || !source || !source->Pixels) return; @@ -117,7 +90,7 @@ PUBLIC void Texture::Copy(Texture* source) { } } -PUBLIC void Texture::Dispose() { +void Texture::Dispose() { Memory::Free(PaletteColors); Memory::Free(Pixels); diff --git a/source/Engine/Rendering/TextureReference.cpp b/source/Engine/Rendering/TextureReference.cpp index 745e0477..d12bea0e 100644 --- a/source/Engine/Rendering/TextureReference.cpp +++ b/source/Engine/Rendering/TextureReference.cpp @@ -1,29 +1,16 @@ -#if INTERFACE -#include - -need_t Texture; - -class TextureReference { -public: - Texture* TexturePtr; - - unsigned References; -}; -#endif - #include -PUBLIC TextureReference::TextureReference(Texture *ptr) { +TextureReference::TextureReference(Texture *ptr) { TexturePtr = ptr; References = 0; AddRef(); } -PUBLIC void TextureReference::AddRef() { +void TextureReference::AddRef() { References++; } -PUBLIC bool TextureReference::TakeRef() { +bool TextureReference::TakeRef() { if (References == 0) abort(); diff --git a/source/Engine/Rendering/VertexBuffer.cpp b/source/Engine/Rendering/VertexBuffer.cpp index 2b3bf5db..f39db1da 100644 --- a/source/Engine/Rendering/VertexBuffer.cpp +++ b/source/Engine/Rendering/VertexBuffer.cpp @@ -1,45 +1,28 @@ -#if INTERFACE -#include -#include -#include - -class VertexBuffer { -public: - VertexAttribute* Vertices = nullptr; // count = max vertex count - FaceInfo* FaceInfoBuffer = nullptr; // count = max face count - void* DriverData = nullptr; - Uint32 Capacity = 0; - Uint32 VertexCount = 0; - Uint32 FaceCount = 0; - Uint32 UnloadPolicy; -}; -#endif - #include #include -PUBLIC VertexBuffer::VertexBuffer() { +VertexBuffer::VertexBuffer() { } -PUBLIC VertexBuffer::VertexBuffer(Uint32 numVertices) { +VertexBuffer::VertexBuffer(Uint32 numVertices) { Init(numVertices); Clear(); } -PUBLIC void VertexBuffer::Init(Uint32 numVertices) { +void VertexBuffer::Init(Uint32 numVertices) { if (!numVertices) numVertices = 192; if (Capacity != numVertices) Resize(numVertices); } -PUBLIC void VertexBuffer::Clear() { +void VertexBuffer::Clear() { VertexCount = 0; FaceCount = 0; // Not sure why we do this memset(Vertices, 0x00, Capacity * sizeof(VertexAttribute)); } -PUBLIC void VertexBuffer::Resize(Uint32 numVertices) { +void VertexBuffer::Resize(Uint32 numVertices) { if (!numVertices) numVertices = 192; @@ -47,7 +30,7 @@ PUBLIC void VertexBuffer::Resize(Uint32 numVertices) { Vertices = (VertexAttribute*)Memory::Realloc(Vertices, numVertices * sizeof(VertexAttribute)); FaceInfoBuffer = (FaceInfo*)Memory::Realloc(FaceInfoBuffer, ((numVertices / 3) + 1) * sizeof(FaceInfo)); } -PUBLIC VertexBuffer::~VertexBuffer() { +VertexBuffer::~VertexBuffer() { Memory::Free(Vertices); Memory::Free(FaceInfoBuffer); } diff --git a/source/Engine/Rendering/ViewTexture.cpp b/source/Engine/Rendering/ViewTexture.cpp index 2e0bd4b6..aac65b1c 100644 --- a/source/Engine/Rendering/ViewTexture.cpp +++ b/source/Engine/Rendering/ViewTexture.cpp @@ -1,23 +1,13 @@ -#if INTERFACE -#include -#include - -class ViewTexture : public GameTexture { -public: - int ViewIndex; -}; -#endif - #include #include -PUBLIC ViewTexture::ViewTexture(int viewIndex) { +ViewTexture::ViewTexture(int viewIndex) { ViewIndex = viewIndex; UnloadPolicy = SCOPE_GAME; OwnsTexture = false; } -PUBLIC VIRTUAL Texture* ViewTexture::GetTexture() { +Texture* ViewTexture::GetTexture() { if (ViewIndex < 0 || ViewIndex >= MAX_SCENE_VIEWS) return nullptr; @@ -27,7 +17,7 @@ PUBLIC VIRTUAL Texture* ViewTexture::GetTexture() { return nullptr; } -PUBLIC VIRTUAL int ViewTexture::GetID() { +int ViewTexture::GetID() { // Using negative IDs makes sure they don't collide with other textures return -(ViewIndex + 1); } diff --git a/source/Engine/ResourceTypes/IModel.cpp b/source/Engine/ResourceTypes/IModel.cpp index e5790989..50bff03b 100644 --- a/source/Engine/ResourceTypes/IModel.cpp +++ b/source/Engine/ResourceTypes/IModel.cpp @@ -1,37 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include - -class IModel { -public: - Mesh** Meshes; - size_t MeshCount; - - size_t VertexCount; - size_t VertexIndexCount; - - Uint8 VertexPerFace; - - Material** Materials; - size_t MaterialCount; - - ModelAnim** Animations; - size_t AnimationCount; - - Armature** ArmatureList; - size_t ArmatureCount; - - bool UseVertexAnimation; - - Armature* BaseArmature; - Matrix4x4* GlobalInverseMatrix; -}; -#endif - #include #include #include @@ -47,7 +13,7 @@ class IModel { #include #include -PUBLIC IModel::IModel() { +IModel::IModel() { VertexCount = 0; Meshes = nullptr; @@ -69,7 +35,7 @@ PUBLIC IModel::IModel() { GlobalInverseMatrix = nullptr; UseVertexAnimation = false; } -PUBLIC IModel::IModel(const char* filename) { +IModel::IModel(const char* filename) { ResourceStream* resourceStream = ResourceStream::New(filename); if (!resourceStream) return; @@ -77,7 +43,7 @@ PUBLIC IModel::IModel(const char* filename) { if (resourceStream) resourceStream->Close(); } -PUBLIC bool IModel::Load(Stream* stream, const char* filename) { +bool IModel::Load(Stream* stream, const char* filename) { if (!stream) return false; if (!filename) return false; @@ -104,11 +70,11 @@ PUBLIC bool IModel::Load(Stream* stream, const char* filename) { return false; } -PUBLIC bool IModel::HasMaterials() { +bool IModel::HasMaterials() { return MaterialCount > 0; } -PRIVATE STATIC Image* IModel::TryLoadMaterialImage(std::string imagePath, const char *parentDirectory) { +Image* IModel::TryLoadMaterialImage(std::string imagePath, const char *parentDirectory) { std::string filename = imagePath; if (parentDirectory) { @@ -130,7 +96,7 @@ PRIVATE STATIC Image* IModel::TryLoadMaterialImage(std::string imagePath, const return nullptr; } -PUBLIC STATIC Image* IModel::LoadMaterialImage(string imagePath, const char *parentDirectory) { +Image* IModel::LoadMaterialImage(string imagePath, const char *parentDirectory) { // Try possible combinations Image* image = nullptr; @@ -148,18 +114,18 @@ PUBLIC STATIC Image* IModel::LoadMaterialImage(string imagePath, const char *par return nullptr; } -PUBLIC STATIC Image* IModel::LoadMaterialImage(const char *imagePath, const char *parentDirectory) { +Image* IModel::LoadMaterialImage(const char *imagePath, const char *parentDirectory) { return LoadMaterialImage(std::string(imagePath), parentDirectory); } -PUBLIC bool IModel::HasBones() { +bool IModel::HasBones() { if (BaseArmature == nullptr) return false; return BaseArmature->NumSkeletons > 0; } -PUBLIC void IModel::AnimateNode(ModelNode* node, SkeletalAnim* animation, Uint32 frame, Matrix4x4* parentMatrix) { +void IModel::AnimateNode(ModelNode* node, SkeletalAnim* animation, Uint32 frame, Matrix4x4* parentMatrix) { NodeAnim* nodeAnim = animation->NodeLookup->Get(node->Name); if (nodeAnim) UpdateChannel(node->LocalTransform, nodeAnim, frame); @@ -170,11 +136,11 @@ PUBLIC void IModel::AnimateNode(ModelNode* node, SkeletalAnim* animation, Uint32 AnimateNode(node->Children[i], animation, frame, node->GlobalTransform); } -PUBLIC void IModel::Pose() { +void IModel::Pose() { BaseArmature->RootNode->Transform(); } -PUBLIC void IModel::Pose(Armature* armature, SkeletalAnim* animation, Uint32 frame) { +void IModel::Pose(Armature* armature, SkeletalAnim* animation, Uint32 frame) { Matrix4x4 identity; Matrix4x4::Identity(&identity); @@ -268,11 +234,11 @@ static Vector4 InterpolateQuaternions(Vector4 q1, Vector4 q2, Sint64 t) { return result; } -PUBLIC Uint32 IModel::GetKeyFrame(Uint32 frame) { +Uint32 IModel::GetKeyFrame(Uint32 frame) { return (frame >> 8) & 0xFFFFFF; } -PUBLIC Sint64 IModel::GetInBetween(Uint32 frame) { +Sint64 IModel::GetInBetween(Uint32 frame) { float interp = (float)(frame & 0xFF) / 0xFF; Sint64 inbetween = (Sint64)(interp * 0x10000); @@ -284,7 +250,7 @@ PUBLIC Sint64 IModel::GetInBetween(Uint32 frame) { return inbetween; } -PUBLIC void IModel::DoVertexFrameInterpolation(Mesh* mesh, ModelAnim* animation, Uint32 frame, Vector3** positionBuffer, Vector3** normalBuffer, Vector2** uvBuffer) { +void IModel::DoVertexFrameInterpolation(Mesh* mesh, ModelAnim* animation, Uint32 frame, Vector3** positionBuffer, Vector3** normalBuffer, Vector2** uvBuffer) { Uint32 startFrame = 0; Uint32 animLength; @@ -339,7 +305,7 @@ PUBLIC void IModel::DoVertexFrameInterpolation(Mesh* mesh, ModelAnim* animation, } } -PRIVATE void IModel::UpdateChannel(Matrix4x4* out, NodeAnim* channel, Uint32 frame) { +void IModel::UpdateChannel(Matrix4x4* out, NodeAnim* channel, Uint32 frame) { Uint32 keyframe = GetKeyFrame(frame); Sint64 inbetween = GetInBetween(frame); @@ -376,7 +342,7 @@ PRIVATE void IModel::UpdateChannel(Matrix4x4* out, NodeAnim* channel, Uint32 fra } } -PUBLIC void IModel::Animate(Armature* armature, ModelAnim* animation, Uint32 frame) { +void IModel::Animate(Armature* armature, ModelAnim* animation, Uint32 frame) { if (animation->Skeletal == nullptr) return; @@ -388,7 +354,7 @@ PUBLIC void IModel::Animate(Armature* armature, ModelAnim* animation, Uint32 fra armature->UpdateSkeletons(); } -PUBLIC void IModel::Animate(Uint16 animation, Uint32 frame) { +void IModel::Animate(Uint16 animation, Uint32 frame) { if (AnimationCount > 0) { if (animation >= AnimationCount) animation = AnimationCount - 1; @@ -397,7 +363,7 @@ PUBLIC void IModel::Animate(Uint16 animation, Uint32 frame) { } } -PUBLIC int IModel::GetAnimationIndex(const char* animationName) { +int IModel::GetAnimationIndex(const char* animationName) { if (!AnimationCount) return -1; @@ -408,7 +374,7 @@ PUBLIC int IModel::GetAnimationIndex(const char* animationName) { return -1; } -PUBLIC int IModel::NewArmature() { +int IModel::NewArmature() { if (UseVertexAnimation) return -1; @@ -439,7 +405,7 @@ PUBLIC int IModel::NewArmature() { return ArmatureCount - 1; } -PUBLIC void IModel::DeleteArmature(size_t index) { +void IModel::DeleteArmature(size_t index) { if (ArmatureList == nullptr) return; @@ -447,7 +413,7 @@ PUBLIC void IModel::DeleteArmature(size_t index) { ArmatureList[index] = nullptr; } -PUBLIC void IModel::Dispose() { +void IModel::Dispose() { for (size_t i = 0; i < MeshCount; i++) delete Meshes[i]; delete[] Meshes; @@ -483,6 +449,6 @@ PUBLIC void IModel::Dispose() { GlobalInverseMatrix = nullptr; } -PUBLIC IModel::~IModel() { +IModel::~IModel() { Dispose(); } diff --git a/source/Engine/ResourceTypes/ISound.cpp b/source/Engine/ResourceTypes/ISound.cpp index 7a8f6189..23274161 100644 --- a/source/Engine/ResourceTypes/ISound.cpp +++ b/source/Engine/ResourceTypes/ISound.cpp @@ -1,24 +1,3 @@ -#if INTERFACE -#include -#include -#include - -#include -#include - -class ISound { -public: - SDL_AudioSpec Format; - int BytesPerSample; - - SoundFormat* SoundData = NULL; - - char Filename[256]; - bool LoadFailed = false; - bool StreamFromFile = false; -}; -#endif - #include #include #include @@ -29,14 +8,14 @@ class ISound { #include #include -PUBLIC ISound::ISound(const char* filename) { +ISound::ISound(const char* filename) { ISound::Load(filename, true); } -PUBLIC ISound::ISound(const char* filename, bool streamFromFile) { +ISound::ISound(const char* filename, bool streamFromFile) { ISound::Load(filename, streamFromFile); } -PUBLIC void ISound::Load(const char* filename, bool streamFromFile) { +void ISound::Load(const char* filename, bool streamFromFile) { LoadFailed = true; StreamFromFile = streamFromFile; strcpy(Filename, filename); @@ -87,7 +66,7 @@ PUBLIC void ISound::Load(const char* filename, bool streamFromFile) { LoadFailed = false; } -PUBLIC AudioPlayback* ISound::CreatePlayer() { +AudioPlayback* ISound::CreatePlayer() { int requiredSamples = AudioManager::DeviceFormat.samples * AUDIO_FIRST_LOAD_SAMPLE_BOOST; AudioPlayback* playback = new AudioPlayback(Format, requiredSamples, BytesPerSample, AudioManager::BytesPerSample); @@ -97,7 +76,7 @@ PUBLIC AudioPlayback* ISound::CreatePlayer() { return playback; } -PUBLIC void ISound::Dispose() { +void ISound::Dispose() { if (SoundData) { SoundData->Dispose(); delete SoundData; diff --git a/source/Engine/ResourceTypes/ISprite.cpp b/source/Engine/ResourceTypes/ISprite.cpp index c36ab635..1123617c 100644 --- a/source/Engine/ResourceTypes/ISprite.cpp +++ b/source/Engine/ResourceTypes/ISprite.cpp @@ -1,22 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class ISprite { -public: - char* Filename = nullptr; - - bool LoadFailed = true; - - vector Spritesheets; - vector SpritesheetFilenames; - int CollisionBoxCount = 0; - - vector Animations; -}; -#endif - #include #include @@ -35,7 +16,7 @@ class ISprite { #include -PUBLIC ISprite::ISprite() { +ISprite::ISprite() { Spritesheets.clear(); Spritesheets.shrink_to_fit(); SpritesheetFilenames.clear(); @@ -43,7 +24,7 @@ PUBLIC ISprite::ISprite() { LoadFailed = true; Filename = nullptr; } -PUBLIC ISprite::ISprite(const char* filename) { +ISprite::ISprite(const char* filename) { Spritesheets.clear(); Spritesheets.shrink_to_fit(); SpritesheetFilenames.clear(); @@ -52,7 +33,7 @@ PUBLIC ISprite::ISprite(const char* filename) { LoadFailed = !LoadAnimation(Filename); } -PUBLIC Texture* ISprite::AddSpriteSheet(const char* filename) { +Texture* ISprite::AddSpriteSheet(const char* filename) { Texture* texture = NULL; Uint32* data = NULL; Uint32 width = 0; @@ -170,10 +151,10 @@ PUBLIC Texture* ISprite::AddSpriteSheet(const char* filename) { return texture; } -PUBLIC void ISprite::ReserveAnimationCount(int count) { +void ISprite::ReserveAnimationCount(int count) { Animations.reserve(count); } -PUBLIC void ISprite::AddAnimation(const char* name, int animationSpeed, int frameToLoop) { +void ISprite::AddAnimation(const char* name, int animationSpeed, int frameToLoop) { size_t strl = strlen(name); Animation an; @@ -185,17 +166,17 @@ PUBLIC void ISprite::AddAnimation(const char* name, int animationSpeed, int fram an.Flags = 0; Animations.push_back(an); } -PUBLIC void ISprite::AddAnimation(const char* name, int animationSpeed, int frameToLoop, int frmAlloc) { +void ISprite::AddAnimation(const char* name, int animationSpeed, int frameToLoop, int frmAlloc) { AddAnimation(name, animationSpeed, frameToLoop); Animations.back().Frames.reserve(frmAlloc); } -PUBLIC void ISprite::AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY) { +void ISprite::AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY) { ISprite::AddFrame(duration, left, top, width, height, pivotX, pivotY, 0); } -PUBLIC void ISprite::AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id) { +void ISprite::AddFrame(int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id) { AddFrame(Animations.size() - 1, duration, left, top, width, height, pivotX, pivotY, id); } -PUBLIC void ISprite::AddFrame(int animID, int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id) { +void ISprite::AddFrame(int animID, int duration, int left, int top, int width, int height, int pivotX, int pivotY, int id) { AnimFrame anfrm; anfrm.Advance = id; anfrm.Duration = duration; @@ -213,24 +194,24 @@ PUBLIC void ISprite::AddFrame(int animID, int duration, int left, int top, int w Animations[animID].Frames.push_back(anfrm); } -PUBLIC void ISprite::RemoveFrames(int animID) { +void ISprite::RemoveFrames(int animID) { for (size_t i = 0; i < Animations[animID].Frames.size(); i++) Graphics::DeleteFrameBufferID(&Animations[animID].Frames[i]); Animations[animID].Frames.clear(); } -PUBLIC void ISprite::ConvertToRGBA() { +void ISprite::ConvertToRGBA() { for (int a = 0; a < Spritesheets.size(); a++) { Graphics::ConvertTextureToRGBA(Spritesheets[a]); } } -PUBLIC void ISprite::ConvertToPalette(unsigned paletteNumber) { +void ISprite::ConvertToPalette(unsigned paletteNumber) { for (int a = 0; a < Spritesheets.size(); a++) { Graphics::ConvertTextureToPalette(Spritesheets[a], paletteNumber); } } -PUBLIC bool ISprite::LoadAnimation(const char* filename) { +bool ISprite::LoadAnimation(const char* filename) { char* str; int animationCount, previousAnimationCount; @@ -388,17 +369,17 @@ PUBLIC bool ISprite::LoadAnimation(const char* filename) { return true; } -PUBLIC int ISprite::FindAnimation(const char* animname) { +int ISprite::FindAnimation(const char* animname) { for (Uint32 a = 0; a < Animations.size(); a++) if (Animations[a].Name[0] == animname[0] && !strcmp(Animations[a].Name, animname)) return a; return -1; } -PUBLIC void ISprite::LinkAnimation(vector ani) { +void ISprite::LinkAnimation(vector ani) { Animations = ani; } -PUBLIC bool ISprite::SaveAnimation(const char* filename) { +bool ISprite::SaveAnimation(const char* filename) { Stream* stream = FileStream::New(filename, FileStream::WRITE_ACCESS); if (!stream) { Log::Print(Log::LOG_ERROR, "Couldn't open file '%s'!", filename); @@ -479,7 +460,7 @@ PUBLIC bool ISprite::SaveAnimation(const char* filename) { return true; } -PUBLIC void ISprite::Dispose() { +void ISprite::Dispose() { for (size_t a = 0; a < Animations.size(); a++) { for (size_t i = 0; i < Animations[a].Frames.size(); i++) { AnimFrame* anfrm = &Animations[a].Frames[i]; @@ -516,6 +497,6 @@ PUBLIC void ISprite::Dispose() { Filename = nullptr; } -PUBLIC ISprite::~ISprite() { +ISprite::~ISprite() { Dispose(); } diff --git a/source/Engine/ResourceTypes/Image.cpp b/source/Engine/ResourceTypes/Image.cpp index 97c4c6d7..ee67c2e2 100644 --- a/source/Engine/ResourceTypes/Image.cpp +++ b/source/Engine/ResourceTypes/Image.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include - -class Image { -public: - char Filename[256]; - Texture* TexturePtr = NULL; -}; -#endif - #include #include @@ -25,23 +14,23 @@ class Image { #include #include -PUBLIC Image::Image(const char* filename) { +Image::Image(const char* filename) { strncpy(Filename, filename, 255); TexturePtr = Image::LoadTextureFromResource(Filename); } -PUBLIC void Image::Dispose() { +void Image::Dispose() { if (TexturePtr) { Graphics::DisposeTexture(TexturePtr); TexturePtr = NULL; } } -PUBLIC Image::~Image() { +Image::~Image() { Dispose(); } -PUBLIC STATIC Texture* Image::LoadTextureFromResource(const char* filename) { +Texture* Image::LoadTextureFromResource(const char* filename) { Texture* texture = NULL; Uint32* data = NULL; Uint32 width = 0; diff --git a/source/Engine/ResourceTypes/ImageFormats/GIF.cpp b/source/Engine/ResourceTypes/ImageFormats/GIF.cpp index ba9979cc..bd32368c 100644 --- a/source/Engine/ResourceTypes/ImageFormats/GIF.cpp +++ b/source/Engine/ResourceTypes/ImageFormats/GIF.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class GIF : public ImageFormat { -public: - vector Frames; -}; -#endif - #include #include @@ -34,7 +23,7 @@ struct Entry { Uint8 Suffix; }; -PRIVATE STATIC inline Uint32 GIF::ReadCode(Stream* stream, int codeSize, int* blockLength, int* bitCache, int* bitCacheLength) { +inline Uint32 GIF::ReadCode(Stream* stream, int codeSize, int* blockLength, int* bitCache, int* bitCacheLength) { if (*blockLength == 0) *blockLength = stream->ReadByte(); @@ -54,7 +43,7 @@ PRIVATE STATIC inline Uint32 GIF::ReadCode(Stream* stream, int codeSize, int* bl return result; } -PRIVATE STATIC inline void GIF::WriteCode(Stream* stream, int* offset, int* partial, Uint8* buffer, uint16_t key, int key_size) { +inline void GIF::WriteCode(Stream* stream, int* offset, int* partial, Uint8* buffer, uint16_t key, int key_size) { int byte_offset, bit_offset, bits_to_write; byte_offset = *offset >> 3; bit_offset = *offset & 0x7; @@ -72,7 +61,7 @@ PRIVATE STATIC inline void GIF::WriteCode(Stream* stream, int* offset, int* pa } *offset = (*offset + key_size) % (0xFF * 8); } -PRIVATE inline void GIF::WriteFrame(Stream* stream, Uint32* data) { +inline void GIF::WriteFrame(Stream* stream, Uint32* data) { int depth = 8; // Put Image Node* node; @@ -143,19 +132,19 @@ PRIVATE inline void GIF::WriteFrame(Stream* stream, Uint32* data) { FreeTree(root, degree); } -PRIVATE STATIC void* GIF::NewNode(Uint16 key, int degree) { +void* GIF::NewNode(Uint16 key, int degree) { Node* node = (Node*)Memory::Calloc(1, sizeof(*node) + degree * sizeof(Node*)); if (node) node->Key = key; return node; } -PRIVATE STATIC void* GIF::NewTree(int degree, int* nkeys) { +void* GIF::NewTree(int degree, int* nkeys) { Node *root = (Node*)GIF::NewNode(0, degree); for (*nkeys = 0; *nkeys < degree; (*nkeys)++) root->Children[*nkeys] = (Node*)GIF::NewNode(*nkeys, degree); *nkeys += 2; return root; } -PRIVATE STATIC void GIF::FreeTree(void* root, int degree) { +void GIF::FreeTree(void* root, int degree) { if (!root) return; for (int i = 0; i < degree; i++) FreeTree(((Node*)root)->Children[i], degree); Memory::Free(root); @@ -172,7 +161,7 @@ Log::Print(Log::LOG_VERBOSE, "- Mark '%s' took %.3f ms to reach.", label, delta) Clock::Start(); \ } -PUBLIC STATIC GIF* GIF::Load(const char* filename) { +GIF* GIF::Load(const char* filename) { bool loadPalette = Graphics::UsePalettes; Entry* codeTable = (Entry*)Memory::Malloc(0x1000 * sizeof(Entry)); @@ -513,11 +502,11 @@ PUBLIC STATIC GIF* GIF::Load(const char* filename) { return gif; } -PUBLIC STATIC bool GIF::Save(GIF* gif, const char* filename) { +bool GIF::Save(GIF* gif, const char* filename) { return gif->Save(filename); } -PUBLIC bool GIF::Save(const char* filename) { +bool GIF::Save(const char* filename) { Stream* stream = FileStream::New(filename, FileStream::WRITE_ACCESS); if (!stream) return false; @@ -575,6 +564,6 @@ PUBLIC bool GIF::Save(const char* filename) { return true; } -PUBLIC GIF::~GIF() { +GIF::~GIF() { } diff --git a/source/Engine/ResourceTypes/ImageFormats/ImageFormat.cpp b/source/Engine/ResourceTypes/ImageFormats/ImageFormat.cpp index e49b7616..ae7cdf1a 100644 --- a/source/Engine/ResourceTypes/ImageFormats/ImageFormat.cpp +++ b/source/Engine/ResourceTypes/ImageFormats/ImageFormat.cpp @@ -1,21 +1,7 @@ -#if INTERFACE -#include - -class ImageFormat { -public: - Uint32* Colors = NULL; - Uint32* Data = NULL; - Uint32 Width = 0; - Uint32 Height = 0; - bool Paletted = false; - Uint16 NumPaletteColors = 0; -}; -#endif - #include #include -PUBLIC Uint32* ImageFormat::GetPalette() { +Uint32* ImageFormat::GetPalette() { if (!Colors) return nullptr; @@ -24,10 +10,10 @@ PUBLIC Uint32* ImageFormat::GetPalette() { return colors; } -PUBLIC VIRTUAL bool ImageFormat::Save(const char* filename) { +bool ImageFormat::Save(const char* filename) { return false; } -PUBLIC VIRTUAL ImageFormat::~ImageFormat() { +ImageFormat::~ImageFormat() { Memory::Free(Colors); Colors = nullptr; } diff --git a/source/Engine/ResourceTypes/ImageFormats/JPEG.cpp b/source/Engine/ResourceTypes/ImageFormats/JPEG.cpp index 4b85e263..774cf9bd 100644 --- a/source/Engine/ResourceTypes/ImageFormats/JPEG.cpp +++ b/source/Engine/ResourceTypes/ImageFormats/JPEG.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class JPEG : public ImageFormat { -public: - -}; -#endif - #include #include @@ -105,7 +94,7 @@ static void jpeg_Hatch_IO_src(j_decompress_ptr cinfo, Stream* stream) { } #endif -PUBLIC STATIC JPEG* JPEG::Load(const char* filename) { +JPEG* JPEG::Load(const char* filename) { #ifdef USING_LIBJPEG JPEG* jpeg = new JPEG; Stream* stream = NULL; @@ -265,11 +254,11 @@ PUBLIC STATIC JPEG* JPEG::Load(const char* filename) { #endif return NULL; } -PUBLIC STATIC bool JPEG::Save(JPEG* jpeg, const char* filename) { +bool JPEG::Save(JPEG* jpeg, const char* filename) { return jpeg->Save(filename); } -PUBLIC bool JPEG::Save(const char* filename) { +bool JPEG::Save(const char* filename) { Stream* stream = FileStream::New(filename, FileStream::WRITE_ACCESS); if (!stream) return false; @@ -278,6 +267,6 @@ PUBLIC bool JPEG::Save(const char* filename) { return true; } -PUBLIC JPEG::~JPEG() { +JPEG::~JPEG() { } diff --git a/source/Engine/ResourceTypes/ImageFormats/PNG.cpp b/source/Engine/ResourceTypes/ImageFormats/PNG.cpp index 30eb9b88..fcfa0075 100644 --- a/source/Engine/ResourceTypes/ImageFormats/PNG.cpp +++ b/source/Engine/ResourceTypes/ImageFormats/PNG.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class PNG : public ImageFormat { -public: - -}; -#endif - #include #include @@ -48,7 +37,7 @@ void png_read_fn(png_structp ctx, png_bytep area, png_size_t size) { #include #endif -PUBLIC STATIC PNG* PNG::Load(const char* filename) { +PNG* PNG::Load(const char* filename) { #ifdef USING_LIBPNG PNG* png = new PNG; Stream* stream = NULL; @@ -351,7 +340,7 @@ PUBLIC STATIC PNG* PNG::Load(const char* filename) { #endif return NULL; } -PUBLIC void PNG::ReadPixelDataARGB(Uint32* pixelData, int num_channels) { + void PNG::ReadPixelDataARGB(Uint32* pixelData, int num_channels) { Uint32 Rmask, Gmask, Bmask, Amask; bool doConvert = false; @@ -399,7 +388,7 @@ PUBLIC void PNG::ReadPixelDataARGB(Uint32* pixelData, int num_channels memcpy(Data, pixelData, Width * Height * sizeof(Uint32)); } } -PUBLIC void PNG::ReadPixelBitstream(Uint8* pixelData, size_t bit_depth) { + void PNG::ReadPixelBitstream(Uint8* pixelData, size_t bit_depth) { size_t scanline_width = (((bit_depth * Width) + 15) / 8) - 1; Uint8 mask = (1 << bit_depth) - 1; @@ -426,11 +415,11 @@ PUBLIC void PNG::ReadPixelBitstream(Uint8* pixelData, size_t bit_depth } } -PUBLIC STATIC bool PNG::Save(PNG* png, const char* filename) { +bool PNG::Save(PNG* png, const char* filename) { return png->Save(filename); } -PUBLIC bool PNG::Save(const char* filename) { +bool PNG::Save(const char* filename) { Stream* stream = FileStream::New(filename, FileStream::WRITE_ACCESS); if (!stream) return false; @@ -439,6 +428,6 @@ PUBLIC bool PNG::Save(const char* filename) { return true; } -PUBLIC PNG::~PNG() { +PNG::~PNG() { } diff --git a/source/Engine/ResourceTypes/ModelFormats/HatchModel.cpp b/source/Engine/ResourceTypes/ModelFormats/HatchModel.cpp index 107a57d3..9082da02 100644 --- a/source/Engine/ResourceTypes/ModelFormats/HatchModel.cpp +++ b/source/Engine/ResourceTypes/ModelFormats/HatchModel.cpp @@ -1,22 +1,3 @@ -#if INTERFACE -#include -#include -class HatchModel { -public: - static Sint32 Version; - - static Uint32 NumVertexStore; - static Uint32 NumNormalStore; - static Uint32 NumTexCoordStore; - static Uint32 NumColorStore; - - static Vector3* VertexStore; - static Vector3* NormalStore; - static Vector2* TexCoordStore; - static Uint32* ColorStore; -}; -#endif - #include #include #include @@ -40,7 +21,7 @@ Vector3* HatchModel::NormalStore; Vector2* HatchModel::TexCoordStore; Uint32* HatchModel::ColorStore; -PUBLIC STATIC bool HatchModel::IsMagic(Stream* stream) { +bool HatchModel::IsMagic(Stream* stream) { Uint32 magic = stream->ReadUInt32BE(); stream->Skip(-4); @@ -48,7 +29,7 @@ PUBLIC STATIC bool HatchModel::IsMagic(Stream* stream) { return magic == HATCH_MODEL_MAGIC; } -PUBLIC STATIC void HatchModel::ReadMaterialInfo(Stream* stream, Uint8 *destColors, char **texName) { +void HatchModel::ReadMaterialInfo(Stream* stream, Uint8 *destColors, char **texName) { *texName = stream->ReadString(); Uint32 colorIndex = stream->ReadUInt32(); @@ -58,7 +39,7 @@ PUBLIC STATIC void HatchModel::ReadMaterialInfo(Stream* stream, Uint8 *destColor ColorUtils::Separate(color, destColors); } -PRIVATE STATIC Material* HatchModel::ReadMaterial(Stream* stream, const char *parentDirectory) { +Material* HatchModel::ReadMaterial(Stream* stream, const char *parentDirectory) { Material* material = new Material(); material->Name = stream->ReadString(); @@ -146,7 +127,7 @@ PRIVATE STATIC Material* HatchModel::ReadMaterial(Stream* stream, const char *pa return material; } -PRIVATE STATIC void HatchModel::ReadVertexStore(Stream* stream) { +void HatchModel::ReadVertexStore(Stream* stream) { NumVertexStore = stream->ReadUInt32(); if (!NumVertexStore) return; @@ -162,7 +143,7 @@ PRIVATE STATIC void HatchModel::ReadVertexStore(Stream* stream) { } } -PRIVATE STATIC void HatchModel::ReadNormalStore(Stream* stream) { +void HatchModel::ReadNormalStore(Stream* stream) { NumNormalStore = stream->ReadUInt32(); if (!NumNormalStore) return; @@ -178,7 +159,7 @@ PRIVATE STATIC void HatchModel::ReadNormalStore(Stream* stream) { } } -PRIVATE STATIC void HatchModel::ReadTexCoordStore(Stream* stream) { +void HatchModel::ReadTexCoordStore(Stream* stream) { NumTexCoordStore = stream->ReadUInt32(); if (!NumTexCoordStore) return; @@ -193,7 +174,7 @@ PRIVATE STATIC void HatchModel::ReadTexCoordStore(Stream* stream) { } } -PRIVATE STATIC void HatchModel::ReadColorStore(Stream* stream) { +void HatchModel::ReadColorStore(Stream* stream) { NumColorStore = stream->ReadUInt32(); if (!NumColorStore) return; @@ -211,35 +192,35 @@ PRIVATE STATIC void HatchModel::ReadColorStore(Stream* stream) { } } -PRIVATE STATIC Vector3 HatchModel::GetStoredVertex(Uint32 idx) { +Vector3 HatchModel::GetStoredVertex(Uint32 idx) { if (idx < 0 || idx >= NumVertexStore) return {}; return VertexStore[idx]; } -PRIVATE STATIC Vector3 HatchModel::GetStoredNormal(Uint32 idx) { +Vector3 HatchModel::GetStoredNormal(Uint32 idx) { if (idx < 0 || idx >= NumNormalStore) return {}; return NormalStore[idx]; } -PRIVATE STATIC Vector2 HatchModel::GetStoredTexCoord(Uint32 idx) { +Vector2 HatchModel::GetStoredTexCoord(Uint32 idx) { if (idx < 0 || idx >= NumTexCoordStore) return {}; return TexCoordStore[idx]; } -PRIVATE STATIC Uint32 HatchModel::GetStoredColor(Uint32 idx) { +Uint32 HatchModel::GetStoredColor(Uint32 idx) { if (idx < 0 || idx >= NumColorStore) return 0; return ColorStore[idx]; } -PRIVATE STATIC void HatchModel::ReadVertexIndices(Sint32* indices, Uint32 triangleCount, Stream* stream) { +void HatchModel::ReadVertexIndices(Sint32* indices, Uint32 triangleCount, Stream* stream) { for (Uint32 i = 0; i < triangleCount; i++) { *indices++ = stream->ReadUInt32(); *indices++ = stream->ReadUInt32(); @@ -249,7 +230,7 @@ PRIVATE STATIC void HatchModel::ReadVertexIndices(Sint32* indices, Uint32 triang *indices = -1; } -PRIVATE STATIC Mesh* HatchModel::ReadMesh(IModel* model, Stream* stream) { +Mesh* HatchModel::ReadMesh(IModel* model, Stream* stream) { // Read mesh data Mesh* mesh = new Mesh; mesh->Name = stream->ReadString(); @@ -336,7 +317,7 @@ PRIVATE STATIC Mesh* HatchModel::ReadMesh(IModel* model, Stream* stream) { return mesh; } -PUBLIC STATIC bool HatchModel::Convert(IModel* model, Stream* stream, const char* path) { +bool HatchModel::Convert(IModel* model, Stream* stream, const char* path) { bool success = false; if (stream->ReadUInt32BE() != HATCH_MODEL_MAGIC) { @@ -483,7 +464,7 @@ static vector normalList; static vector texCoordList; static vector colorList; -PRIVATE STATIC void HatchModel::WriteMesh(Mesh* mesh, Stream* stream) { +void HatchModel::WriteMesh(Mesh* mesh, Stream* stream) { Uint8 flags = 0; if (mesh->VertexFlag & VertexType_Normal) flags |= 1; @@ -575,7 +556,7 @@ PRIVATE STATIC void HatchModel::WriteMesh(Mesh* mesh, Stream* stream) { stream->WriteUInt32(mesh->VertexIndexBuffer[j]); } -PRIVATE STATIC char* HatchModel::GetMaterialTextureName(const char* name, const char* parentDirectory) { +char* HatchModel::GetMaterialTextureName(const char* name, const char* parentDirectory) { const char* result = strstr(name, parentDirectory); if (result) { size_t offset = strlen(parentDirectory); @@ -587,7 +568,7 @@ PRIVATE STATIC char* HatchModel::GetMaterialTextureName(const char* name, const return StringUtils::Duplicate(name); } -PRIVATE STATIC void HatchModel::WriteColorIndex(Uint32* color, Stream* stream) { +void HatchModel::WriteColorIndex(Uint32* color, Stream* stream) { Uint32 key = colorIDs->HashFunction(color, sizeof(*color)); if (colorIDs->Exists(key)) stream->WriteUInt32(colorIDs->Get(key)); @@ -598,7 +579,7 @@ PRIVATE STATIC void HatchModel::WriteColorIndex(Uint32* color, Stream* stream) { } } -PRIVATE STATIC void HatchModel::WriteMaterial(Material* material, Stream* stream, const char* parentDirectory) { +void HatchModel::WriteMaterial(Material* material, Stream* stream, const char* parentDirectory) { stream->WriteString(material->Name); Uint8 flags = 0; @@ -759,7 +740,7 @@ PRIVATE STATIC void HatchModel::WriteMaterial(Material* material, Stream* stream } } -PUBLIC STATIC bool HatchModel::Save(IModel* model, const char* filename) { +bool HatchModel::Save(IModel* model, const char* filename) { Stream* stream = FileStream::New(filename, FileStream::WRITE_ACCESS); if (!stream) { Log::Print(Log::LOG_ERROR, "Couldn't open \"%s\"!", filename); diff --git a/source/Engine/ResourceTypes/ModelFormats/Importer.cpp b/source/Engine/ResourceTypes/ModelFormats/Importer.cpp index 979e7521..174f3cb6 100644 --- a/source/Engine/ResourceTypes/ModelFormats/Importer.cpp +++ b/source/Engine/ResourceTypes/ModelFormats/Importer.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include -class ModelImporter { -public: - static vector MeshIDs; - static char* ParentDirectory; -}; -#endif - #include #include #include @@ -102,7 +91,7 @@ static AnimQuaternionKey GetQuatKey(struct aiQuatKey* quatKey) { return key; } -PRIVATE STATIC Mesh* ModelImporter::LoadMesh(IModel* imodel, struct aiMesh* amesh) { +Mesh* ModelImporter::LoadMesh(IModel* imodel, struct aiMesh* amesh) { size_t numFaces = amesh->mNumFaces; size_t numVertices = amesh->mNumVertices; @@ -185,7 +174,7 @@ PRIVATE STATIC Mesh* ModelImporter::LoadMesh(IModel* imodel, struct aiMesh* ames return mesh; } -PRIVATE STATIC Material* ModelImporter::LoadMaterial(IModel* imodel, struct aiMaterial* mat, unsigned i) { +Material* ModelImporter::LoadMaterial(IModel* imodel, struct aiMaterial* mat, unsigned i) { Material* material = new Material(); aiString matName; @@ -242,7 +231,7 @@ PRIVATE STATIC Material* ModelImporter::LoadMaterial(IModel* imodel, struct aiMa return material; } -PRIVATE STATIC ModelNode* ModelImporter::LoadNode(IModel* imodel, ModelNode* parent, const struct aiNode* anode) { +ModelNode* ModelImporter::LoadNode(IModel* imodel, ModelNode* parent, const struct aiNode* anode) { ModelNode* node = new ModelNode; node->Name = GetString(anode->mName); @@ -266,7 +255,7 @@ PRIVATE STATIC ModelNode* ModelImporter::LoadNode(IModel* imodel, ModelNode* par return node; } -PRIVATE STATIC Skeleton* ModelImporter::LoadBones(IModel* imodel, Mesh* mesh, struct aiMesh* amesh) { +Skeleton* ModelImporter::LoadBones(IModel* imodel, Mesh* mesh, struct aiMesh* amesh) { Skeleton* skeleton = new Skeleton; skeleton->NumBones = amesh->mNumBones; @@ -311,7 +300,7 @@ PRIVATE STATIC Skeleton* ModelImporter::LoadBones(IModel* imodel, Mesh* mesh, st return skeleton; } -PRIVATE STATIC SkeletalAnim* ModelImporter::LoadAnimation(IModel* imodel, ModelAnim* parentAnim, struct aiAnimation* aanim) { +SkeletalAnim* ModelImporter::LoadAnimation(IModel* imodel, ModelAnim* parentAnim, struct aiAnimation* aanim) { SkeletalAnim* anim = new SkeletalAnim; anim->Channels.resize(aanim->mNumChannels); anim->NodeLookup = new HashMap(NULL, 256); // Might be enough @@ -360,7 +349,7 @@ PRIVATE STATIC SkeletalAnim* ModelImporter::LoadAnimation(IModel* imodel, ModelA return anim; } -PRIVATE STATIC bool ModelImporter::DoConversion(const struct aiScene* scene, IModel* imodel) { +bool ModelImporter::DoConversion(const struct aiScene* scene, IModel* imodel) { if (!scene->mNumMeshes) return false; @@ -482,7 +471,7 @@ PRIVATE STATIC bool ModelImporter::DoConversion(const struct aiScene* scene, IMo } #endif -PUBLIC STATIC bool ModelImporter::Convert(IModel* model, Stream* stream, const char* path) { +bool ModelImporter::Convert(IModel* model, Stream* stream, const char* path) { #ifdef USING_ASSIMP size_t size = stream->Length(); void* data = Memory::Malloc(size); diff --git a/source/Engine/ResourceTypes/ModelFormats/MD3Model.cpp b/source/Engine/ResourceTypes/ModelFormats/MD3Model.cpp index 55aa91c5..a2f6ca49 100644 --- a/source/Engine/ResourceTypes/ModelFormats/MD3Model.cpp +++ b/source/Engine/ResourceTypes/ModelFormats/MD3Model.cpp @@ -1,15 +1,3 @@ -#if INTERFACE -#include -#include -class MD3Model { -public: - static Sint32 Version; - static bool UseUVKeyframes; - static Sint32 DataEndOffset; - static vector MaterialNames; -}; -#endif - #include #include #include @@ -35,7 +23,7 @@ bool MD3Model::UseUVKeyframes; Sint32 MD3Model::DataEndOffset; vector MD3Model::MaterialNames; -PUBLIC STATIC bool MD3Model::IsMagic(Stream* stream) { +bool MD3Model::IsMagic(Stream* stream) { Uint32 magic = stream->ReadUInt32BE(); stream->Skip(-4); @@ -43,7 +31,7 @@ PUBLIC STATIC bool MD3Model::IsMagic(Stream* stream) { return magic == MD3_MODEL_MAGIC; } -PRIVATE STATIC void MD3Model::DecodeNormal(Uint16 index, float& x, float& y, float& z) { +void MD3Model::DecodeNormal(Uint16 index, float& x, float& y, float& z) { unsigned latIdx = (index >> 8) & 0xFF; unsigned lngIdx = index & 0xFF; @@ -55,7 +43,7 @@ PRIVATE STATIC void MD3Model::DecodeNormal(Uint16 index, float& x, float& y, flo z = cosf(lng); } -PRIVATE STATIC void MD3Model::ReadShader(Stream* stream) { +void MD3Model::ReadShader(Stream* stream) { char name[MAX_QPATH + 1]; memset(name, '\0', sizeof name); stream->ReadBytes(name, MAX_QPATH); @@ -65,7 +53,7 @@ PRIVATE STATIC void MD3Model::ReadShader(Stream* stream) { MaterialNames.push_back(shaderName); } -PRIVATE STATIC void MD3Model::ReadVerticesAndNormals(Vector3* vert, Vector3* norm, Sint32 vertexCount, Stream* stream) { +void MD3Model::ReadVerticesAndNormals(Vector3* vert, Vector3* norm, Sint32 vertexCount, Stream* stream) { for (Sint32 i = 0; i < vertexCount; i++) { // MD3 coordinate system is usually Z up and Y forward (I think.) vert->X = stream->ReadInt16() * FP16_TO(MD3_XYZ_SCALE); @@ -83,7 +71,7 @@ PRIVATE STATIC void MD3Model::ReadVerticesAndNormals(Vector3* vert, Vector3* nor } } -PRIVATE STATIC void MD3Model::ReadUVs(Vector2* uvs, Sint32 vertexCount, Stream* stream) { +void MD3Model::ReadUVs(Vector2* uvs, Sint32 vertexCount, Stream* stream) { for (Sint32 i = 0; i < vertexCount; i++) { uvs->X = (int)(stream->ReadFloat() * 0x10000); uvs->Y = (int)(stream->ReadFloat() * 0x10000); @@ -91,7 +79,7 @@ PRIVATE STATIC void MD3Model::ReadUVs(Vector2* uvs, Sint32 vertexCount, Stream* } } -PRIVATE STATIC void MD3Model::ReadVertexIndices(Sint32* indices, Sint32 triangleCount, Stream* stream) { +void MD3Model::ReadVertexIndices(Sint32* indices, Sint32 triangleCount, Stream* stream) { for (Sint32 i = 0; i < triangleCount; i++) { *indices++ = stream->ReadUInt32(); *indices++ = stream->ReadUInt32(); @@ -101,7 +89,7 @@ PRIVATE STATIC void MD3Model::ReadVertexIndices(Sint32* indices, Sint32 triangle *indices = -1; } -PRIVATE STATIC Mesh* MD3Model::ReadSurface(IModel* model, Stream* stream, size_t surfaceDataOffset) { +Mesh* MD3Model::ReadSurface(IModel* model, Stream* stream, size_t surfaceDataOffset) { Sint32 magic = stream->ReadUInt32BE(); if (magic != MD3_MODEL_MAGIC) { Log::Print(Log::LOG_ERROR, "Invalid magic for MD3 surface!"); @@ -212,7 +200,7 @@ PRIVATE STATIC Mesh* MD3Model::ReadSurface(IModel* model, Stream* stream, size_t return mesh; } -PUBLIC STATIC bool MD3Model::Convert(IModel* model, Stream* stream, const char* path) { +bool MD3Model::Convert(IModel* model, Stream* stream, const char* path) { if (stream->ReadUInt32BE() != MD3_MODEL_MAGIC) { Log::Print(Log::LOG_ERROR, "Model not of MD3 (Quake III) type!"); return false; diff --git a/source/Engine/ResourceTypes/ModelFormats/RSDKModel.cpp b/source/Engine/ResourceTypes/ModelFormats/RSDKModel.cpp index accd781f..b0ccc74f 100644 --- a/source/Engine/ResourceTypes/ModelFormats/RSDKModel.cpp +++ b/source/Engine/ResourceTypes/ModelFormats/RSDKModel.cpp @@ -1,12 +1,3 @@ -#if INTERFACE -#include -#include -class RSDKModel { -public: - -}; -#endif - #include #include #include @@ -16,7 +7,7 @@ class RSDKModel { #define RSDK_MODEL_MAGIC 0x4D444C00 // MDL0 -PUBLIC STATIC bool RSDKModel::IsMagic(Stream* stream) { +bool RSDKModel::IsMagic(Stream* stream) { Uint32 magic = stream->ReadUInt32BE(); stream->Skip(-4); @@ -24,7 +15,7 @@ PUBLIC STATIC bool RSDKModel::IsMagic(Stream* stream) { return magic == RSDK_MODEL_MAGIC; } -PUBLIC STATIC bool RSDKModel::Convert(IModel* model, Stream* stream) { +bool RSDKModel::Convert(IModel* model, Stream* stream) { if (stream->ReadUInt32BE() != RSDK_MODEL_MAGIC) { Log::Print(Log::LOG_ERROR, "Model not of RSDK type!"); return false; diff --git a/source/Engine/ResourceTypes/ResourceManager.cpp b/source/Engine/ResourceTypes/ResourceManager.cpp index eda7fc1c..c0332601 100644 --- a/source/Engine/ResourceTypes/ResourceManager.cpp +++ b/source/Engine/ResourceTypes/ResourceManager.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include - -class ResourceManager { -public: - static bool UsingDataFolder; - static bool UsingModPack; -}; -#endif - #include #include @@ -42,10 +31,10 @@ HashMap* ResourceRegistry = NULL; bool ResourceManager::UsingDataFolder = true; bool ResourceManager::UsingModPack = false; -PUBLIC STATIC void ResourceManager::PrefixResourcePath(char* out, size_t outSize, const char* path) { +void ResourceManager::PrefixResourcePath(char* out, size_t outSize, const char* path) { snprintf(out, outSize, "Resources/%s", path); } -PUBLIC STATIC void ResourceManager::PrefixParentPath(char* out, size_t outSize, const char* path) { +void ResourceManager::PrefixParentPath(char* out, size_t outSize, const char* path) { #if defined(SWITCH_ROMFS) snprintf(out, outSize, "romfs:/%s", path); #else @@ -53,7 +42,7 @@ PUBLIC STATIC void ResourceManager::PrefixParentPath(char* out, size_t outSize #endif } -PUBLIC STATIC void ResourceManager::Init(const char* filename) { +void ResourceManager::Init(const char* filename) { StreamNodeHead = NULL; ResourceRegistry = new HashMap(CRC32::EncryptData, 16); @@ -80,7 +69,7 @@ PUBLIC STATIC void ResourceManager::Init(const char* filename) { } } } -PUBLIC STATIC void ResourceManager::Load(const char* filename) { +void ResourceManager::Load(const char* filename) { if (!ResourceRegistry) return; @@ -128,7 +117,7 @@ PUBLIC STATIC void ResourceManager::Load(const char* filename) { // Log::Print(Log::LOG_VERBOSE, "%08X: Offset: %08llX Size: %08llX Comp Size: %08llX Data Flag: %08X", crc32, offset, size, compressedSize, dataFlag); } } -PUBLIC STATIC bool ResourceManager::LoadResource(const char* filename, Uint8** out, size_t* size) { +bool ResourceManager::LoadResource(const char* filename, Uint8** out, size_t* size) { Uint8* memory; char resourcePath[4096]; char *pathToLoad = StringUtils::ReplacePathSeparators(filename); @@ -264,7 +253,7 @@ PUBLIC STATIC bool ResourceManager::LoadResource(const char* filename, Uint8** *size = rwSize; return true; } -PUBLIC STATIC bool ResourceManager::ResourceExists(const char* filename) { +bool ResourceManager::ResourceExists(const char* filename) { char *pathToLoad = StringUtils::ReplacePathSeparators(filename); char resourcePath[4096]; @@ -293,7 +282,7 @@ PUBLIC STATIC bool ResourceManager::ResourceExists(const char* filename) { SDL_RWclose(rw); return true; } -PUBLIC STATIC void ResourceManager::Dispose() { +void ResourceManager::Dispose() { if (StreamNodeHead) { for (StreamNode *old, *streamNode = StreamNodeHead; streamNode; ) { old = streamNode; diff --git a/source/Engine/ResourceTypes/SceneFormats/HatchSceneReader.cpp b/source/Engine/ResourceTypes/SceneFormats/HatchSceneReader.cpp index 19b0f43f..3a749e1e 100644 --- a/source/Engine/ResourceTypes/SceneFormats/HatchSceneReader.cpp +++ b/source/Engine/ResourceTypes/SceneFormats/HatchSceneReader.cpp @@ -1,14 +1,3 @@ -#if INTERFACE -#include -#include -#include - -class HatchSceneReader { -public: - static Uint32 Magic; -}; -#endif - #include #include @@ -39,7 +28,7 @@ Uint32 HatchSceneReader::Magic = 0x4E435348; // HSCN #define HSCN_FLIPY_MASK 0x00002000U #define HSCN_FXYID_MASK 0x00003FFFU // Max. 4096 tiles -PUBLIC STATIC bool HatchSceneReader::Read(const char* filename, const char* parentFolder) { +bool HatchSceneReader::Read(const char* filename, const char* parentFolder) { Stream* r = ResourceStream::New(filename); if (!r) { Log::Print(Log::LOG_ERROR, "Couldn't open file '%s'!", filename); @@ -49,7 +38,7 @@ PUBLIC STATIC bool HatchSceneReader::Read(const char* filename, const char* pare return HatchSceneReader::Read(r, parentFolder); } -PUBLIC STATIC bool HatchSceneReader::Read(Stream* r, const char* parentFolder) { +bool HatchSceneReader::Read(Stream* r, const char* parentFolder) { // Start reading if (r->ReadUInt32() != HatchSceneReader::Magic) { Log::Print(Log::LOG_ERROR, "Not a Hatch scene!"); @@ -107,7 +96,7 @@ PUBLIC STATIC bool HatchSceneReader::Read(Stream* r, const char* parentFolder) { return true; } -PRIVATE STATIC SceneLayer HatchSceneReader::ReadLayer(Stream* r) { +SceneLayer HatchSceneReader::ReadLayer(Stream* r) { char* name = r->ReadHeaderedString(); Uint8 drawBehavior = r->ReadByte(); Uint8 drawGroup = r->ReadByte(); @@ -161,7 +150,7 @@ PRIVATE STATIC SceneLayer HatchSceneReader::ReadLayer(Stream* r) { return layer; } -PRIVATE STATIC void HatchSceneReader::ReadTileData(Stream* r, SceneLayer layer) { +void HatchSceneReader::ReadTileData(Stream* r, SceneLayer layer) { size_t streamPos = r->Position(); r->ReadUInt32(); // compressed size @@ -176,7 +165,7 @@ PRIVATE STATIC void HatchSceneReader::ReadTileData(Stream* r, SceneLayer layer) r->ReadCompressed(layer.Tiles, dataSize); } -PRIVATE STATIC void HatchSceneReader::ConvertTileData(SceneLayer* layer) { +void HatchSceneReader::ConvertTileData(SceneLayer* layer) { for (size_t i = 0; i < (size_t)layer->Width * layer->Height; i++) { if (layer->Tiles[i] == HSCN_EMPTY_TILE) { layer->Tiles[i] = Scene::EmptyTile; @@ -205,7 +194,7 @@ PRIVATE STATIC void HatchSceneReader::ConvertTileData(SceneLayer* layer) { } } -PRIVATE STATIC void HatchSceneReader::ReadScrollData(Stream* r, SceneLayer layer) { +void HatchSceneReader::ReadScrollData(Stream* r, SceneLayer layer) { for (Uint16 i = 0; i < layer.ScrollInfoCount; i++) { ScrollingInfo* info = &layer.ScrollInfos[i]; @@ -235,7 +224,7 @@ PRIVATE STATIC void HatchSceneReader::ReadScrollData(Stream* r, SceneLayer layer static vector SceneClasses; -PRIVATE STATIC SceneClass* HatchSceneReader::FindClass(SceneHash hash) { +SceneClass* HatchSceneReader::FindClass(SceneHash hash) { for (size_t i = 0; i < SceneClasses.size(); i++) { if (SceneClasses[i].Hash == hash) return &SceneClasses[i]; @@ -244,7 +233,7 @@ PRIVATE STATIC SceneClass* HatchSceneReader::FindClass(SceneHash hash) { return NULL; } -PRIVATE STATIC SceneClassProperty* HatchSceneReader::FindProperty(SceneClass* scnClass, SceneHash hash) { +SceneClassProperty* HatchSceneReader::FindProperty(SceneClass* scnClass, SceneHash hash) { for (size_t i = 0; i < scnClass->Properties.size(); i++) { if (scnClass->Properties[i].Hash == hash) return &scnClass->Properties[i]; @@ -253,7 +242,7 @@ PRIVATE STATIC SceneClassProperty* HatchSceneReader::FindProperty(SceneClass* sc return NULL; } -PRIVATE STATIC void HatchSceneReader::HashString(char* string, SceneHash* hash) { +void HatchSceneReader::HashString(char* string, SceneHash* hash) { Uint8 final[16]; MD5::EncryptString(final, string); @@ -264,7 +253,7 @@ PRIVATE STATIC void HatchSceneReader::HashString(char* string, SceneHash* hash) hash->D = final[12] + (final[13] << 8) + (final[14] << 16) + (final[15] << 24); } -PRIVATE STATIC void HatchSceneReader::ReadClasses(Stream *r) { +void HatchSceneReader::ReadClasses(Stream *r) { Uint16 numClasses = r->ReadUInt16(); SceneClasses.clear(); @@ -317,7 +306,7 @@ PRIVATE STATIC void HatchSceneReader::ReadClasses(Stream *r) { } } -PRIVATE STATIC void HatchSceneReader::FreeClasses() { +void HatchSceneReader::FreeClasses() { for (size_t i = 0; i < SceneClasses.size(); i++) { SceneClass* scnClass = &SceneClasses[i]; Memory::Free(scnClass->Name); @@ -328,7 +317,7 @@ PRIVATE STATIC void HatchSceneReader::FreeClasses() { SceneClasses.clear(); } -PRIVATE STATIC bool HatchSceneReader::LoadTileset(const char* parentFolder) { +bool HatchSceneReader::LoadTileset(const char* parentFolder) { int curTileCount = (int)Scene::TileSpriteInfos.size(); char tilesetFile[4096]; @@ -379,7 +368,7 @@ PRIVATE STATIC bool HatchSceneReader::LoadTileset(const char* parentFolder) { return true; } -PRIVATE STATIC void HatchSceneReader::ReadEntities(Stream *r) { +void HatchSceneReader::ReadEntities(Stream *r) { Uint16 numEntities = r->ReadUInt16(); for (Uint16 i = 0; i < numEntities; i++) { @@ -532,7 +521,7 @@ PRIVATE STATIC void HatchSceneReader::ReadEntities(Stream *r) { } } -PRIVATE STATIC void HatchSceneReader::SkipEntityProperties(Stream *r, Uint8 numProps) { +void HatchSceneReader::SkipEntityProperties(Stream *r, Uint8 numProps) { for (Uint8 j = 0; j < numProps; j++) { r->ReadUInt32(); r->ReadUInt32(); @@ -542,7 +531,7 @@ PRIVATE STATIC void HatchSceneReader::SkipEntityProperties(Stream *r, Uint8 numP } } -PRIVATE STATIC void HatchSceneReader::SkipProperty(Stream *r, Uint8 varType) { +void HatchSceneReader::SkipProperty(Stream *r, Uint8 varType) { switch (varType) { case HSCN_VAR_INT8: case HSCN_VAR_UINT8: diff --git a/source/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.cpp b/source/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.cpp index 4be7a5b4..fbf3ba9b 100644 --- a/source/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.cpp +++ b/source/Engine/ResourceTypes/SceneFormats/RSDKSceneReader.cpp @@ -1,13 +1,3 @@ -#if INTERFACE -#include -#include -class RSDKSceneReader { -public: - static Uint32 Magic; - static bool Initialized; -}; -#endif - #include #include @@ -49,7 +39,7 @@ static HashMap* PropertyHashes = NULL; static Uint32 HACK_PlayerNameHash = 0; -PUBLIC STATIC void RSDKSceneReader::StageConfig_GetColors(const char* filename) { +void RSDKSceneReader::StageConfig_GetColors(const char* filename) { MemoryStream* memoryReader; ResourceStream* stageConfigReader; if ((stageConfigReader = ResourceStream::New(filename))) { @@ -95,7 +85,7 @@ PUBLIC STATIC void RSDKSceneReader::StageConfig_GetColors(const char* filename) stageConfigReader->Close(); } } -PUBLIC STATIC void RSDKSceneReader::GameConfig_GetColors(const char* filename) { +void RSDKSceneReader::GameConfig_GetColors(const char* filename) { MemoryStream* memoryReader; ResourceStream* gameConfigReader; if ((gameConfigReader = ResourceStream::New(filename))) { @@ -147,7 +137,7 @@ PUBLIC STATIC void RSDKSceneReader::GameConfig_GetColors(const char* filename) { gameConfigReader->Close(); } } -PRIVATE STATIC void RSDKSceneReader::LoadObjectList() { +void RSDKSceneReader::LoadObjectList() { // Object names Stream* r = ResourceStream::New("ObjectList.txt"); if (!r) return; @@ -187,7 +177,7 @@ PRIVATE STATIC void RSDKSceneReader::LoadObjectList() { r->Close(); } -PRIVATE STATIC void RSDKSceneReader::LoadPropertyList() { +void RSDKSceneReader::LoadPropertyList() { // Property Names Stream* r = ResourceStream::New("PropertyList.txt"); if (!r) return; @@ -219,7 +209,7 @@ PRIVATE STATIC void RSDKSceneReader::LoadPropertyList() { r->Close(); } -PUBLIC STATIC bool RSDKSceneReader::Read(const char* filename, const char* parentFolder) { +bool RSDKSceneReader::Read(const char* filename, const char* parentFolder) { Stream* r = ResourceStream::New(filename); if (!r) { Log::Print(Log::LOG_ERROR, "Couldn't open file '%s'!", filename); @@ -228,7 +218,7 @@ PUBLIC STATIC bool RSDKSceneReader::Read(const char* filename, const char* paren return RSDKSceneReader::Read(r, parentFolder); } -PRIVATE STATIC SceneLayer RSDKSceneReader::ReadLayer(Stream* r) { +SceneLayer RSDKSceneReader::ReadLayer(Stream* r) { r->ReadByte(); // Ignored Byte char* Name = r->ReadHeaderedString(); @@ -303,7 +293,7 @@ PRIVATE STATIC SceneLayer RSDKSceneReader::ReadLayer(Stream* r) { return layer; } -PUBLIC STATIC bool RSDKSceneReader::ReadObjectDefinition(Stream* r, Entity** objSlots, const int maxObjSlots) { +bool RSDKSceneReader::ReadObjectDefinition(Stream* r, Entity** objSlots, const int maxObjSlots) { Uint8 hashTemp[16]; r->ReadBytes(hashTemp, 16); @@ -471,7 +461,7 @@ PUBLIC STATIC bool RSDKSceneReader::ReadObjectDefinition(Stream* r, Entity** obj return true; } -PUBLIC STATIC bool RSDKSceneReader::Read(Stream* r, const char* parentFolder) { +bool RSDKSceneReader::Read(Stream* r, const char* parentFolder) { // Load PropertyList and ObjectList and others // (use regular malloc and calloc as this is technically a hack outside the scope of the engine) if (!RSDKSceneReader::Initialized) { @@ -572,7 +562,7 @@ PUBLIC STATIC bool RSDKSceneReader::Read(Stream* r, const char* parentFolder) { return true; } -PRIVATE STATIC bool RSDKSceneReader::LoadTileset(const char* parentFolder) { +bool RSDKSceneReader::LoadTileset(const char* parentFolder) { Graphics::UsePalettes = true; char filename16x16Tiles[4096]; diff --git a/source/Engine/ResourceTypes/SceneFormats/TiledMapReader.cpp b/source/Engine/ResourceTypes/SceneFormats/TiledMapReader.cpp index 68d2eb06..b53c7716 100644 --- a/source/Engine/ResourceTypes/SceneFormats/TiledMapReader.cpp +++ b/source/Engine/ResourceTypes/SceneFormats/TiledMapReader.cpp @@ -1,11 +1,3 @@ -#if INTERFACE -#include -#include -class TiledMapReader { -public: -}; -#endif - #include #include @@ -104,7 +96,7 @@ int base64_decode_block(const char* code_in, const int length_in, char* plaint return (int)(plainchar - (int8_t*)plaintext_out); } -PRIVATE STATIC VMValue TiledMapReader::ParseProperty(XMLNode* property) { +VMValue TiledMapReader::ParseProperty(XMLNode* property) { // If the property has no value (for example, a multiline string), // the value is assumed to be in the content if (!property->attributes.Exists("value")) { @@ -179,7 +171,7 @@ PRIVATE STATIC VMValue TiledMapReader::ParseProperty(XMLNode* property) { return val; } -PRIVATE STATIC void TiledMapReader::ParsePropertyNode(XMLNode* node, HashMap* properties) { +void TiledMapReader::ParsePropertyNode(XMLNode* node, HashMap* properties) { if (!node->attributes.Exists("name")) return; @@ -188,7 +180,7 @@ PRIVATE STATIC void TiledMapReader::ParsePropertyNode(XMLNode* node, HashMapPut(property_name.ToString().c_str(), TiledMapReader::ParseProperty(node)); } -PRIVATE STATIC ObjArray* TiledMapReader::ParsePolyPoints(XMLNode* node) { +ObjArray* TiledMapReader::ParsePolyPoints(XMLNode* node) { if (!node->attributes.Exists("points")) return nullptr; @@ -216,7 +208,7 @@ PRIVATE STATIC ObjArray* TiledMapReader::ParsePolyPoints(XMLNode* node) { return array; } -PRIVATE STATIC Tileset* TiledMapReader::ParseTilesetImage(XMLNode* node, int firstgid, const char* parentFolder) { +Tileset* TiledMapReader::ParseTilesetImage(XMLNode* node, int firstgid, const char* parentFolder) { char imagePath[4096]; Token image_source = node->attributes.Get("source"); @@ -274,7 +266,7 @@ PRIVATE STATIC Tileset* TiledMapReader::ParseTilesetImage(XMLNode* node, int fir return &Scene::Tilesets.back(); } -PRIVATE STATIC void TiledMapReader::ParseTileAnimation(int tileID, int firstgid, Tileset* tilesetPtr, XMLNode* node) { +void TiledMapReader::ParseTileAnimation(int tileID, int firstgid, Tileset* tilesetPtr, XMLNode* node) { vector tileIDs; vector frameDurations; @@ -293,7 +285,7 @@ PRIVATE STATIC void TiledMapReader::ParseTileAnimation(int tileID, int firstgid, tilesetPtr->AddTileAnimSequence(tileID, &Scene::TileSpriteInfos[tileID], tileIDs, frameDurations); } -PRIVATE STATIC void TiledMapReader::ParseTile(Tileset* tilesetPtr, XMLNode* node) { +void TiledMapReader::ParseTile(Tileset* tilesetPtr, XMLNode* node) { if (!tilesetPtr) return; @@ -307,7 +299,7 @@ PRIVATE STATIC void TiledMapReader::ParseTile(Tileset* tilesetPtr, XMLNode* node } } -PRIVATE STATIC void TiledMapReader::LoadTileset(XMLNode* tileset, const char* parentFolder) { +void TiledMapReader::LoadTileset(XMLNode* tileset, const char* parentFolder) { int firstgid = (int)XMLParser::TokenToNumber(tileset->attributes.Get("firstgid")); XMLNode* tilesetXML = NULL; @@ -344,7 +336,7 @@ PRIVATE STATIC void TiledMapReader::LoadTileset(XMLNode* tileset, const char* pa XMLParser::Free(tilesetXML); } -PUBLIC STATIC void TiledMapReader::Read(const char* sourceF, const char* parentFolder) { +void TiledMapReader::Read(const char* sourceF, const char* parentFolder) { XMLNode* tileMapXML = XMLParser::ParseFromResource(sourceF); if (!tileMapXML) { Log::Print(Log::LOG_ERROR, "Could not parse from resource \"%s\"", sourceF); diff --git a/source/Engine/ResourceTypes/SoundFormats/OGG.cpp b/source/Engine/ResourceTypes/SoundFormats/OGG.cpp index cf1f6bda..4449937b 100644 --- a/source/Engine/ResourceTypes/SoundFormats/OGG.cpp +++ b/source/Engine/ResourceTypes/SoundFormats/OGG.cpp @@ -1,16 +1,3 @@ -#if INTERFACE -#include -#include - -#include - -class OGG : public SoundFormat { -private: - // OGG Specific - char Vorbis[0x800]; -}; -#endif - #include #include @@ -45,11 +32,11 @@ struct VorbisGroup { }; #endif -PRIVATE STATIC size_t OGG::StaticRead(void* mem, size_t size, size_t nmemb, void* ptr) { +size_t OGG::StaticRead(void* mem, size_t size, size_t nmemb, void* ptr) { class Stream* stream = (class Stream*)ptr; return stream->ReadBytes(mem, size * nmemb); } -PRIVATE STATIC Sint32 OGG::StaticSeek(void* ptr, Sint64 offset, int whence) { +Sint32 OGG::StaticSeek(void* ptr, Sint64 offset, int whence) { class Stream* stream = (class Stream*)ptr; if (whence == SEEK_CUR) { stream->Skip((Sint64)offset); @@ -68,17 +55,17 @@ PRIVATE STATIC Sint32 OGG::StaticSeek(void* ptr, Sint64 offset, int whence) return -1; } } -PRIVATE STATIC Sint32 OGG::StaticCloseFree(void* ptr) { +Sint32 OGG::StaticCloseFree(void* ptr) { return 0; } -PRIVATE STATIC Sint32 OGG::StaticCloseNoFree(void* ptr) { +Sint32 OGG::StaticCloseNoFree(void* ptr) { return 0; } -PRIVATE STATIC long OGG::StaticTell(void* ptr) { +long OGG::StaticTell(void* ptr) { return ((class Stream*)ptr)->Position(); } -PUBLIC STATIC SoundFormat* OGG::Load(const char* filename) { +SoundFormat* OGG::Load(const char* filename) { VorbisGroup* vorbis; OGG* ogg = NULL; @@ -268,7 +255,7 @@ PUBLIC STATIC SoundFormat* OGG::Load(const char* filename) { return ogg; } -PUBLIC size_t OGG::SeekSample(int index) { +size_t OGG::SeekSample(int index) { VorbisGroup* vorbis = (VorbisGroup*)this->Vorbis; #ifdef USING_LIBOGG ov_pcm_seek(&vorbis->File, index); @@ -279,7 +266,7 @@ PUBLIC size_t OGG::SeekSample(int index) { SampleIndex = (size_t)index; return SampleIndex; } -PUBLIC int OGG::LoadSamples(size_t count) { +int OGG::LoadSamples(size_t count) { if (SampleBuffer == NULL) { SampleBuffer = (Uint8*)Memory::TrackedMalloc("SoundData::SampleBuffer", TotalPossibleSamples * SampleSize); Samples.reserve(TotalPossibleSamples); @@ -287,7 +274,7 @@ PUBLIC int OGG::LoadSamples(size_t count) { return GetSamples(SampleBuffer, count, -1); } -PUBLIC int OGG::GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex) { +int OGG::GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex) { #ifdef USING_LIBOGG int read; Uint32 total = 0, @@ -379,7 +366,7 @@ PUBLIC int OGG::GetSamples(Uint8* buffer, size_t count, Sint32 l #endif return 0; } -PUBLIC VIRTUAL void OGG::LoadAllSamples() { +void OGG::LoadAllSamples() { if (SampleBuffer == nullptr) { SampleBuffer = (Uint8*)Memory::TrackedMalloc("SoundData::SampleBuffer", TotalPossibleSamples * SampleSize); Samples.reserve(TotalPossibleSamples); @@ -402,7 +389,7 @@ PUBLIC VIRTUAL void OGG::LoadAllSamples() { } } -PUBLIC void OGG::Dispose() { +void OGG::Dispose() { #ifdef USING_LIBOGG // OGG specific clean up functions VorbisGroup* vorbis = (VorbisGroup*)this->Vorbis; diff --git a/source/Engine/ResourceTypes/SoundFormats/SoundFormat.cpp b/source/Engine/ResourceTypes/SoundFormats/SoundFormat.cpp index 3b61a709..f5f882a0 100644 --- a/source/Engine/ResourceTypes/SoundFormats/SoundFormat.cpp +++ b/source/Engine/ResourceTypes/SoundFormats/SoundFormat.cpp @@ -1,33 +1,13 @@ -#if INTERFACE -#include -#include -#include - -class SoundFormat { -public: - // Common - Stream* StreamPtr = NULL; - SDL_AudioSpec InputFormat; - - vector Samples; - size_t SampleSize; - size_t SampleIndex = 0; - - int TotalPossibleSamples; - Uint8* SampleBuffer = NULL; -}; -#endif - #include #include #include #include -PUBLIC VIRTUAL int SoundFormat::LoadSamples(size_t count) { +int SoundFormat::LoadSamples(size_t count) { return 0; } -PUBLIC VIRTUAL int SoundFormat::GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex) { +int SoundFormat::GetSamples(Uint8* buffer, size_t count, Sint32 loopIndex) { if (SampleIndex >= Samples.size()) { if (LoadSamples(count) == 0) // If we've reached end of file return 0; @@ -45,18 +25,18 @@ PUBLIC VIRTUAL int SoundFormat::GetSamples(Uint8* buffer, size_t count, Sint3 SampleIndex += samplecount; return (int)samplecount; } -PUBLIC VIRTUAL size_t SoundFormat::SeekSample(int index) { +size_t SoundFormat::SeekSample(int index) { SampleIndex = (size_t)index; return SampleIndex; } -PUBLIC VIRTUAL size_t SoundFormat::TellSample() { +size_t SoundFormat::TellSample() { return SampleIndex; } -PUBLIC VIRTUAL void SoundFormat::LoadAllSamples() { +void SoundFormat::LoadAllSamples() { LoadSamples(TotalPossibleSamples - Samples.size()); } -PUBLIC void SoundFormat::CopySamples(SoundFormat* dest) { +void SoundFormat::CopySamples(SoundFormat* dest) { // Load the entire sound if (Samples.size() < TotalPossibleSamples) { LoadAllSamples(); @@ -73,34 +53,34 @@ PUBLIC void SoundFormat::CopySamples(SoundFormat* dest) { dest->InputFormat = InputFormat; } -PUBLIC VIRTUAL double SoundFormat::GetPosition() { +double SoundFormat::GetPosition() { return (double)SampleIndex / InputFormat.freq; } -PUBLIC VIRTUAL double SoundFormat::SetPosition(double seconds) { +double SoundFormat::SetPosition(double seconds) { SampleIndex = (size_t)(seconds * InputFormat.freq); return GetPosition(); } -PUBLIC VIRTUAL double SoundFormat::GetDuration() { +double SoundFormat::GetDuration() { return (double)TotalPossibleSamples / InputFormat.freq; } -PROTECTED void SoundFormat::LoadFinish() { +void SoundFormat::LoadFinish() { SampleIndex = 0; SampleSize = ((InputFormat.format & 0xFF) >> 3) * InputFormat.channels; SampleBuffer = NULL; } -PUBLIC VIRTUAL SoundFormat::~SoundFormat() { +SoundFormat::~SoundFormat() { // Do not add anything to a base class' destructor. } -PUBLIC VIRTUAL void SoundFormat::Close() { +void SoundFormat::Close() { if (StreamPtr) { StreamPtr->Close(); StreamPtr = NULL; } } -PUBLIC VIRTUAL void SoundFormat::Dispose() { +void SoundFormat::Dispose() { Samples.clear(); Samples.shrink_to_fit(); diff --git a/source/Engine/ResourceTypes/SoundFormats/WAV.cpp b/source/Engine/ResourceTypes/SoundFormats/WAV.cpp index 6c6d2730..8c4c0ee6 100644 --- a/source/Engine/ResourceTypes/SoundFormats/WAV.cpp +++ b/source/Engine/ResourceTypes/SoundFormats/WAV.cpp @@ -1,16 +1,3 @@ -#if INTERFACE -#include -#include - -#include - -class WAV : public SoundFormat { -private: - // WAV Specific - int DataStart = 0; -}; -#endif - #include #include @@ -48,7 +35,7 @@ struct WAVheader { Uint8 OverflowBuffer[64]; }; -PUBLIC STATIC SoundFormat* WAV::Load(const char* filename) { +SoundFormat* WAV::Load(const char* filename) { WAV* wav = NULL; class Stream* stream = ResourceStream::New(filename); if (!stream) { @@ -111,7 +98,7 @@ PUBLIC STATIC SoundFormat* WAV::Load(const char* filename) { return wav; } -PUBLIC int WAV::LoadSamples(size_t count) { +int WAV::LoadSamples(size_t count) { size_t read, bytesForSample = 0, total = 0; @@ -146,7 +133,7 @@ PUBLIC int WAV::LoadSamples(size_t count) { return (int)total; } -PUBLIC void WAV::Dispose() { +void WAV::Dispose() { // WAV specific clean up functions // Common cleanup SoundFormat::Dispose(); diff --git a/source/Engine/Scene.cpp b/source/Engine/Scene.cpp index 318fbb4c..62da3673 100644 --- a/source/Engine/Scene.cpp +++ b/source/Engine/Scene.cpp @@ -1,138 +1,3 @@ -#if INTERFACE -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -need_t Entity; - -class Scene { -public: - static int ShowTileCollisionFlag; - static int ShowObjectRegions; - - static HashMap* Properties; - - static HashMap* ObjectLists; - static HashMap* ObjectRegistries; - - static HashMap* StaticObjectLists; - - static int StaticObjectCount; - static Entity* StaticObjectFirst; - static Entity* StaticObjectLast; - static int DynamicObjectCount; - static Entity* DynamicObjectFirst; - static Entity* DynamicObjectLast; - - static int ObjectCount; - static Entity* ObjectFirst; - static Entity* ObjectLast; - - static int BasePriorityPerLayer; - static int PriorityPerLayer; - static DrawGroupList* PriorityLists; - - static vector Tilesets; - static vector TileSpriteInfos; - static Uint16 EmptyTile; - - static vector Layers; - static bool AnyLayerTileChange; - - static int TileCount; - static int TileWidth; - static int TileHeight; - static int BaseTileCount; - static int BaseTilesetCount; - static bool TileCfgLoaded; - static vector TileCfg; - - static vector SpriteList; - static vector ImageList; - static vector SoundList; - static vector MusicList; - static vector ModelList; - static vector MediaList; - static vector TextureList; - static vector AnimatorList; - - static int Frame; - static bool Paused; - static bool Loaded; - static int TileAnimationEnabled; - - static View Views[MAX_SCENE_VIEWS]; - static int ViewCurrent; - static int ViewsActive; - - static int CurrentDrawGroup; - - static int ObjectViewRenderFlag; - static int TileViewRenderFlag; - - static Perf_ViewRender PERF_ViewRender[MAX_SCENE_VIEWS]; - - static char NextScene[256]; - static char CurrentScene[256]; - static bool DoRestart; - static bool NoPersistency; - - static int TimeEnabled; - static int TimeCounter; - static int Minutes; - static int Seconds; - static int Milliseconds; - - static int Filter; - - static int CurrentSceneInList; - static char CurrentFolder[256]; - static char CurrentID[256]; - static char CurrentResourceFolder[256]; - static char CurrentCategory[256]; - static int ActiveCategory; - - static int DebugMode; - - static float CollisionTolerance; - static bool UseCollisionOffset; - static float CollisionMaskAir; - static CollisionBox CollisionOuter; - static CollisionBox CollisionInner; - static Entity* CollisionEntity; - static CollisionSensor Sensors[6]; - static float CollisionMinimumDistance; - static float LowCollisionTolerance; - static float HighCollisionTolerance; - static int FloorAngleTolerance; - static int WallAngleTolerance; - static int RoofAngleTolerance; - static bool ShowHitboxes; - static int DebugHitboxCount; - static DebugHitboxInfo DebugHitboxList[DEBUG_HITBOX_COUNT]; -}; -#endif - #include #include @@ -503,7 +368,7 @@ void UpdateObject(Entity* ent) { } // Double linked-list functions -PUBLIC STATIC void Scene::Add(Entity** first, Entity** last, int* count, Entity* obj) { +void Scene::Add(Entity** first, Entity** last, int* count, Entity* obj) { // Set "prev" of obj to last obj->PrevEntity = (*last); obj->NextEntity = NULL; @@ -529,7 +394,7 @@ PUBLIC STATIC void Scene::Add(Entity** first, Entity** last, int* count, Entity* Scene::AddToScene(obj); } -PUBLIC STATIC void Scene::Remove(Entity** first, Entity** last, int* count, Entity* obj) { +void Scene::Remove(Entity** first, Entity** last, int* count, Entity* obj) { if (obj == NULL) return; if (obj->Removed) return; @@ -549,7 +414,7 @@ PUBLIC STATIC void Scene::Remove(Entity** first, Entity** last, int* count, Enti Scene::RemoveObject(obj); } -PUBLIC STATIC void Scene::AddToScene(Entity* obj) { +void Scene::AddToScene(Entity* obj) { obj->PrevSceneEntity = Scene::ObjectLast; obj->NextSceneEntity = NULL; @@ -561,7 +426,7 @@ PUBLIC STATIC void Scene::AddToScene(Entity* obj) { Scene::ObjectLast = obj; Scene::ObjectCount++; } -PUBLIC STATIC void Scene::RemoveFromScene(Entity* obj) { +void Scene::RemoveFromScene(Entity* obj) { if (Scene::ObjectFirst == obj) Scene::ObjectFirst = obj->NextSceneEntity; if (Scene::ObjectLast == obj) @@ -576,7 +441,7 @@ PUBLIC STATIC void Scene::RemoveFromScene(Entity* obj) { Scene::ObjectCount--; } -PRIVATE STATIC void Scene::RemoveObject(Entity* obj) { +void Scene::RemoveObject(Entity* obj) { // Remove from proper list if (obj->List) obj->List->Remove(obj); @@ -604,20 +469,20 @@ PRIVATE STATIC void Scene::RemoveObject(Entity* obj) { // won't be in any object list or draw groups at this point. obj->Remove(); } -PUBLIC STATIC void Scene::Clear(Entity** first, Entity** last, int* count) { +void Scene::Clear(Entity** first, Entity** last, int* count) { (*first) = NULL; (*last) = NULL; (*count) = 0; } // Object management -PUBLIC STATIC void Scene::AddStatic(ObjectList* objectList, Entity* obj) { +void Scene::AddStatic(ObjectList* objectList, Entity* obj) { Scene::Add(&Scene::StaticObjectFirst, &Scene::StaticObjectLast, &Scene::StaticObjectCount, obj); } -PUBLIC STATIC void Scene::AddDynamic(ObjectList* objectList, Entity* obj) { +void Scene::AddDynamic(ObjectList* objectList, Entity* obj) { Scene::Add(&Scene::DynamicObjectFirst, &Scene::DynamicObjectLast, &Scene::DynamicObjectCount, obj); } -PUBLIC STATIC void Scene::DeleteRemoved(Entity* obj) { +void Scene::DeleteRemoved(Entity* obj) { if (!obj->Removed) return; @@ -625,7 +490,7 @@ PUBLIC STATIC void Scene::DeleteRemoved(Entity* obj) { delete obj; } -PUBLIC STATIC void Scene::OnEvent(Uint32 event) { +void Scene::OnEvent(Uint32 event) { switch (event) { case SDL_APP_TERMINATING: case SDL_APP_LOWMEMORY: @@ -641,7 +506,7 @@ PUBLIC STATIC void Scene::OnEvent(Uint32 event) { } // Scene List Functions -PUBLIC STATIC void Scene::SetCurrent(const char* categoryName, const char* sceneName) { +void Scene::SetCurrent(const char* categoryName, const char* sceneName) { int categoryID = SceneInfo::GetCategoryID(categoryName); if (categoryID < 0) return; @@ -658,7 +523,7 @@ PUBLIC STATIC void Scene::SetCurrent(const char* categoryName, const char* scene else Scene::CurrentSceneInList = category.OffsetStart; } -PUBLIC STATIC void Scene::SetInfoFromCurrentID() { +void Scene::SetInfoFromCurrentID() { if (!SceneInfo::IsCategoryValid(Scene::ActiveCategory)) return; @@ -678,7 +543,7 @@ PUBLIC STATIC void Scene::SetInfoFromCurrentID() { } // Scene Lifecycle -PUBLIC STATIC void Scene::Init() { +void Scene::Init() { Scene::NextScene[0] = '\0'; Scene::CurrentScene[0] = '\0'; @@ -731,7 +596,7 @@ PUBLIC STATIC void Scene::Init() { if (ScriptManager::LoadAllClasses) ScriptManager::LoadClasses(); } -PUBLIC STATIC void Scene::InitObjectListsAndRegistries() { +void Scene::InitObjectListsAndRegistries() { if (Scene::ObjectLists == NULL) Scene::ObjectLists = new HashMap(CombinedHash::EncryptData, 4); if (Scene::ObjectRegistries == NULL) @@ -740,14 +605,14 @@ PUBLIC STATIC void Scene::InitObjectListsAndRegistries() { Scene::StaticObjectLists = new HashMap(CombinedHash::EncryptData, 4); } -PUBLIC STATIC void Scene::ResetPerf() { +void Scene::ResetPerf() { if (Scene::ObjectLists) { Scene::ObjectLists->ForAll([](Uint32, ObjectList* list) -> void { list->ResetPerf(); }); } } -PUBLIC STATIC void Scene::Update() { +void Scene::Update() { // Animate tiles Scene::RunTileAnimations(); @@ -819,20 +684,20 @@ PUBLIC STATIC void Scene::Update() { Scene::ProcessSceneTimer(); } } -PRIVATE STATIC void Scene::RunTileAnimations() { +void Scene::RunTileAnimations() { if ((Scene::TileAnimationEnabled == 1 && !Scene::Paused) || Scene::TileAnimationEnabled == 2) { for (Tileset& tileset : Scene::Tilesets) tileset.RunAnimations(); } } -PUBLIC STATIC Tileset* Scene::GetTileset(int tileID) { +Tileset* Scene::GetTileset(int tileID) { for (Tileset& tileset : Scene::Tilesets) { if (tileID >= tileset.StartTile) return &tileset; } return nullptr; } -PUBLIC STATIC TileAnimator* Scene::GetTileAnimator(int tileID) { +TileAnimator* Scene::GetTileAnimator(int tileID) { for (Tileset& tileset : Scene::Tilesets) { TileAnimator* animator = tileset.GetTileAnimSequence(tileID); if (animator) @@ -840,7 +705,7 @@ PUBLIC STATIC TileAnimator* Scene::GetTileAnimator(int tileID) { } return nullptr; } -PUBLIC STATIC void Scene::SetViewActive(int viewIndex, bool active) { +void Scene::SetViewActive(int viewIndex, bool active) { if (Scene::Views[viewIndex].Active == active) return; @@ -852,12 +717,12 @@ PUBLIC STATIC void Scene::SetViewActive(int viewIndex, bool active) { Scene::SortViews(); } -PUBLIC STATIC void Scene::SetViewPriority(int viewIndex, int priority) { +void Scene::SetViewPriority(int viewIndex, int priority) { Scene::Views[viewIndex].Priority = priority; Scene::SortViews(); } -PRIVATE STATIC void Scene::ResetViews() { +void Scene::ResetViews() { Scene::ViewsActive = 0; // Deactivate extra views @@ -869,7 +734,7 @@ PRIVATE STATIC void Scene::ResetViews() { Scene::SetViewActive(0, true); } -PUBLIC STATIC void Scene::SortViews() { +void Scene::SortViews() { int count = 0; for (int i = 0; i < MAX_SCENE_VIEWS; i++) { @@ -886,7 +751,7 @@ PUBLIC STATIC void Scene::SortViews() { } } -PUBLIC STATIC void Scene::SetView(int viewIndex) { +void Scene::SetView(int viewIndex) { View* currentView = &Scene::Views[viewIndex]; Graphics::CurrentView = currentView; @@ -915,7 +780,7 @@ PUBLIC STATIC void Scene::SetView(int viewIndex) { Scene::ViewCurrent = viewIndex; } -PUBLIC STATIC bool Scene::CheckPosOnScreen(float posX, float posY, float rangeX, float rangeY) { +bool Scene::CheckPosOnScreen(float posX, float posY, float rangeX, float rangeY) { if (!posX || !posY || !rangeX || !rangeY) return false; @@ -935,7 +800,7 @@ PUBLIC STATIC bool Scene::CheckPosOnScreen(float posX, float posY, float rangeX, #define PERF_START(n) if (viewPerf) viewPerf->n = Clock::GetTicks() #define PERF_END(n) if (viewPerf) viewPerf->n = Clock::GetTicks() - viewPerf->n -PUBLIC STATIC void Scene::RenderView(int viewIndex, bool doPerf) { +void Scene::RenderView(int viewIndex, bool doPerf) { View* currentView = &Scene::Views[viewIndex]; Perf_ViewRender* viewPerf = doPerf ? &Scene::PERF_ViewRender[viewIndex] : NULL; @@ -1185,7 +1050,7 @@ PUBLIC STATIC void Scene::RenderView(int viewIndex, bool doPerf) { PERF_END(RenderFinishTime); } -PUBLIC STATIC void Scene::Render() { +void Scene::Render() { if (!Scene::PriorityLists) return; @@ -1287,7 +1152,7 @@ PUBLIC STATIC void Scene::Render() { Scene::ViewCurrent = -1; } -PUBLIC STATIC void Scene::AfterScene() { +void Scene::AfterScene() { ScriptManager::ResetStack(); ScriptManager::RequestGarbageCollection(); @@ -1310,29 +1175,29 @@ PUBLIC STATIC void Scene::AfterScene() { } } -PRIVATE STATIC void Scene::Iterate(Entity* first, std::function func) { +void Scene::Iterate(Entity* first, std::function func) { for (Entity* ent = first, *next; ent; ent = next) { next = ent->NextEntity; func(ent); } } -PRIVATE STATIC void Scene::IterateAll(Entity* first, std::function func) { +void Scene::IterateAll(Entity* first, std::function func) { for (Entity* ent = first, *next; ent; ent = next) { next = ent->NextSceneEntity; func(ent); } } -PRIVATE STATIC void Scene::ResetPriorityListIndex(Entity* first) { +void Scene::ResetPriorityListIndex(Entity* first) { Scene::Iterate(first, [](Entity* ent) -> void { ent->PriorityListIndex = -1; }); } -PRIVATE STATIC int Scene::GetPersistenceScopeForObjectDeletion() { +int Scene::GetPersistenceScopeForObjectDeletion() { return Scene::NoPersistency ? Persistence_SCENE : Persistence_NONE; } -PUBLIC STATIC void Scene::Restart() { +void Scene::Restart() { Scene::ViewCurrent = 0; Graphics::CurrentView = NULL; @@ -1470,7 +1335,7 @@ PUBLIC STATIC void Scene::Restart() { ScriptManager::ResetStack(); ScriptManager::RequestGarbageCollection(); } -PRIVATE STATIC void Scene::ClearPriorityLists() { +void Scene::ClearPriorityLists() { if (!Scene::PriorityLists) return; @@ -1482,14 +1347,14 @@ PRIVATE STATIC void Scene::ClearPriorityLists() { ResetPriorityListIndex(Scene::StaticObjectFirst); ResetPriorityListIndex(Scene::DynamicObjectFirst); } -PRIVATE STATIC void Scene::DeleteObjects(Entity** first, Entity** last, int* count) { +void Scene::DeleteObjects(Entity** first, Entity** last, int* count) { Scene::Iterate(*first, [](Entity* ent) -> void { // Garbage collection will take care of it later. Scene::RemoveObject(ent); }); Scene::Clear(first, last, count); } -PRIVATE STATIC void Scene::RemoveNonPersistentObjects(Entity** first, Entity** last, int* count) { +void Scene::RemoveNonPersistentObjects(Entity** first, Entity** last, int* count) { int persistencyScope = Scene::GetPersistenceScopeForObjectDeletion(); for (Entity* ent = *first, *next; ent; ent = next) { next = ent->NextEntity; @@ -1497,7 +1362,7 @@ PRIVATE STATIC void Scene::RemoveNonPersistentObjects(Entity** first, Entity** l Scene::Remove(first, last, count, ent); } } -PRIVATE STATIC void Scene::DeleteAllObjects() { +void Scene::DeleteAllObjects() { // Dispose and clear Static objects Scene::DeleteObjects(&Scene::StaticObjectFirst, &Scene::StaticObjectLast, &Scene::StaticObjectCount); @@ -1518,7 +1383,7 @@ PRIVATE STATIC void Scene::DeleteAllObjects() { }); } } -PUBLIC STATIC void Scene::LoadScene(const char* filename) { +void Scene::LoadScene(const char* filename) { // Remove non-persistent objects from lists if (Scene::ObjectLists) { Scene::ObjectLists->ForAll([](Uint32, ObjectList* list) -> void { @@ -1651,7 +1516,7 @@ PUBLIC STATIC void Scene::LoadScene(const char* filename) { Scene::Loaded = false; } -PUBLIC STATIC void Scene::ProcessSceneTimer() { +void Scene::ProcessSceneTimer() { if (Scene::TimeEnabled) { Scene::TimeCounter += 100; @@ -1672,13 +1537,13 @@ PUBLIC STATIC void Scene::ProcessSceneTimer() { } } -PUBLIC STATIC ObjectList* Scene::NewObjectList(const char* objectName) { +ObjectList* Scene::NewObjectList(const char* objectName) { ObjectList* objectList = new (std::nothrow) ObjectList(objectName); if (objectList && ScriptManager::LoadObjectClass(objectName, true)) objectList->SpawnFunction = ScriptManager::ObjectSpawnFunction; return objectList; } -PRIVATE STATIC void Scene::AddStaticClass() { +void Scene::AddStaticClass() { StaticObjectList = Scene::NewObjectList("Static"); if (!StaticObjectList->SpawnFunction) return; @@ -1697,11 +1562,11 @@ PRIVATE STATIC void Scene::AddStaticClass() { StaticObject = obj; } -PRIVATE STATIC void Scene::CallGameStart() { +void Scene::CallGameStart() { if (StaticObject) StaticObject->GameStart(); } -PUBLIC STATIC ObjectList* Scene::GetObjectList(const char* objectName, bool callListLoadFunction) { +ObjectList* Scene::GetObjectList(const char* objectName, bool callListLoadFunction) { Uint32 objectNameHash = Scene::ObjectLists->HashFunction(objectName, strlen(objectName)); ObjectList* objectList; @@ -1717,10 +1582,10 @@ PUBLIC STATIC ObjectList* Scene::GetObjectList(const char* objectName, bool call return objectList; } -PUBLIC STATIC ObjectList* Scene::GetObjectList(const char* objectName) { +ObjectList* Scene::GetObjectList(const char* objectName) { return GetObjectList(objectName, true); } -PUBLIC STATIC ObjectList* Scene::GetStaticObjectList(const char* objectName) { +ObjectList* Scene::GetStaticObjectList(const char* objectName) { ObjectList* objectList; if (Scene::StaticObjectLists->Exists(objectName)) { @@ -1743,7 +1608,7 @@ PUBLIC STATIC ObjectList* Scene::GetStaticObjectList(const char* objectName) { return objectList; } -PRIVATE STATIC void Scene::SpawnStaticObject(const char* objectName) { +void Scene::SpawnStaticObject(const char* objectName) { ObjectList* objectList = Scene::GetObjectList(objectName, false); if (objectList->SpawnFunction) { Entity* obj = objectList->Spawn(); @@ -1757,13 +1622,13 @@ PRIVATE STATIC void Scene::SpawnStaticObject(const char* objectName) { Scene::AddStatic(objectList, obj); } } -PUBLIC STATIC void Scene::AddManagers() { +void Scene::AddManagers() { Scene::SpawnStaticObject("WindowManager"); Scene::SpawnStaticObject("InputManager"); Scene::SpawnStaticObject("FadeManager"); } -PUBLIC STATIC void Scene::FreePriorityLists() { +void Scene::FreePriorityLists() { if (Scene::PriorityLists) { for (int i = Scene::PriorityPerLayer - 1; i >= 0; i--) { Scene::PriorityLists[i].Dispose(); @@ -1773,7 +1638,7 @@ PUBLIC STATIC void Scene::FreePriorityLists() { Scene::PriorityLists = NULL; Scene::PriorityPerLayer = 0; } -PUBLIC STATIC void Scene::InitPriorityLists() { +void Scene::InitPriorityLists() { if (Scene::PriorityPerLayer == 0) Scene::PriorityPerLayer = Scene::BasePriorityPerLayer; @@ -1792,7 +1657,7 @@ PUBLIC STATIC void Scene::InitPriorityLists() { for (int i = Scene::PriorityPerLayer - 1; i >= 0; i--) Scene::PriorityLists[i].Init(); } -PUBLIC STATIC void Scene::SetPriorityPerLayer(int count) { +void Scene::SetPriorityPerLayer(int count) { if (count < 1) count = 1; else if (count > 256) @@ -1814,7 +1679,7 @@ PUBLIC STATIC void Scene::SetPriorityPerLayer(int count) { Scene::PriorityPerLayer = count; } -PRIVATE STATIC void Scene::ReadRSDKTile(TileConfig* tile, Uint8* line) { +void Scene::ReadRSDKTile(TileConfig* tile, Uint8* line) { int bufferPos = 0; Uint8 collisionHeights[16]; @@ -1999,7 +1864,7 @@ PRIVATE STATIC void Scene::ReadRSDKTile(TileConfig* tile, Uint8* line) { tileDest->CollisionBottom[xD] = tile->CollisionTop[xS] ^ 15; } } -PRIVATE STATIC void Scene::LoadRSDKTileConfig(int tilesetID, Stream* tileColReader) { +void Scene::LoadRSDKTileConfig(int tilesetID, Stream* tileColReader) { Uint32 tileCount = 0x400; Uint8* tileData = (Uint8*)Memory::Calloc(1, tileCount * 2 * 0x26); @@ -2033,7 +1898,7 @@ PRIVATE STATIC void Scene::LoadRSDKTileConfig(int tilesetID, Stream* tileColRead Memory::Free(tileData); } -PRIVATE STATIC void Scene::LoadHCOLTileConfig(size_t tilesetID, Stream* tileColReader) { +void Scene::LoadHCOLTileConfig(size_t tilesetID, Stream* tileColReader) { if (!Scene::Tilesets.size() || tilesetID >= Scene::Tilesets.size()) return; @@ -2240,7 +2105,7 @@ PRIVATE STATIC void Scene::LoadHCOLTileConfig(size_t tilesetID, Stream* tileColR } } } -PRIVATE STATIC void Scene::InitTileCollisions() { +void Scene::InitTileCollisions() { if (Scene::TileCount == 0) { size_t tileCount = 0x400; @@ -2265,7 +2130,7 @@ PRIVATE STATIC void Scene::InitTileCollisions() { Scene::TileCfg.push_back(tileCfgA); Scene::TileCfg.push_back(tileCfgB); } -PRIVATE STATIC void Scene::ClearTileCollisions(TileConfig* cfg, size_t numTiles) { +void Scene::ClearTileCollisions(TileConfig* cfg, size_t numTiles) { for (size_t i = 0; i < numTiles; i++) { TileConfig* tile = &cfg[i]; memset(tile->CollisionTop, 16, 16); @@ -2274,7 +2139,7 @@ PRIVATE STATIC void Scene::ClearTileCollisions(TileConfig* cfg, size_t numTiles) memset(tile->CollisionRight, 16, 16); } } -PUBLIC STATIC bool Scene::AddTileset(char* path) { +bool Scene::AddTileset(char* path) { ISprite* tileSprite = new ISprite(); Texture* spriteSheet = tileSprite->AddSpriteSheet(path); if (!spriteSheet) { @@ -2310,7 +2175,7 @@ PUBLIC STATIC bool Scene::AddTileset(char* path) { return true; } -PRIVATE STATIC void Scene::SetTileCount(size_t tileCount) { +void Scene::SetTileCount(size_t tileCount) { vector configFlipX; vector configFlipY; vector configFlipXY; @@ -2357,7 +2222,7 @@ PRIVATE STATIC void Scene::SetTileCount(size_t tileCount) { Scene::TileCount = tileCount; } -PUBLIC STATIC void Scene::LoadTileCollisions(const char* filename, size_t tilesetID) { +void Scene::LoadTileCollisions(const char* filename, size_t tilesetID) { if (!ResourceManager::ResourceExists(filename)) { Log::Print(Log::LOG_WARN, "Could not find tile collision file \"%s\"!", filename); return; @@ -2382,7 +2247,7 @@ PUBLIC STATIC void Scene::LoadTileCollisions(const char* filename, size_t tilese tileColReader->Close(); } -PUBLIC STATIC void Scene::UnloadTileCollisions() { +void Scene::UnloadTileCollisions() { for (size_t i = 0; i < Scene::TileCfg.size(); i++) Memory::Free(Scene::TileCfg[i]); @@ -2393,7 +2258,7 @@ PUBLIC STATIC void Scene::UnloadTileCollisions() { // Resource Management // return true if we found it in the list -PUBLIC STATIC bool Scene::GetResourceListSpace(vector* list, ResourceType* resource, size_t& index, bool& foundEmpty) { +bool Scene::GetResourceListSpace(vector* list, ResourceType* resource, size_t& index, bool& foundEmpty) { foundEmpty = false; index = list->size(); for (size_t i = 0, listSz = list->size(); i < listSz; i++) { @@ -2413,7 +2278,7 @@ PUBLIC STATIC bool Scene::GetResourceListSpace(vector* list, Reso return false; } -PUBLIC STATIC bool Scene::GetResource(vector* list, ResourceType* resource, size_t& index) { +bool Scene::GetResource(vector* list, ResourceType* resource, size_t& index) { bool foundEmpty = false; if (GetResourceListSpace(list, resource, index, foundEmpty)) return true; @@ -2424,7 +2289,7 @@ PUBLIC STATIC bool Scene::GetResource(vector* list, ResourceType* return false; } -PUBLIC STATIC ISprite* Scene::GetSpriteResource(int index) { +ISprite* Scene::GetSpriteResource(int index) { if (index < 0 || index >= (int)Scene::SpriteList.size()) return NULL; @@ -2433,7 +2298,7 @@ PUBLIC STATIC ISprite* Scene::GetSpriteResource(int index) { return Scene::SpriteList[index]->AsSprite; } -PUBLIC STATIC void Scene::DisposeInScope(Uint32 scope) { +void Scene::DisposeInScope(Uint32 scope) { // Images for (size_t i = 0, i_sz = Scene::ImageList.size(); i < i_sz; i++) { if (!Scene::ImageList[i]) continue; @@ -2520,7 +2385,7 @@ PUBLIC STATIC void Scene::DisposeInScope(Uint32 scope) { Scene::AnimatorList[i] = NULL; } } -PUBLIC STATIC void Scene::Dispose() { +void Scene::Dispose() { for (int i = 0; i < MAX_SCENE_VIEWS; i++) { if (Scene::Views[i].DrawTarget) { Graphics::DisposeTexture(Scene::Views[i].DrawTarget); @@ -2615,7 +2480,7 @@ PUBLIC STATIC void Scene::Dispose() { Compiler::Dispose(); } -PUBLIC STATIC void Scene::UnloadTilesets() { +void Scene::UnloadTilesets() { for (size_t i = 0; i < Scene::Tilesets.size(); i++) { if (Scene::Tilesets[i].Sprite) delete Scene::Tilesets[i].Sprite; @@ -2627,7 +2492,7 @@ PUBLIC STATIC void Scene::UnloadTilesets() { } // Tile Batching -PUBLIC STATIC void Scene::SetTile(int layer, int x, int y, int tileID, int flip_x, int flip_y, int collA, int collB) { +void Scene::SetTile(int layer, int x, int y, int tileID, int flip_x, int flip_y, int collA, int collB) { Uint32* tile = &Scene::Layers[layer].Tiles[x + (y << Scene::Layers[layer].WidthInBits)]; *tile = tileID & TILE_IDENT_MASK; @@ -2640,7 +2505,7 @@ PUBLIC STATIC void Scene::SetTile(int layer, int x, int y, int tileID, int flip_ } // Tile Collision -PUBLIC STATIC int Scene::CollisionAt(int x, int y, int collisionField, int collideSide, int* angle) { +int Scene::CollisionAt(int x, int y, int collisionField, int collideSide, int* angle) { if (collisionField < 0 || collisionField >= Scene::TileCfg.size()) return -1; @@ -2743,7 +2608,7 @@ PUBLIC STATIC int Scene::CollisionAt(int x, int y, int collisionField, int coll return -1; } -PUBLIC STATIC int Scene::CollisionInLine(int x, int y, int angleMode, int checkLen, int collisionField, bool compareAngle, Sensor* sensor) { +int Scene::CollisionInLine(int x, int y, int angleMode, int checkLen, int collisionField, bool compareAngle, Sensor* sensor) { if (checkLen < 0 || collisionField < 0 || collisionField >= Scene::TileCfg.size()) return -1; @@ -2929,7 +2794,7 @@ PUBLIC STATIC int Scene::CollisionInLine(int x, int y, int angleMode, int checkL return -1; } -PUBLIC STATIC void Scene::SetupCollisionConfig(float minDistance, float lowTolerance, float highTolerance, int floorAngleTolerance, int wallAngleTolerance, int roofAngleTolerance) { +void Scene::SetupCollisionConfig(float minDistance, float lowTolerance, float highTolerance, int floorAngleTolerance, int wallAngleTolerance, int roofAngleTolerance) { CollisionMinimumDistance = minDistance; LowCollisionTolerance = lowTolerance; HighCollisionTolerance = highTolerance; @@ -2938,7 +2803,7 @@ PUBLIC STATIC void Scene::SetupCollisionConfig(float minDistance, float lowToler RoofAngleTolerance = roofAngleTolerance; } -PUBLIC STATIC int Scene::AddDebugHitbox(int type, int dir, Entity* entity, CollisionBox* hitbox) { +int Scene::AddDebugHitbox(int type, int dir, Entity* entity, CollisionBox* hitbox) { int i = 0; for (; i < DebugHitboxCount; ++i) { if (DebugHitboxList[i].hitbox.Left == hitbox->Left && DebugHitboxList[i].hitbox.Top == hitbox->Top @@ -2979,7 +2844,7 @@ PUBLIC STATIC int Scene::AddDebugHitbox(int type, int dir, Entity* entity, Colli return -1; } -PUBLIC STATIC bool Scene::CheckObjectCollisionTouch(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox) { +bool Scene::CheckObjectCollisionTouch(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox) { int store = 0; if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox) return false; @@ -3038,7 +2903,7 @@ PUBLIC STATIC bool Scene::CheckObjectCollisionTouch(Entity* thisEntity, Collisio return collided; } -PUBLIC STATIC bool Scene::CheckObjectCollisionCircle(Entity* thisEntity, float thisRadius, Entity* otherEntity, float otherRadius) { +bool Scene::CheckObjectCollisionCircle(Entity* thisEntity, float thisRadius, Entity* otherEntity, float otherRadius) { float x = thisEntity->X - otherEntity->X; float y = thisEntity->Y - otherEntity->Y; float r = thisRadius + otherRadius; @@ -3062,7 +2927,7 @@ PUBLIC STATIC bool Scene::CheckObjectCollisionCircle(Entity* thisEntity, float t return x * x + y * y < r * r; } -PUBLIC STATIC bool Scene::CheckObjectCollisionBox(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues) { +bool Scene::CheckObjectCollisionBox(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues) { if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox) return C_NONE; @@ -3255,7 +3120,7 @@ PUBLIC STATIC bool Scene::CheckObjectCollisionBox(Entity* thisEntity, CollisionB return side; } -PUBLIC STATIC bool Scene::CheckObjectCollisionPlatform(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues) { +bool Scene::CheckObjectCollisionPlatform(Entity* thisEntity, CollisionBox* thisHitbox, Entity* otherEntity, CollisionBox* otherHitbox, bool setValues) { int store = 0; bool collided = false; @@ -3363,7 +3228,7 @@ PUBLIC STATIC bool Scene::CheckObjectCollisionPlatform(Entity* thisEntity, Colli return collided; } -PUBLIC STATIC bool Scene::ObjectTileCollision(Entity* entity, int cLayers, int cMode, int cPlane, int xOffset, int yOffset, bool setPos) { +bool Scene::ObjectTileCollision(Entity* entity, int cLayers, int cMode, int cPlane, int xOffset, int yOffset, bool setPos) { int layerID = 1; bool collided = false; int posX = xOffset + entity->X; @@ -3569,7 +3434,7 @@ PUBLIC STATIC bool Scene::ObjectTileCollision(Entity* entity, int cLayers, int c } } -PUBLIC STATIC bool Scene::ObjectTileGrip(Entity* entity, int cLayers, int cMode, int cPlane, float xOffset, float yOffset, float tolerance) { +bool Scene::ObjectTileGrip(Entity* entity, int cLayers, int cMode, int cPlane, float xOffset, float yOffset, float tolerance) { int layerID = 1; bool collided = false; int posX = xOffset + entity->X; @@ -3787,7 +3652,7 @@ PUBLIC STATIC bool Scene::ObjectTileGrip(Entity* entity, int cLayers, int cMode, } } -PUBLIC STATIC void Scene::ProcessObjectMovement(Entity* entity, CollisionBox* outerBox, CollisionBox* innerBox) { +void Scene::ProcessObjectMovement(Entity* entity, CollisionBox* outerBox, CollisionBox* innerBox) { if (entity && outerBox && innerBox) { if (entity->TileCollisions) { entity->Angle &= 0xFF; @@ -3844,7 +3709,7 @@ PUBLIC STATIC void Scene::ProcessObjectMovement(Entity* entity, CollisionBox* ou } } -PUBLIC STATIC void Scene::ProcessPathGrip() { +void Scene::ProcessPathGrip() { float xVel = 0.0; float yVel = 0.0; @@ -4320,7 +4185,7 @@ PUBLIC STATIC void Scene::ProcessPathGrip() { } } -PUBLIC STATIC void Scene::ProcessAirCollision_Down() { +void Scene::ProcessAirCollision_Down() { int movingDown = 0; int movingUp = 0; int movingLeft = 0; @@ -4585,7 +4450,7 @@ PUBLIC STATIC void Scene::ProcessAirCollision_Down() { } } -PUBLIC STATIC void Scene::ProcessAirCollision_Up() { +void Scene::ProcessAirCollision_Up() { int movingDown = 0; int movingUp = 0; int movingLeft = 0; @@ -4850,7 +4715,7 @@ PUBLIC STATIC void Scene::ProcessAirCollision_Up() { } } -PUBLIC STATIC void Scene::SetPathGripSensors(CollisionSensor* sensors) { +void Scene::SetPathGripSensors(CollisionSensor* sensors) { int offset = UseCollisionOffset ? COLLISION_OFFSET : 0.0; switch (CollisionEntity->CollisionMode) { @@ -4918,7 +4783,7 @@ PUBLIC STATIC void Scene::SetPathGripSensors(CollisionSensor* sensors) { } } -PUBLIC STATIC void Scene::FindFloorPosition(CollisionSensor* sensor) { +void Scene::FindFloorPosition(CollisionSensor* sensor) { int x = sensor->X; int y = sensor->Y; int temp; @@ -5018,7 +4883,7 @@ PUBLIC STATIC void Scene::FindFloorPosition(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::FindLWallPosition(CollisionSensor* sensor) { +void Scene::FindLWallPosition(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5088,7 +4953,7 @@ PUBLIC STATIC void Scene::FindLWallPosition(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::FindRoofPosition(CollisionSensor* sensor) { +void Scene::FindRoofPosition(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5157,7 +5022,7 @@ PUBLIC STATIC void Scene::FindRoofPosition(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::FindRWallPosition(CollisionSensor* sensor) { +void Scene::FindRWallPosition(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5227,7 +5092,7 @@ PUBLIC STATIC void Scene::FindRWallPosition(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::FloorCollision(CollisionSensor* sensor) { +void Scene::FloorCollision(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5305,7 +5170,7 @@ PUBLIC STATIC void Scene::FloorCollision(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::LWallCollision(CollisionSensor* sensor) { +void Scene::LWallCollision(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5366,7 +5231,7 @@ PUBLIC STATIC void Scene::LWallCollision(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::RoofCollision(CollisionSensor* sensor) { +void Scene::RoofCollision(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; @@ -5441,7 +5306,7 @@ PUBLIC STATIC void Scene::RoofCollision(CollisionSensor* sensor) { } } -PUBLIC STATIC void Scene::RWallCollision(CollisionSensor* sensor) { +void Scene::RWallCollision(CollisionSensor* sensor) { int posX = sensor->X; int posY = sensor->Y; int OGX = sensor->X; diff --git a/source/Engine/Scene/SceneInfo.cpp b/source/Engine/Scene/SceneInfo.cpp index b0aa6ab1..c4f8c2c5 100644 --- a/source/Engine/Scene/SceneInfo.cpp +++ b/source/Engine/Scene/SceneInfo.cpp @@ -1,23 +1,10 @@ -#if INTERFACE -#include -#include -#include -#include - -class SceneInfo { -public: - static vector Entries; - static vector Categories; -}; -#endif - #include #include vector SceneInfo::Entries; vector SceneInfo::Categories; -PUBLIC STATIC void SceneInfo::Dispose() { +void SceneInfo::Dispose() { for (size_t i = 0; i < Categories.size(); i++) { Categories[i].Properties->WithAll([](Uint32 hash, char* string) -> void { Memory::Free(string); @@ -39,22 +26,22 @@ PUBLIC STATIC void SceneInfo::Dispose() { Entries.shrink_to_fit(); } -PUBLIC STATIC bool SceneInfo::IsCategoryValid(int categoryID) { +bool SceneInfo::IsCategoryValid(int categoryID) { return categoryID >= 0 && categoryID < (int)Categories.size(); } -PUBLIC STATIC bool SceneInfo::IsEntryValid(int entryID) { +bool SceneInfo::IsEntryValid(int entryID) { return entryID >= 0 && entryID < (int)Entries.size(); } -PUBLIC STATIC bool SceneInfo::IsEntryValidInCategory(size_t categoryID, size_t entryID) { +bool SceneInfo::IsEntryValidInCategory(size_t categoryID, size_t entryID) { if (!IsCategoryValid((int)categoryID)) return false; return entryID >= Categories[categoryID].OffsetStart && entryID < Categories[categoryID].OffsetEnd; } -PUBLIC STATIC int SceneInfo::GetCategoryID(const char* categoryName) { +int SceneInfo::GetCategoryID(const char* categoryName) { for (size_t i = 0; i < Categories.size(); i++) { if (!strcmp(Categories[i].Name, categoryName)) return i; @@ -63,7 +50,7 @@ PUBLIC STATIC int SceneInfo::GetCategoryID(const char* categoryName) { return -1; } -PUBLIC STATIC int SceneInfo::GetEntryID(const char* categoryName, const char* entryName) { +int SceneInfo::GetEntryID(const char* categoryName, const char* entryName) { int categoryID = GetCategoryID(categoryName); if (categoryID < 0) return -1; @@ -72,7 +59,7 @@ PUBLIC STATIC int SceneInfo::GetEntryID(const char* categoryName, const char* en return GetEntryIDWithinRange(category.OffsetStart, category.OffsetEnd, entryName); } -PUBLIC STATIC int SceneInfo::GetEntryID(const char* categoryName, size_t entryID) { +int SceneInfo::GetEntryID(const char* categoryName, size_t entryID) { int categoryID = GetCategoryID(categoryName); if (categoryID < 0) return -1; @@ -80,7 +67,7 @@ PUBLIC STATIC int SceneInfo::GetEntryID(const char* categoryName, size_t entryID return GetEntryID((size_t)categoryID, (size_t)entryID); } -PUBLIC STATIC int SceneInfo::GetEntryID(size_t categoryID, size_t entryID) { +int SceneInfo::GetEntryID(size_t categoryID, size_t entryID) { if (!SceneInfo::IsCategoryValid((int)categoryID)) return -1; @@ -92,7 +79,7 @@ PUBLIC STATIC int SceneInfo::GetEntryID(size_t categoryID, size_t entryID) { return (int)actualEntryID; } -PUBLIC STATIC int SceneInfo::GetEntryPosInCategory(const char *categoryName, const char* entryName) { +int SceneInfo::GetEntryPosInCategory(const char *categoryName, const char* entryName) { int categoryID = GetCategoryID(categoryName); if (categoryID < 0) return -1; @@ -100,7 +87,7 @@ PUBLIC STATIC int SceneInfo::GetEntryPosInCategory(const char *categoryName, con return GetEntryPosInCategory((size_t)categoryID, entryName); } -PUBLIC STATIC int SceneInfo::GetEntryPosInCategory(size_t categoryID, const char* entryName) { +int SceneInfo::GetEntryPosInCategory(size_t categoryID, const char* entryName) { if (!SceneInfo::IsCategoryValid((int)categoryID)) return -1; @@ -112,7 +99,7 @@ PUBLIC STATIC int SceneInfo::GetEntryPosInCategory(size_t categoryID, const char return actualEntryID - (int)category.OffsetStart; } -PUBLIC STATIC int SceneInfo::GetEntryIDWithinRange(size_t start, size_t end, const char* entryName) { +int SceneInfo::GetEntryIDWithinRange(size_t start, size_t end, const char* entryName) { for (size_t i = start; i < end; i++) { if (!strcmp(Entries[i].Name, entryName)) return (int)i; @@ -121,7 +108,7 @@ PUBLIC STATIC int SceneInfo::GetEntryIDWithinRange(size_t start, size_t end, con return -1; } -PUBLIC STATIC string SceneInfo::GetParentPath(int entryID) { +string SceneInfo::GetParentPath(int entryID) { SceneListEntry& entry = Entries[entryID]; char filePath[4096]; @@ -138,7 +125,7 @@ PUBLIC STATIC string SceneInfo::GetParentPath(int entryID) { return std::string(filePath); } -PUBLIC STATIC string SceneInfo::GetFilename(int entryID) { +string SceneInfo::GetFilename(int entryID) { SceneListEntry scene = Entries[entryID]; std::string parentPath = GetParentPath(entryID); @@ -174,11 +161,11 @@ PUBLIC STATIC string SceneInfo::GetFilename(int entryID) { return parentPath; } -PUBLIC STATIC string SceneInfo::GetTileConfigFilename(int entryID) { +string SceneInfo::GetTileConfigFilename(int entryID) { return GetParentPath(entryID) + "TileConfig.bin"; } -PUBLIC STATIC char* SceneInfo::GetEntryProperty(int entryID, char* property) { +char* SceneInfo::GetEntryProperty(int entryID, char* property) { if (IsEntryValid(entryID)) { SceneListEntry& entry = Entries[entryID]; if (entry.Properties->Exists(property)) @@ -186,7 +173,7 @@ PUBLIC STATIC char* SceneInfo::GetEntryProperty(int entryID, char* property) { } return nullptr; } -PUBLIC STATIC char* SceneInfo::GetCategoryProperty(int categoryID, char* property) { +char* SceneInfo::GetCategoryProperty(int categoryID, char* property) { if (IsCategoryValid(categoryID)) { SceneListCategory& category = Categories[categoryID]; if (category.Properties->Exists(property)) @@ -195,18 +182,18 @@ PUBLIC STATIC char* SceneInfo::GetCategoryProperty(int categoryID, char* propert return nullptr; } -PUBLIC STATIC bool SceneInfo::HasEntryProperty(int entryID, char* property) { +bool SceneInfo::HasEntryProperty(int entryID, char* property) { if (IsEntryValid(entryID)) return Entries[entryID].Properties->Exists(property); return false; } -PUBLIC STATIC bool SceneInfo::HasCategoryProperty(int categoryID, char* property) { +bool SceneInfo::HasCategoryProperty(int categoryID, char* property) { if (IsCategoryValid(categoryID)) return Categories[categoryID].Properties->Exists(property); return false; } -PRIVATE STATIC void SceneInfo::FillAttributesHashMap(XMLAttributes* attr, HashMap* map) { +void SceneInfo::FillAttributesHashMap(XMLAttributes* attr, HashMap* map) { for (size_t i = 0; i < attr->KeyVector.size(); i++) { char *key = attr->KeyVector[i]; char *value = XMLParser::TokenToString(attr->ValueMap.Get(key)); @@ -215,7 +202,7 @@ PRIVATE STATIC void SceneInfo::FillAttributesHashMap(XMLAttributes* attr, HashMa } } -PUBLIC STATIC bool SceneInfo::Load(XMLNode* node) { +bool SceneInfo::Load(XMLNode* node) { for (size_t i = 0; i < node->children.size(); i++) { XMLNode* listElement = node->children[i]; if (XMLParser::MatchToken(listElement->name, "category")) { diff --git a/source/Engine/Scene/SceneLayer.cpp b/source/Engine/Scene/SceneLayer.cpp index a38d8add..23448a14 100644 --- a/source/Engine/Scene/SceneLayer.cpp +++ b/source/Engine/Scene/SceneLayer.cpp @@ -1,85 +1,11 @@ -#if INTERFACE - -#include -#include -#include -#include - -class SceneLayer { -public: - char Name[50]; - bool Visible = true; - - int Width = 0; - int Height = 0; - Uint32 WidthMask = 0; - Uint32 HeightMask = 0; - Uint32 WidthInBits = 0; - Uint32 HeightInBits = 0; - Uint32 WidthData = 0; - Uint32 HeightData = 0; - Uint32 DataSize = 0; - Uint32 ScrollIndexCount = 0; - - int RelativeY = 0x0100; - int ConstantY = 0x0000; - int OffsetX = 0x0000; - int OffsetY = 0x0000; - - Uint32* Tiles = NULL; - Uint32* TilesBackup = NULL; - Uint16* TileOffsetY = NULL; - - int DeformOffsetA = 0; - int DeformOffsetB = 0; - int DeformSetA[MAX_DEFORM_LINES]; - int DeformSetB[MAX_DEFORM_LINES]; - int DeformSplitLine = 0; - - int Flags = 0x0000; - int DrawGroup = 0; - Uint8 DrawBehavior = 0; - - HashMap* Properties = NULL; - - bool Blending = false; - Uint8 BlendMode = 0; // BlendMode_NORMAL - float Opacity = 1.0f; - - bool UsePaletteIndexLines = false; - - bool UsingCustomScanlineFunction = false; - ObjFunction CustomScanlineFunction; - - bool UsingCustomRenderFunction = false; - ObjFunction CustomRenderFunction; - - int ScrollInfoCount = 0; - ScrollingInfo* ScrollInfos = NULL; - int ScrollInfosSplitIndexesCount = 0; - Uint16* ScrollInfosSplitIndexes = NULL; - Uint8* ScrollIndexes = NULL; - - Uint32 BufferID = 0; - int VertexCount = 0; - void* TileBatches = NULL; - - enum { - FLAGS_COLLIDEABLE = 1, - FLAGS_REPEAT_X = 2, - FLAGS_REPEAT_Y = 4, - }; -}; -#endif - #include #include #include -PUBLIC SceneLayer::SceneLayer() { +SceneLayer::SceneLayer() { } -PUBLIC SceneLayer::SceneLayer(int w, int h) { +SceneLayer::SceneLayer(int w, int h) { Width = w; Height = h; @@ -110,15 +36,15 @@ PUBLIC SceneLayer::SceneLayer(int w, int h) { TilesBackup = (Uint32*)Memory::TrackedCalloc("SceneLayer::TilesBackup", w * h, sizeof(Uint32)); ScrollIndexes = (Uint8*)Memory::Calloc(ScrollIndexCount * 16, sizeof(Uint8)); } -PUBLIC bool SceneLayer::PropertyExists(char* property) { +bool SceneLayer::PropertyExists(char* property) { return Properties && Properties->Exists(property); } -PUBLIC VMValue SceneLayer::PropertyGet(char* property) { +VMValue SceneLayer::PropertyGet(char* property) { if (!PropertyExists(property)) return NULL_VAL; return Properties->Get(property); } -PUBLIC void SceneLayer::Dispose() { +void SceneLayer::Dispose() { if (Properties) delete Properties; if (ScrollInfos) diff --git a/source/Engine/Scene/ScrollingIndex.cpp b/source/Engine/Scene/ScrollingIndex.cpp deleted file mode 100644 index c4112f54..00000000 --- a/source/Engine/Scene/ScrollingIndex.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#if INTERFACE -class ScrollingIndex { -public: - int Index; - int Size; - int* TileBuffers = NULL; -}; -#endif diff --git a/source/Engine/Scene/ScrollingInfo.cpp b/source/Engine/Scene/ScrollingInfo.cpp deleted file mode 100644 index b5032afd..00000000 --- a/source/Engine/Scene/ScrollingInfo.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#if INTERFACE -class ScrollingInfo { -public: - int RelativeParallax; - int ConstantParallax; - char CanDeform; - int Position; - int Offset; -}; -#endif diff --git a/source/Engine/Scene/TileConfig.cpp b/source/Engine/Scene/TileConfig.cpp deleted file mode 100644 index fefc9fd8..00000000 --- a/source/Engine/Scene/TileConfig.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#if INTERFACE -class TileConfig { -public: - Uint8 CollisionTop[16]; - Uint8 CollisionLeft[16]; - Uint8 CollisionRight[16]; - Uint8 CollisionBottom[16]; - Uint8 AngleTop; - Uint8 AngleLeft; - Uint8 AngleRight; - Uint8 AngleBottom; - Uint8 Behavior; - Uint8 IsCeiling; -}; -#endif diff --git a/source/Engine/Scene/TileSpriteInfo.cpp b/source/Engine/Scene/TileSpriteInfo.cpp deleted file mode 100644 index a4b6057c..00000000 --- a/source/Engine/Scene/TileSpriteInfo.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#if INTERFACE -class TileSpriteInfo { -public: - ISprite* Sprite; - int AnimationIndex; - int FrameIndex; - size_t TilesetID; -}; -#endif diff --git a/source/Engine/Scene/View.cpp b/source/Engine/Scene/View.cpp index f59175aa..44d923d8 100644 --- a/source/Engine/Scene/View.cpp +++ b/source/Engine/Scene/View.cpp @@ -1,46 +1,8 @@ -#if INTERFACE -#include -#include -#include - -class View { -public: - bool Active = false; - bool Visible = true; - bool Software = false; - int Priority = 0; - float X = 0.0f; - float Y = 0.0f; - float Z = 0.0f; - float RotateX = 0.0f; - float RotateY = 0.0f; - float RotateZ = 0.0f; - float Width = 1.0f; - float Height = 1.0f; - float OutputX = 0.0f; - float OutputY = 0.0f; - float OutputWidth = 1.0f; - float OutputHeight = 1.0f; - int Stride = 1; - float FOV = 45.0f; - float NearPlane = 0.1f; - float FarPlane = 1000.f; - bool UsePerspective = false; - bool UseDrawTarget = false; - bool UseStencil = false; - Texture* DrawTarget = NULL; - Uint8* StencilBuffer = NULL; - size_t StencilBufferSize = 0; - Matrix4x4* ProjectionMatrix = NULL; - Matrix4x4* BaseProjectionMatrix = NULL; -}; -#endif - #include #include #include -PUBLIC void View::SetSize(float w, float h) { +void View::SetSize(float w, float h) { Width = w; Height = h; Stride = Math::CeilPOT(w); @@ -49,14 +11,14 @@ PUBLIC void View::SetSize(float w, float h) { ReallocStencil(); } -PUBLIC void View::SetStencilEnabled(bool enabled) { +void View::SetStencilEnabled(bool enabled) { UseStencil = enabled; if (!UseStencil) return; ReallocStencil(); } -PUBLIC void View::ReallocStencil() { +void View::ReallocStencil() { if (DrawTarget == nullptr) return; @@ -67,11 +29,11 @@ PUBLIC void View::ReallocStencil() { ClearStencil(); } } -PUBLIC void View::ClearStencil() { +void View::ClearStencil() { if (StencilBuffer) memset(StencilBuffer, 0x00, StencilBufferSize * sizeof(*StencilBuffer)); } -PUBLIC void View::DeleteStencil() { +void View::DeleteStencil() { Memory::Free(StencilBuffer); StencilBuffer = NULL; StencilBufferSize = 0; diff --git a/source/Engine/TextFormats/INI/INI.cpp b/source/Engine/TextFormats/INI/INI.cpp index 3da22189..485f1abb 100644 --- a/source/Engine/TextFormats/INI/INI.cpp +++ b/source/Engine/TextFormats/INI/INI.cpp @@ -1,26 +1,10 @@ -#if INTERFACE -#include -#include -#include - -#include - -class INI { -public: - char* Filename = nullptr; - vector Sections; -}; -#endif - #include #include #include #include #include -#define INI_IMPLEMENTATION - -PUBLIC STATIC INI* INI::New(const char* filename) { +INI* INI::New(const char* filename) { INI* ini = new INI; ini->SetFilename(filename); @@ -28,7 +12,7 @@ PUBLIC STATIC INI* INI::New(const char* filename) { return ini; } -PUBLIC STATIC INI* INI::Load(const char* filename) { +INI* INI::Load(const char* filename) { INI* ini = INI::New(filename); SDLStream* stream = SDLStream::New(filename, SDLStream::READ_ACCESS); @@ -49,7 +33,7 @@ PUBLIC STATIC INI* INI::Load(const char* filename) { return ini; } -PUBLIC bool INI::Reload() { +bool INI::Reload() { SDLStream* stream = SDLStream::New(Filename, SDLStream::READ_ACCESS); if (!stream) { Log::Print(Log::LOG_ERROR, "Couldn't open file '%s'!", Filename); @@ -66,7 +50,7 @@ PUBLIC bool INI::Reload() { return true; } -PUBLIC bool INI::Save(const char* filename) { +bool INI::Save(const char* filename) { SDLStream* stream = SDLStream::New(filename, SDLStream::WRITE_ACCESS); if (!stream) { Log::Print(Log::LOG_ERROR, "Couldn't open file '%s'!", filename); @@ -82,15 +66,15 @@ PUBLIC bool INI::Save(const char* filename) { stream->Close(); return true; } -PUBLIC bool INI::Save() { +bool INI::Save() { return Save(Filename); } -PUBLIC void INI::SetFilename(const char* filename) { +void INI::SetFilename(const char* filename) { Memory::Free(Filename); Filename = StringUtils::Duplicate(filename); } -PUBLIC bool INI::Read(Stream* stream) { +bool INI::Read(Stream* stream) { INISection* section = nullptr; size_t length = stream->Length(); @@ -180,7 +164,7 @@ PUBLIC bool INI::Read(Stream* stream) { return true; } -PUBLIC bool INI::Write(Stream* stream) { +bool INI::Write(Stream* stream) { for (INISection* section: Sections) { if (!section->Name && section->Properties.size() == 0) continue; @@ -208,7 +192,7 @@ PUBLIC bool INI::Write(Stream* stream) { return true; } -PUBLIC INISection* INI::FindSection(const char* name) { +INISection* INI::FindSection(const char* name) { if (name == nullptr) return Sections[0]; @@ -220,7 +204,7 @@ PUBLIC INISection* INI::FindSection(const char* name) { return nullptr; } -PUBLIC bool INI::GetString(const char* sectionName, const char* key, char* dest, size_t destSize) { +bool INI::GetString(const char* sectionName, const char* key, char* dest, size_t destSize) { if (!dest || !destSize) return false; @@ -235,7 +219,7 @@ PUBLIC bool INI::GetString(const char* sectionName, const char* key, char* dest, StringUtils::Copy(dest, property->Value, destSize); return true; } -PUBLIC bool INI::GetInteger(const char* sectionName, const char* key, int* dest) { +bool INI::GetInteger(const char* sectionName, const char* key, int* dest) { if (!dest) return false; @@ -249,7 +233,7 @@ PUBLIC bool INI::GetInteger(const char* sectionName, const char* key, int* dest) return StringUtils::ToNumber(dest, property->Value); } -PUBLIC bool INI::GetDecimal(const char* sectionName, const char* key, double* dest) { +bool INI::GetDecimal(const char* sectionName, const char* key, double* dest) { if (!dest) return false; @@ -263,7 +247,7 @@ PUBLIC bool INI::GetDecimal(const char* sectionName, const char* key, double* de return StringUtils::ToDecimal(dest, property->Value); } -PUBLIC bool INI::GetBool(const char* sectionName, const char* key, bool* dest) { +bool INI::GetBool(const char* sectionName, const char* key, bool* dest) { if (!dest) return false; @@ -279,7 +263,7 @@ PUBLIC bool INI::GetBool(const char* sectionName, const char* key, bool* dest) { return true; } -PUBLIC bool INI::SetString(const char* sectionName, const char* key, const char* value) { +bool INI::SetString(const char* sectionName, const char* key, const char* value) { INISection* section = FindSection(sectionName); if (section == nullptr) section = AddSection(sectionName); @@ -293,27 +277,27 @@ PUBLIC bool INI::SetString(const char* sectionName, const char* key, const char* property->SetValue(value); return true; } -PUBLIC bool INI::SetInteger(const char* section, const char* key, int value) { +bool INI::SetInteger(const char* section, const char* key, int value) { char toStr[21]; snprintf(toStr, sizeof toStr, "%d", value); return SetString(section, key, toStr); } -PUBLIC bool INI::SetDecimal(const char* section, const char* key, double value) { +bool INI::SetDecimal(const char* section, const char* key, double value) { char toStr[512]; snprintf(toStr, sizeof toStr, "%lf", value); return SetString(section, key, toStr); } -PUBLIC bool INI::SetBool(const char* section, const char* key, bool value) { +bool INI::SetBool(const char* section, const char* key, bool value) { const char* toStr = value ? "true" : "false"; return SetString(section, key, toStr); } -PUBLIC INISection* INI::AddSection(const char* name) { +INISection* INI::AddSection(const char* name) { INISection* sec = new INISection(name); Sections.push_back(sec); return sec; } -PUBLIC bool INI::RemoveSection(const char* sectionName) { +bool INI::RemoveSection(const char* sectionName) { if (sectionName == nullptr) { Sections[0]->Properties.clear(); return true; @@ -330,14 +314,14 @@ PUBLIC bool INI::RemoveSection(const char* sectionName) { return false; } -PUBLIC bool INI::SectionExists(const char* sectionName) { +bool INI::SectionExists(const char* sectionName) { return FindSection(sectionName) != nullptr; } -PUBLIC int INI::GetSectionCount() { +int INI::GetSectionCount() { return Sections.size() - 1; } -PUBLIC char* INI::GetProperty(const char* sectionName, const char* key) { +char* INI::GetProperty(const char* sectionName, const char* key) { INISection* section = FindSection(sectionName); if (section == nullptr) return nullptr; @@ -348,21 +332,21 @@ PUBLIC char* INI::GetProperty(const char* sectionName, const char* key) { return property->Value; } -PUBLIC bool INI::PropertyExists(const char* sectionName, const char* key) { +bool INI::PropertyExists(const char* sectionName, const char* key) { INISection* section = FindSection(sectionName); if (section == nullptr) return false; return section->FindProperty(key) != nullptr; } -PUBLIC bool INI::RemoveProperty(const char* sectionName, const char* key) { +bool INI::RemoveProperty(const char* sectionName, const char* key) { INISection* section = FindSection(sectionName); if (section == nullptr) return false; return section->RemoveProperty(key); } -PUBLIC int INI::GetPropertyCount(const char* sectionName) { +int INI::GetPropertyCount(const char* sectionName) { INISection* section = FindSection(sectionName); if (section == nullptr) return 0; @@ -370,7 +354,7 @@ PUBLIC int INI::GetPropertyCount(const char* sectionName) { return section->Properties.size(); } -PUBLIC void INI::Dispose() { +void INI::Dispose() { Memory::Free(Filename); for (size_t i = 0; i < Sections.size(); i++) diff --git a/source/Engine/TextFormats/XML/XMLParser.cpp b/source/Engine/TextFormats/XML/XMLParser.cpp index df0d9835..d08d38f0 100644 --- a/source/Engine/TextFormats/XML/XMLParser.cpp +++ b/source/Engine/TextFormats/XML/XMLParser.cpp @@ -1,17 +1,3 @@ -#if INTERFACE -#include -#include -#include -#include -#include -#include - -class XMLParser { -public: - -}; -#endif - #include #include @@ -386,16 +372,16 @@ void GetInstruction() { ConsumeToken(TOKEN_RIGHT_BRACE, "Missing '>' after instruction."); } -PUBLIC STATIC bool XMLParser::MatchToken(Token tok, const char* string) { +bool XMLParser::MatchToken(Token tok, const char* string) { if (tok.Length == 0) return false; return memcmp(string, tok.Start, tok.Length) == 0; } -PUBLIC STATIC float XMLParser::TokenToNumber(Token tok) { +float XMLParser::TokenToNumber(Token tok) { return atof(tok.ToString().c_str()); } -PUBLIC STATIC XMLNode* XMLParser::Parse() { +XMLNode* XMLParser::Parse() { XMLNode* XMLRoot = new (std::nothrow) XMLNode; if (!XMLRoot) return NULL; @@ -476,7 +462,7 @@ PUBLIC STATIC XMLNode* XMLParser::Parse() { return XMLRoot; } -PUBLIC STATIC XMLNode* XMLParser::ParseFromStream(MemoryStream* stream) { +XMLNode* XMLParser::ParseFromStream(MemoryStream* stream) { // NOTE: This fixes the XML overread bug (unterminated string caused bad access/read) stream->SeekEnd(0); stream->WriteByte(0); @@ -495,12 +481,12 @@ PUBLIC STATIC XMLNode* XMLParser::ParseFromStream(MemoryStream* stream) { xml->base_stream = stream; return xml; } -PUBLIC STATIC XMLNode* XMLParser::ParseFromStream(Stream* streamSrc) { +XMLNode* XMLParser::ParseFromStream(Stream* streamSrc) { MemoryStream* stream = MemoryStream::New(streamSrc); if (!stream) return NULL; return XMLParser::ParseFromStream(stream); } -PUBLIC STATIC XMLNode* XMLParser::ParseFromResource(const char* filename) { +XMLNode* XMLParser::ParseFromResource(const char* filename) { ResourceStream* res = ResourceStream::New(filename); if (!res) { Log::Print(Log::LOG_ERROR, "Could not open ResourceStream from \"%s\"", filename); @@ -512,7 +498,7 @@ PUBLIC STATIC XMLNode* XMLParser::ParseFromResource(const char* filename) { return node; } -PUBLIC STATIC char* XMLParser::TokenToString(Token tok) { +char* XMLParser::TokenToString(Token tok) { char* string = StringUtils::Create(tok); if (!string) { Log::Print(Log::LOG_ERROR, "Out of memory converting XML token to string!"); @@ -521,7 +507,7 @@ PUBLIC STATIC char* XMLParser::TokenToString(Token tok) { return string; } -PUBLIC STATIC void XMLParser::CopyTokenToString(Token tok, char* buffer, size_t size) { +void XMLParser::CopyTokenToString(Token tok, char* buffer, size_t size) { size_t length = tok.Length; if (length >= size) length = size - 1; @@ -529,7 +515,7 @@ PUBLIC STATIC void XMLParser::CopyTokenToString(Token tok, char* buffer, siz buffer[length] = '\0'; } -PUBLIC STATIC XMLNode* XMLParser::SearchNode(XMLNode* root, const char* search) { +XMLNode* XMLParser::SearchNode(XMLNode* root, const char* search) { for (size_t i = 0; i < root->children.size(); i++) { XMLNode* node = root->children[i]; if (XMLParser::MatchToken(node->name, search)) @@ -546,7 +532,7 @@ void FreeNode(XMLNode* root) { delete root; } -PUBLIC STATIC void XMLParser::Free(XMLNode* root) { +void XMLParser::Free(XMLNode* root) { if (root->base_stream) root->base_stream->Close(); diff --git a/source/Engine/Types/DrawGroupList.cpp b/source/Engine/Types/DrawGroupList.cpp index 9408a5f2..c7d2a0aa 100644 --- a/source/Engine/Types/DrawGroupList.cpp +++ b/source/Engine/Types/DrawGroupList.cpp @@ -1,43 +1,29 @@ -#if INTERFACE - -#include - -#include - -class DrawGroupList { -public: - vector* Entities = nullptr; - bool EntityDepthSortingEnabled = false; - bool NeedsSorting = false; -}; -#endif - #include #include -PUBLIC DrawGroupList::DrawGroupList() { +DrawGroupList::DrawGroupList() { Init(); } // Double linked-list functions -PUBLIC int DrawGroupList::Add(Entity* obj) { +int DrawGroupList::Add(Entity* obj) { Entities->push_back(obj); if (EntityDepthSortingEnabled) NeedsSorting = true; return Entities->size() - 1; } -PUBLIC bool DrawGroupList::Contains(Entity* obj) { +bool DrawGroupList::Contains(Entity* obj) { return GetEntityIndex(obj) == -1 ? false : true; } -PUBLIC int DrawGroupList::GetEntityIndex(Entity* obj) { +int DrawGroupList::GetEntityIndex(Entity* obj) { for (size_t i = 0, iSz = Entities->size(); i < iSz; i++) { if ((*Entities)[i] == obj) return (int)i; } return -1; } -PUBLIC void DrawGroupList::Remove(Entity* obj) { +void DrawGroupList::Remove(Entity* obj) { for (size_t i = 0, iSz = Entities->size(); i < iSz; i++) { if ((*Entities)[i] == obj) { Entities->erase(Entities->begin() + i); @@ -45,29 +31,29 @@ PUBLIC void DrawGroupList::Remove(Entity* obj) { } } } -PUBLIC void DrawGroupList::Clear() { +void DrawGroupList::Clear() { Entities->clear(); NeedsSorting = false; } -PUBLIC void DrawGroupList::Sort() { +void DrawGroupList::Sort() { std::stable_sort(Entities->begin(), Entities->end(), [](const Entity* entA, const Entity* entB) { return entA->Depth < entB->Depth; }); NeedsSorting = false; } -PUBLIC void DrawGroupList::Init() { +void DrawGroupList::Init() { Entities = new vector(); } -PUBLIC void DrawGroupList::Dispose() { +void DrawGroupList::Dispose() { delete Entities; Entities = nullptr; } -PUBLIC DrawGroupList::~DrawGroupList() { + DrawGroupList::~DrawGroupList() { // Dispose(); } -PUBLIC int DrawGroupList::Count() { +int DrawGroupList::Count() { return Entities->size(); } diff --git a/source/Engine/Types/Entity.cpp b/source/Engine/Types/Entity.cpp index 525e1f62..ccf8e2d5 100644 --- a/source/Engine/Types/Entity.cpp +++ b/source/Engine/Types/Entity.cpp @@ -1,129 +1,11 @@ -#if INTERFACE -#include -#include -#include -#include -#include - -#include -#include - -need_t ObjectList; -need_t ObjectRegistry; -need_t DrawGroupList; - -class Entity { -public: - float InitialX = 0; - float InitialY = 0; - int Active = true; - int Pauseable = true; - int Interactable = true; - int Persistence = Persistence_NONE; - int Activity = ACTIVE_BOUNDS; - int InRange = false; - bool Created = false; - bool PostCreated = false; - - float X = 0.0f; - float Y = 0.0f; - float Z = 0.0f; - - float XSpeed = 0.0f; - float YSpeed = 0.0f; - float GroundSpeed = 0.0f; - float Gravity = 0.0f; - int Ground = false; - - int WasOffScreen = false; - int OnScreen = true; - float OnScreenHitboxW = 0.0f; - float OnScreenHitboxH = 0.0f; - float OnScreenRegionTop = 0.0f; - float OnScreenRegionLeft = 0.0f; - float OnScreenRegionRight = 0.0f; - float OnScreenRegionBottom = 0.0f; - int ViewRenderFlag = 0xFFFFFFFF; - int ViewOverrideFlag = 0; - float RenderRegionW = 0.0f; - float RenderRegionH = 0.0f; - float RenderRegionTop = 0.0f; - float RenderRegionLeft = 0.0f; - float RenderRegionRight = 0.0f; - float RenderRegionBottom = 0.0f; - - int Angle = 0; - int AngleMode = 0; - float ScaleX = 1.0; - float ScaleY = 1.0; - float Rotation = 0.0; - float Alpha = 1.0; - int AutoPhysics = false; - - int Priority = 0; - int PriorityListIndex = -1; - int PriorityOld = -1; - - float Depth = 0.0f; - float OldDepth = 0.0f; - float ZDepth = 0.0; - - int Sprite = -1; - int CurrentAnimation = -1; - int CurrentFrame = -1; - int CurrentFrameCount = 0; - float AnimationSpeedMult = 1.0; - int AnimationSpeedAdd = 0; - int AutoAnimate = true; - float AnimationSpeed = 0.0; - float AnimationTimer = 0.0; - int AnimationFrameDuration = 0; - int AnimationLoopIndex = 0; - - EntityHitbox Hitbox; - int FlipFlag = 0; - - float SensorX = 0.0f; - float SensorY = 0.0f; - int SensorCollided = false; - int SensorAngle = 0; - - float VelocityX = 0.0f; - float VelocityY = 0.0f; - float GroundVel = 0.0f; - float GravityStrength = 0.0f; - int OnGround = false; - int Direction = 0; - - int TileCollisions = false; - int CollisionLayers = 0; - int CollisionPlane = 0; - int CollisionMode = 0; - - int SlotID = -1; - - bool Removed = false; - - Entity* PrevEntity = NULL; - Entity* NextEntity = NULL; - - ObjectList* List = NULL; - Entity* PrevEntityInList = NULL; - Entity* NextEntityInList = NULL; - - Entity* PrevSceneEntity = NULL; - Entity* NextSceneEntity = NULL; -}; -#endif - #include -PUBLIC void Entity::ApplyMotion() { +void Entity::ApplyMotion() { YSpeed += Gravity; X += XSpeed; Y += YSpeed; } -PUBLIC void Entity::Animate() { +void Entity::Animate() { ISprite* sprite = Scene::GetSpriteResource(Sprite); if (!sprite || CurrentAnimation < 0 || (size_t)CurrentAnimation >= sprite->Animations.size()) @@ -173,11 +55,11 @@ PUBLIC void Entity::Animate() { } #endif } -PUBLIC void Entity::SetAnimation(int animation, int frame) { +void Entity::SetAnimation(int animation, int frame) { if (CurrentAnimation != animation) ResetAnimation(animation, frame); } -PUBLIC void Entity::ResetAnimation(int animation, int frame) { +void Entity::ResetAnimation(int animation, int frame) { ISprite* sprite = Scene::GetSpriteResource(Sprite); if (!sprite || animation < 0 || (size_t)animation >= sprite->Animations.size()) @@ -194,7 +76,7 @@ PUBLIC void Entity::ResetAnimation(int animation, int frame) { AnimationSpeed = sprite->Animations[CurrentAnimation].AnimationSpeed; AnimationLoopIndex = sprite->Animations[CurrentAnimation].FrameToLoop; } -PUBLIC bool Entity::BasicCollideWithObject(Entity* other) { +bool Entity::BasicCollideWithObject(Entity* other) { float otherHitboxW = other->Hitbox.Width; float otherHitboxH = other->Hitbox.Height; @@ -207,7 +89,7 @@ PUBLIC bool Entity::BasicCollideWithObject(Entity* other) { other->X + other->Hitbox.GetRight() < X + Hitbox.GetRight() && other->Y + other->Hitbox.GetBottom() < Y + Hitbox.GetBottom(); } -PUBLIC bool Entity::CollideWithObject(Entity* other) { +bool Entity::CollideWithObject(Entity* other) { float sourceFlipX = (this->FlipFlag & 1) ? -1.0 : 1.0; float sourceFlipY = (this->FlipFlag & 2) ? -1.0 : 1.0; float otherFlipX = (other->FlipFlag & 1) ? -1.0 : 1.0; @@ -228,7 +110,7 @@ PUBLIC bool Entity::CollideWithObject(Entity* other) { sourceX - sourceHitboxW > otherX + otherHitboxW || sourceX + sourceHitboxW < otherX - otherHitboxW); } -PUBLIC int Entity::SolidCollideWithObject(Entity* other, int flag) { +int Entity::SolidCollideWithObject(Entity* other, int flag) { // NOTE: "flag" is setValues float initialOtherX = (other->X); float initialOtherY = (other->Y); @@ -378,7 +260,7 @@ PUBLIC int Entity::SolidCollideWithObject(Entity* other, int flag) { } return 0; } -PUBLIC bool Entity::TopSolidCollideWithObject(Entity* other, int flag) { +bool Entity::TopSolidCollideWithObject(Entity* other, int flag) { // NOTE: "flag" might be "UseGroundSpeed" float initialOtherX = (other->X); float initialOtherY = (other->Y); @@ -417,7 +299,7 @@ PUBLIC bool Entity::TopSolidCollideWithObject(Entity* other, int flag) { return true; } -PUBLIC void Entity::Copy(Entity* other) { +void Entity::Copy(Entity* other) { // Add the other entity to this object's list if (other->List != List) { other->List->Remove(other); @@ -440,7 +322,7 @@ PUBLIC void Entity::Copy(Entity* other) { CopyFields(other); } -PUBLIC void Entity::CopyFields(Entity* other) { +void Entity::CopyFields(Entity* other) { #define COPY(which) other->which = which COPY(InitialX); COPY(InitialY); @@ -529,59 +411,59 @@ PUBLIC void Entity::CopyFields(Entity* other) { #undef COPY } -PUBLIC void Entity::ApplyPhysics() { +void Entity::ApplyPhysics() { } -PUBLIC VIRTUAL void Entity::Initialize() { +void Entity::Initialize() { } -PUBLIC VIRTUAL void Entity::Create() { +void Entity::Create() { } -PUBLIC VIRTUAL void Entity::PostCreate() { +void Entity::PostCreate() { } -PUBLIC VIRTUAL void Entity::UpdateEarly() { +void Entity::UpdateEarly() { } -PUBLIC VIRTUAL void Entity::Update() { +void Entity::Update() { } -PUBLIC VIRTUAL void Entity::UpdateLate() { +void Entity::UpdateLate() { } -PUBLIC VIRTUAL void Entity::OnAnimationFinish() { +void Entity::OnAnimationFinish() { } -PUBLIC VIRTUAL void Entity::OnSceneLoad() { +void Entity::OnSceneLoad() { } -PUBLIC VIRTUAL void Entity::OnSceneRestart() { +void Entity::OnSceneRestart() { } -PUBLIC VIRTUAL void Entity::GameStart() { +void Entity::GameStart() { } -PUBLIC VIRTUAL void Entity::RenderEarly() { +void Entity::RenderEarly() { } -PUBLIC VIRTUAL void Entity::Render(int CamX, int CamY) { +void Entity::Render(int CamX, int CamY) { } -PUBLIC VIRTUAL void Entity::RenderLate() { +void Entity::RenderLate() { } -PUBLIC VIRTUAL void Entity::Remove() { +void Entity::Remove() { } -PUBLIC VIRTUAL void Entity::Dispose() { +void Entity::Dispose() { } diff --git a/source/Engine/Types/ObjectList.cpp b/source/Engine/Types/ObjectList.cpp index 3cda52a2..dcb3173e 100644 --- a/source/Engine/Types/ObjectList.cpp +++ b/source/Engine/Types/ObjectList.cpp @@ -1,29 +1,8 @@ -#if INTERFACE -#include -#include - -class ObjectList { -public: - int EntityCount = 0; - int Activity = ACTIVE_NORMAL; - Entity* EntityFirst = nullptr; - Entity* EntityLast = nullptr; - - char* ObjectName; - char* LoadFunctionName; - char* GlobalUpdateFunctionName; - - ObjectListPerformance Performance; - - Entity* (*SpawnFunction)(ObjectList*) = nullptr; -}; -#endif - #include #include -PUBLIC ObjectList::ObjectList(const char* name) { +ObjectList::ObjectList(const char* name) { ObjectName = StringUtils::Duplicate(name); std::string loadFunctionName = std::string(name) + "_Load"; @@ -32,14 +11,14 @@ PUBLIC ObjectList::ObjectList(const char* name) { LoadFunctionName = StringUtils::Create(loadFunctionName); GlobalUpdateFunctionName = StringUtils::Create(globalUpdateFunctionName); } -PUBLIC ObjectList::~ObjectList() { +ObjectList::~ObjectList() { Memory::Free(ObjectName); Memory::Free(LoadFunctionName); Memory::Free(GlobalUpdateFunctionName); } // Double linked-list functions -PUBLIC void ObjectList::Add(Entity* obj) { +void ObjectList::Add(Entity* obj) { // Set "prev" of obj to last obj->PrevEntityInList = EntityLast; obj->NextEntityInList = NULL; @@ -56,7 +35,7 @@ PUBLIC void ObjectList::Add(Entity* obj) { EntityCount++; } -PUBLIC bool ObjectList::Contains(Entity* obj) { +bool ObjectList::Contains(Entity* obj) { for (Entity* search = EntityFirst; search != NULL; search = search->NextEntityInList) { if (search == obj) return true; @@ -64,7 +43,7 @@ PUBLIC bool ObjectList::Contains(Entity* obj) { return false; } -PUBLIC void ObjectList::Remove(Entity* obj) { +void ObjectList::Remove(Entity* obj) { if (obj == NULL) return; obj->List = NULL; @@ -86,7 +65,7 @@ PUBLIC void ObjectList::Remove(Entity* obj) { EntityCount--; } -PUBLIC void ObjectList::Clear() { +void ObjectList::Clear() { EntityCount = 0; EntityFirst = NULL; EntityLast = NULL; @@ -95,14 +74,14 @@ PUBLIC void ObjectList::Clear() { } // ObjectList functions -PUBLIC Entity* ObjectList::Spawn() { +Entity* ObjectList::Spawn() { return SpawnFunction(this); } -PUBLIC void ObjectList::Iterate(std::function func) { +void ObjectList::Iterate(std::function func) { for (Entity* ent = EntityFirst; ent != NULL; ent = ent->NextEntityInList) func(ent); } -PUBLIC void ObjectList::RemoveNonPersistentFromLinkedList(Entity* first, int persistence) { +void ObjectList::RemoveNonPersistentFromLinkedList(Entity* first, int persistence) { for (Entity* ent = first, *next; ent; ent = next) { // Store the "next" so that when/if the current is removed, // it can still be used to point at the end of the loop. @@ -112,18 +91,18 @@ PUBLIC void ObjectList::RemoveNonPersistentFromLinkedList(Entity* first, int per Remove(ent); } } -PUBLIC void ObjectList::RemoveNonPersistentFromLinkedList(Entity* first) { +void ObjectList::RemoveNonPersistentFromLinkedList(Entity* first) { RemoveNonPersistentFromLinkedList(first, Persistence_NONE); } -PUBLIC void ObjectList::ResetPerf() { +void ObjectList::ResetPerf() { Performance.Clear(); } -PUBLIC Entity* ObjectList::GetNth(int n) { +Entity* ObjectList::GetNth(int n) { Entity* ent = EntityFirst; for (ent = EntityFirst; ent != NULL && n > 0; ent = ent->NextEntityInList, n--); return ent; } -PUBLIC Entity* ObjectList::GetClosest(int x, int y) { +Entity* ObjectList::GetClosest(int x, int y) { if (!EntityCount) return NULL; else if (EntityCount == 1) @@ -144,6 +123,6 @@ PUBLIC Entity* ObjectList::GetClosest(int x, int y) { return closest; } -PUBLIC int ObjectList::Count() { +int ObjectList::Count() { return EntityCount; } diff --git a/source/Engine/Types/ObjectRegistry.cpp b/source/Engine/Types/ObjectRegistry.cpp index 89fe80eb..19b195c6 100644 --- a/source/Engine/Types/ObjectRegistry.cpp +++ b/source/Engine/Types/ObjectRegistry.cpp @@ -1,38 +1,28 @@ -#if INTERFACE -#include -#include - -class ObjectRegistry { -public: - vector List; -}; -#endif - #include #include -PUBLIC void ObjectRegistry::Add(Entity* obj) { +void ObjectRegistry::Add(Entity* obj) { if (!Contains(obj)) List.push_back(obj); } -PUBLIC bool ObjectRegistry::Contains(Entity* obj) { +bool ObjectRegistry::Contains(Entity* obj) { return std::find(List.begin(), List.end(), obj) != List.end(); } -PUBLIC void ObjectRegistry::Remove(Entity* obj) { +void ObjectRegistry::Remove(Entity* obj) { if (obj == NULL) return; auto it = std::find(List.begin(), List.end(), obj); if (it != List.end()) List.erase(it); } -PUBLIC void ObjectRegistry::Clear() { +void ObjectRegistry::Clear() { List.clear(); } -PUBLIC void ObjectRegistry::Iterate(std::function func) { +void ObjectRegistry::Iterate(std::function func) { std::for_each(List.begin(), List.end(), func); } -PUBLIC void ObjectRegistry::RemoveNonPersistentFromLinkedList(Entity* first, int persistence) { +void ObjectRegistry::RemoveNonPersistentFromLinkedList(Entity* first, int persistence) { for (Entity* ent = first, *next; ent; ent = next) { // Store the "next" so that when/if the current is removed, // it can still be used to point at the end of the loop. @@ -42,15 +32,15 @@ PUBLIC void ObjectRegistry::RemoveNonPersistentFromLinkedList(Entity* first, int Remove(ent); } } -PUBLIC void ObjectRegistry::RemoveNonPersistentFromLinkedList(Entity* first) { +void ObjectRegistry::RemoveNonPersistentFromLinkedList(Entity* first) { RemoveNonPersistentFromLinkedList(first, Persistence_NONE); } -PUBLIC Entity* ObjectRegistry::GetNth(int n) { +Entity* ObjectRegistry::GetNth(int n) { if (n < 0 || n >= (int)List.size()) return NULL; return List[n]; } -PUBLIC Entity* ObjectRegistry::GetClosest(int x, int y) { +Entity* ObjectRegistry::GetClosest(int x, int y) { if (List.size() == 1) return List[0]; @@ -69,14 +59,14 @@ PUBLIC Entity* ObjectRegistry::GetClosest(int x, int y) { return closest; } -PUBLIC void ObjectRegistry::Dispose() { +void ObjectRegistry::Dispose() { List.clear(); List.shrink_to_fit(); } -PUBLIC ObjectRegistry::~ObjectRegistry() { +ObjectRegistry::~ObjectRegistry() { Dispose(); } -PUBLIC int ObjectRegistry::Count() { +int ObjectRegistry::Count() { return (int)List.size(); } diff --git a/source/Engine/Types/Tileset.cpp b/source/Engine/Types/Tileset.cpp index d3939904..dd1dd73f 100644 --- a/source/Engine/Types/Tileset.cpp +++ b/source/Engine/Types/Tileset.cpp @@ -1,28 +1,7 @@ -#if INTERFACE -#include -#include -#include - -class Tileset { -public: - ISprite* Sprite = nullptr; - char* Filename = nullptr; - int NumCols = 0; - int NumRows = 0; - int TileWidth = 0; - int TileHeight = 0; - size_t StartTile = 0; - size_t FirstGlobalTileID = 0; - size_t TileCount = 0; - unsigned PaletteID = 0; - std::map AnimatorMap; -}; -#endif - #include #include -PUBLIC Tileset::Tileset(ISprite* sprite, int tileWidth, int tileHeight, size_t firstgid, size_t startTile, size_t tileCount, char* filename) { +Tileset::Tileset(ISprite* sprite, int tileWidth, int tileHeight, size_t firstgid, size_t startTile, size_t tileCount, char* filename) { if (sprite->Spritesheets.size() < 1) return; @@ -37,7 +16,7 @@ PUBLIC Tileset::Tileset(ISprite* sprite, int tileWidth, int tileHeight, size_t f Filename = StringUtils::Duplicate(filename); } -PUBLIC void Tileset::RunAnimations() { +void Tileset::RunAnimations() { for (map::iterator it = AnimatorMap.begin(); it != AnimatorMap.end(); it++) { TileAnimator& animator = it->second; if (!animator.Paused) @@ -45,7 +24,7 @@ PUBLIC void Tileset::RunAnimations() { } } -PUBLIC void Tileset::RestartAnimations() { +void Tileset::RestartAnimations() { for (map::iterator it = AnimatorMap.begin(); it != AnimatorMap.end(); it++) { TileAnimator& animator = it->second; animator.RestartAnimation(); @@ -53,7 +32,7 @@ PUBLIC void Tileset::RestartAnimations() { } } -PUBLIC void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, vector& tileIDs, vector& durations) { +void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, vector& tileIDs, vector& durations) { ISprite* tileSprite = Sprite; if (!tileSprite) return; @@ -87,7 +66,7 @@ PUBLIC void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteI AnimatorMap.insert( { tileID, animator } ); } -PUBLIC void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, ISprite* animSprite, int animID) { +void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteInfo, ISprite* animSprite, int animID) { if (animSprite == nullptr) { AnimatorMap.erase(tileID); return; @@ -99,7 +78,7 @@ PUBLIC void Tileset::AddTileAnimSequence(int tileID, TileSpriteInfo* tileSpriteI AnimatorMap.insert( { tileID, animator } ); } -PUBLIC TileAnimator* Tileset::GetTileAnimSequence(int tileID) { +TileAnimator* Tileset::GetTileAnimSequence(int tileID) { std::map::iterator it = AnimatorMap.find(tileID); if (it == AnimatorMap.end()) return nullptr; diff --git a/source/Engine/Utilities/ColorUtils.cpp b/source/Engine/Utilities/ColorUtils.cpp index c6db53c5..6033e274 100644 --- a/source/Engine/Utilities/ColorUtils.cpp +++ b/source/Engine/Utilities/ColorUtils.cpp @@ -1,23 +1,15 @@ -#if INTERFACE -#include - -class ColorUtils { -public: -}; -#endif - #include #define CLAMP_VAL(v, a, b) if (v < a) v = a; else if (v > b) v = b -PUBLIC STATIC Uint32 ColorUtils::ToRGB(int r, int g, int b) { +Uint32 ColorUtils::ToRGB(int r, int g, int b) { CLAMP_VAL(r, 0x00, 0xFF); CLAMP_VAL(g, 0x00, 0xFF); CLAMP_VAL(b, 0x00, 0xFF); return 0xFF000000U | r << 16 | g << 8 | b; } -PUBLIC STATIC Uint32 ColorUtils::ToRGB(int r, int g, int b, int a) { +Uint32 ColorUtils::ToRGB(int r, int g, int b, int a) { CLAMP_VAL(r, 0x00, 0xFF); CLAMP_VAL(g, 0x00, 0xFF); CLAMP_VAL(b, 0x00, 0xFF); @@ -25,14 +17,14 @@ PUBLIC STATIC Uint32 ColorUtils::ToRGB(int r, int g, int b, int a) { return a << 24 | r << 16 | g << 8 | b; } -PUBLIC STATIC Uint32 ColorUtils::ToRGB(float r, float g, float b) { +Uint32 ColorUtils::ToRGB(float r, float g, float b) { int colR = (int)(r * 0xFF); int colG = (int)(g * 0xFF); int colB = (int)(b * 0xFF); return ColorUtils::ToRGB(colR, colG, colB); } -PUBLIC STATIC Uint32 ColorUtils::ToRGB(float r, float g, float b, float a) { +Uint32 ColorUtils::ToRGB(float r, float g, float b, float a) { int colR = (int)(r * 0xFF); int colG = (int)(g * 0xFF); int colB = (int)(b * 0xFF); @@ -40,40 +32,40 @@ PUBLIC STATIC Uint32 ColorUtils::ToRGB(float r, float g, float b, float a) { return ColorUtils::ToRGB(colR, colG, colB, colA); } -PUBLIC STATIC Uint32 ColorUtils::ToRGB(float *r) { +Uint32 ColorUtils::ToRGB(float *r) { return ToRGB(r[0], r[1], r[2]); } -PUBLIC STATIC Uint32 ColorUtils::ToRGBA(float *r) { +Uint32 ColorUtils::ToRGBA(float *r) { return ToRGB(r[0], r[1], r[2], r[3]); } -PUBLIC STATIC void ColorUtils::SeparateRGB(Uint32 color, float* dest) { +void ColorUtils::SeparateRGB(Uint32 color, float* dest) { dest[0] = (color >> 16 & 0xFF) / 255.f; dest[1] = (color >> 8 & 0xFF) / 255.f; dest[2] = (color & 0xFF) / 255.f; } -PUBLIC STATIC void ColorUtils::Separate(Uint32 color, float* dest) { +void ColorUtils::Separate(Uint32 color, float* dest) { dest[3] = (color >> 24 & 0xFF) / 255.f; SeparateRGB(color, dest); } -PUBLIC STATIC void ColorUtils::SeparateRGB(Uint32 color, Uint8* dest) { +void ColorUtils::SeparateRGB(Uint32 color, Uint8* dest) { dest[0] = (color >> 16) & 0xFF; dest[1] = (color >> 8) & 0xFF; dest[2] = color & 0xFF; } -PUBLIC STATIC void ColorUtils::Separate(Uint32 color, Uint8* dest) { +void ColorUtils::Separate(Uint32 color, Uint8* dest) { dest[3] = (color >> 24) & 0xFF; SeparateRGB(color, dest); } -PUBLIC STATIC void ColorUtils::SeparateRGB(float* color, Uint8* dest) { +void ColorUtils::SeparateRGB(float* color, Uint8* dest) { dest[0] = color[0] * 0xFF; dest[1] = color[1] * 0xFF; dest[2] = color[2] * 0xFF; } -PUBLIC STATIC void ColorUtils::Separate(float* color, Uint8* dest) { +void ColorUtils::Separate(float* color, Uint8* dest) { dest[2] = color[3] * 0xFF; SeparateRGB(color, dest); } -PUBLIC STATIC Uint32 ColorUtils::Tint(Uint32 color, Uint32 colorMult) { +Uint32 ColorUtils::Tint(Uint32 color, Uint32 colorMult) { Uint32 dR = (colorMult >> 16) & 0xFF; Uint32 dG = (colorMult >> 8) & 0xFF; Uint32 dB = colorMult & 0xFF; @@ -85,23 +77,23 @@ PUBLIC STATIC Uint32 ColorUtils::Tint(Uint32 color, Uint32 colorMult) { dB = (Uint8)((dB * sB + 0xFF) >> 8); return dB | (dG << 8) | (dR << 16); } -PUBLIC STATIC Uint32 ColorUtils::Tint(Uint32 color, Uint32 colorMult, Uint16 percentage) { +Uint32 ColorUtils::Tint(Uint32 color, Uint32 colorMult, Uint16 percentage) { return Blend(color, Tint(color, colorMult), percentage); } -PUBLIC STATIC Uint32 ColorUtils::Multiply(Uint32 color, Uint32 colorMult) { +Uint32 ColorUtils::Multiply(Uint32 color, Uint32 colorMult) { Uint32 R = (((colorMult >> 16) & 0xFF) + 1) * (color & 0xFF0000); Uint32 G = (((colorMult >> 8) & 0xFF) + 1) * (color & 0x00FF00); Uint32 B = (((colorMult) & 0xFF) + 1) * (color & 0x0000FF); return (int)((R >> 8) | (G >> 8) | (B >> 8)); } -PUBLIC STATIC Uint32 ColorUtils::Blend(Uint32 color1, Uint32 color2, int percent) { +Uint32 ColorUtils::Blend(Uint32 color1, Uint32 color2, int percent) { Uint32 rb = color1 & 0xFF00FFU; Uint32 g = color1 & 0x00FF00U; rb += (((color2 & 0xFF00FFU) - rb) * percent) >> 8; g += (((color2 & 0x00FF00U) - g) * percent) >> 8; return (rb & 0xFF00FFU) | (g & 0x00FF00U); } -PUBLIC STATIC void ColorUtils::ConvertFromARGBtoABGR(Uint32* argb, int count) { +void ColorUtils::ConvertFromARGBtoABGR(Uint32* argb, int count) { for (int p = 0; p < count; p++) { Uint8 red = (*argb >> 16) & 0xFF; Uint8 green = (*argb >> 8) & 0xFF; @@ -110,7 +102,7 @@ PUBLIC STATIC void ColorUtils::ConvertFromARGBtoABGR(Uint32* argb, int count) argb++; } } -PUBLIC STATIC void ColorUtils::ConvertFromABGRtoARGB(Uint32* argb, int count) { +void ColorUtils::ConvertFromABGRtoARGB(Uint32* argb, int count) { for (int p = 0; p < count; p++) { Uint8 blue = (*argb >> 16) & 0xFF; Uint8 green = (*argb >> 8) & 0xFF; @@ -119,7 +111,7 @@ PUBLIC STATIC void ColorUtils::ConvertFromABGRtoARGB(Uint32* argb, int count) argb++; } } -PUBLIC STATIC int ColorUtils::NearestColor(Uint8 r, Uint8 g, Uint8 b, Uint32* palette, unsigned numColors) { +int ColorUtils::NearestColor(Uint8 r, Uint8 g, Uint8 b, Uint32* palette, unsigned numColors) { Sint64 minDist = 255 * 255 * 3; int bestColor = 0; diff --git a/source/Engine/Utilities/StringUtils.cpp b/source/Engine/Utilities/StringUtils.cpp index c9fd7e7e..493f7504 100644 --- a/source/Engine/Utilities/StringUtils.cpp +++ b/source/Engine/Utilities/StringUtils.cpp @@ -1,37 +1,28 @@ -#if INTERFACE -#include -#include - -class StringUtils { -public: -}; -#endif - #include #include -PUBLIC STATIC char* StringUtils::Create(void* src, size_t length) { +char* StringUtils::Create(void* src, size_t length) { char* string = (char*)Memory::Malloc(length + 1); memcpy(string, src, length); string[length] = '\0'; return string; } -PUBLIC STATIC char* StringUtils::Create(string src) { +char* StringUtils::Create(string src) { return StringUtils::Duplicate(src.c_str()); } -PUBLIC STATIC char* StringUtils::Create(Token token) { +char* StringUtils::Create(Token token) { char* string = (char*)Memory::Malloc(token.Length + 1); memcpy(string, token.Start, token.Length); string[token.Length] = '\0'; return string; } -PUBLIC STATIC char* StringUtils::Duplicate(const char* src) { +char* StringUtils::Duplicate(const char* src) { size_t length = strlen(src) + 1; char* string = (char*)Memory::Malloc(length); memcpy(string, src, length); return string; } -PUBLIC STATIC char* StringUtils::Duplicate(const char* src, size_t length) { +char* StringUtils::Duplicate(const char* src, size_t length) { size_t srcLength = strlen(src); if (length > srcLength) length = srcLength; @@ -40,7 +31,7 @@ PUBLIC STATIC char* StringUtils::Duplicate(const char* src, size_t length) { string[length] = '\0'; return string; } -PUBLIC STATIC char* StringUtils::Resize(char* src, size_t length) { +char* StringUtils::Resize(char* src, size_t length) { size_t originalSize = strlen(src); char* string = (char *)Memory::Realloc(src, length + 1); if (length > originalSize) @@ -49,7 +40,7 @@ PUBLIC STATIC char* StringUtils::Resize(char* src, size_t length) { string[length] = '\0'; return string; } -PUBLIC STATIC bool StringUtils::WildcardMatch(const char* first, const char* second) { +bool StringUtils::WildcardMatch(const char* first, const char* second) { if (*first == 0 && *second == 0) return true; if (*first == 0 && *second == '*' && *(second + 1) != 0) @@ -60,14 +51,14 @@ PUBLIC STATIC bool StringUtils::WildcardMatch(const char* first, const char* sec return StringUtils::WildcardMatch(first, second + 1) || StringUtils::WildcardMatch(first + 1, second); return false; } -PUBLIC STATIC bool StringUtils::StartsWith(const char* string, const char* compare) { +bool StringUtils::StartsWith(const char* string, const char* compare) { size_t cmpLen = strlen(compare); if (strlen(string) < cmpLen) return false; return memcmp(string, compare, cmpLen) == 0; } -PUBLIC STATIC char* StringUtils::StrCaseStr(const char* haystack, const char* needle) { +char* StringUtils::StrCaseStr(const char* haystack, const char* needle) { if (!needle[0]) return (char*)haystack; /* Loop over all possible start positions. */ @@ -89,7 +80,7 @@ PUBLIC STATIC char* StringUtils::StrCaseStr(const char* haystack, const char* ne } return NULL; } -PUBLIC STATIC size_t StringUtils::Copy(char* dst, const char* src, size_t sz) { +size_t StringUtils::Copy(char* dst, const char* src, size_t sz) { char* d = dst; const char* s = src; size_t n = sz; @@ -112,7 +103,7 @@ PUBLIC STATIC size_t StringUtils::Copy(char* dst, const char* src, size_t sz) { return s - src - 1; // count does not include NUL } -PUBLIC STATIC size_t StringUtils::Concat(char* dst, const char* src, size_t sz) { +size_t StringUtils::Concat(char* dst, const char* src, size_t sz) { char *d = dst; const char *s = src; size_t n = sz; @@ -137,7 +128,7 @@ PUBLIC STATIC size_t StringUtils::Concat(char* dst, const char* src, size_t sz) return dlen + (s - src); // count does not include NUL } -PUBLIC STATIC bool StringUtils::ToNumber(int* dst, const char* src) { +bool StringUtils::ToNumber(int* dst, const char* src) { char* end; long num = strtol(src, &end, 10); @@ -151,7 +142,7 @@ PUBLIC STATIC bool StringUtils::ToNumber(int* dst, const char* src) { (*dst) = num; return true; } -PUBLIC STATIC bool StringUtils::ToDecimal(double* dst, const char* src) { +bool StringUtils::ToDecimal(double* dst, const char* src) { char* end; double num = strtod(src, &end); @@ -163,13 +154,13 @@ PUBLIC STATIC bool StringUtils::ToDecimal(double* dst, const char* src) { (*dst) = num; return true; } -PUBLIC STATIC bool StringUtils::ToNumber(int* dst, string src) { +bool StringUtils::ToNumber(int* dst, string src) { return ToNumber(dst, src.c_str()); } -PUBLIC STATIC bool StringUtils::ToDecimal(double* dst, string src) { +bool StringUtils::ToDecimal(double* dst, string src) { return ToDecimal(dst, src.c_str()); } -PUBLIC STATIC char* StringUtils::GetPath(const char* filename) { +char* StringUtils::GetPath(const char* filename) { if (!filename) return nullptr; @@ -189,7 +180,7 @@ PUBLIC STATIC char* StringUtils::GetPath(const char* filename) { return path; } -PUBLIC STATIC char* StringUtils::ConcatPaths(const char* pathA, const char* pathB) { +char* StringUtils::ConcatPaths(const char* pathA, const char* pathB) { if (!pathA || !pathB) return nullptr; @@ -217,7 +208,7 @@ PUBLIC STATIC char* StringUtils::ConcatPaths(const char* pathA, const char* path memcpy(newPath, pathB, lenB); return out; } -PUBLIC STATIC char* StringUtils::ReplacePathSeparators(const char* path) { +char* StringUtils::ReplacePathSeparators(const char* path) { if (!path) return nullptr; @@ -239,7 +230,7 @@ PUBLIC STATIC char* StringUtils::ReplacePathSeparators(const char* path) { return newPath; } -PUBLIC STATIC void StringUtils::ReplacePathSeparatorsInPlace(char* path) { +void StringUtils::ReplacePathSeparatorsInPlace(char* path) { if (!path) return; From 77483851ff95f9782d2eebe7e403fa2a01934d0c Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 6 Oct 2024 16:12:22 -0300 Subject: [PATCH 12/13] Update VC++ files --- VisualC/HatchGameEngine.vcxproj | 24 ------------------------ VisualC/HatchGameEngine.vcxproj.filters | 12 ------------ 2 files changed, 36 deletions(-) diff --git a/VisualC/HatchGameEngine.vcxproj b/VisualC/HatchGameEngine.vcxproj index 044eca69..76a10fef 100644 --- a/VisualC/HatchGameEngine.vcxproj +++ b/VisualC/HatchGameEngine.vcxproj @@ -94,11 +94,6 @@ Console Ws2_32.lib;Wldap32.lib;Advapi32.lib;Crypt32.lib;Normaliz.lib;legacy_stdio_definitions.lib;glew32s.lib;opengl32.lib;freetype.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) - - CD "..\tools" -"makeheaders.exe" ../source -CD .. - copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Debug.exe" @@ -118,11 +113,6 @@ CD .. true Ws2_32.lib;Wldap32.lib;Advapi32.lib;Crypt32.lib;Normaliz.lib;legacy_stdio_definitions.lib;glew32s.lib;opengl32.lib;freetype.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) - - CD "..\tools" -"makeheaders.exe" ../source -CD .. - copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Release.exe" @@ -131,11 +121,6 @@ CD .. stdcpp17 - - CD "..\tools" -"makeheaders.exe" ../source -CD .. - copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Debug.exe" @@ -144,11 +129,6 @@ CD .. stdcpp17 - - CD "..\tools" -"makeheaders.exe" ../source -CD .. - copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Release.exe" @@ -263,10 +243,6 @@ CD .. - - - - diff --git a/VisualC/HatchGameEngine.vcxproj.filters b/VisualC/HatchGameEngine.vcxproj.filters index a16cbcd1..d8c447fa 100644 --- a/VisualC/HatchGameEngine.vcxproj.filters +++ b/VisualC/HatchGameEngine.vcxproj.filters @@ -339,18 +339,6 @@ Source Files - - Source Files - - - Source Files - - - Source Files - - - Source Files - Source Files From e30303ef5763b5fc7c8a09e30a7a4644b5673492 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 6 Oct 2024 16:12:39 -0300 Subject: [PATCH 13/13] Enable GitHub workflow for this branch --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index bc55f166..bb098c9a 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -2,7 +2,7 @@ name: CMake (Linux and Windows) on: push: - branches: [ "master", "dev", "workflow-test" ] + branches: [ "master", "dev", "dev-no-makeheaders", "workflow-test" ] pull_request: branches: [ "master", "dev" ]