├── launch.sh ├── include ├── shader_strings.h ├── GridFunctionLibrary.h ├── GridFunctionParameter.h ├── ParallelAnimationGroup.h ├── SequentialAnimationGroup.h ├── singletons.h ├── gui │ ├── gui_common.h │ ├── CanvasGuiSection.h │ ├── RenderGuiWindow.h │ ├── FileDialog.h │ ├── gui_tips.h │ └── UserInterface.h ├── AnimationGroup.h ├── Script.h ├── SerializerContext.h ├── ScriptAnimation.h ├── main.h ├── CurveAnimation.h ├── GridAnimation.h ├── SpriteManager.h ├── RenderingResources.h ├── Canvas.h ├── Texture.h ├── Configuration.h ├── PropertyAnimation.h ├── LuaSaver.h ├── AnimationManager.h ├── LoopComponent.h ├── EasingCurve.h ├── IAnimation.h ├── SpriteEntry.h ├── Serializers.h ├── GridFunction.h ├── ScriptManager.h └── Sprite.h ├── src ├── singletons.cpp ├── gui │ ├── openfile.cpp │ ├── gui_common.cpp │ ├── style.cpp │ ├── CanvasGuiSection.cpp │ └── config_window.cpp ├── LoopComponent.cpp ├── GridFunction.cpp ├── IAnimation.cpp ├── Script.cpp ├── GridAnimation.cpp ├── AnimationGroup.cpp ├── shader_strings.cpp ├── RenderingResources.cpp ├── CurveAnimation.cpp ├── ScriptAnimation.cpp ├── SpriteEntry.cpp ├── PropertyAnimation.cpp ├── EasingCurve.cpp ├── ParallelAnimationGroup.cpp ├── Canvas.cpp ├── Texture.cpp ├── SpriteManager.cpp ├── SequentialAnimationGroup.cpp ├── LuaSaver.cpp └── GridFunctionLibrary.cpp ├── cmake ├── custom_fontawesome_download.in ├── custom_iconfontcppheaders_download.in ├── custom_fontawesome.cmake └── custom_iconfontcppheaders.cmake ├── .itch.toml ├── LICENSE ├── README.md └── .github └── workflows ├── codeql-analysis.yml ├── android.yml ├── macos.yml ├── emscripten.yml ├── windows.yml ├── linux.yml └── mingw.yml /launch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "`dirname "$0"`" 4 | 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib64 6 | cd bin && exec ./spookyghost "$@" 7 | -------------------------------------------------------------------------------- /include/shader_strings.h: -------------------------------------------------------------------------------- 1 | struct ShaderStrings 2 | { 3 | static char const *const texture_vs; 4 | static char const *const texture_fs; 5 | 6 | static char const *const sprite_vs; 7 | static char const *const sprite_fs; 8 | static char const *const meshsprite_vs; 9 | static char const *const meshsprite_snap_vs; 10 | }; 11 | -------------------------------------------------------------------------------- /src/singletons.cpp: -------------------------------------------------------------------------------- 1 | #include "singletons.h" 2 | 3 | Configuration theCfg; 4 | nctl::UniquePtr theCanvas; 5 | nctl::UniquePtr theResizedCanvas; 6 | nctl::UniquePtr theSpritesheet; 7 | nctl::UniquePtr theSpriteMgr; 8 | nctl::UniquePtr theAnimMgr; 9 | nctl::UniquePtr theSaver; 10 | nctl::UniquePtr theScriptingMgr; 11 | -------------------------------------------------------------------------------- /include/GridFunctionLibrary.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_GRIDFUNCTIONLIBRARY 2 | #define CLASS_GRIDFUNCTIONLIBRARY 3 | 4 | #include "GridFunction.h" 5 | 6 | namespace nc = ncine; 7 | 8 | class GridFunctionLibrary 9 | { 10 | public: 11 | static void init(); 12 | static const nctl::Array &gridFunctions() { return gridFunctions_; } 13 | 14 | private: 15 | static nctl::Array gridFunctions_; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /cmake/custom_fontawesome_download.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | 3 | project(fontawesome-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(fontawesome 7 | GIT_REPOSITORY https://github.com/FortAwesome/Font-Awesome.git 8 | GIT_TAG "${FONTAWESOME_VERSION_TAG}" 9 | GIT_SHALLOW TRUE 10 | SOURCE_DIR "${CMAKE_BINARY_DIR}/fontawesome-src" 11 | CONFIGURE_COMMAND "" 12 | BUILD_COMMAND "" 13 | INSTALL_COMMAND "" 14 | TEST_COMMAND "" 15 | ) 16 | -------------------------------------------------------------------------------- /include/GridFunctionParameter.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_GRIDFUNCTIONPARAMETER 2 | #define CLASS_GRIDFUNCTIONPARAMETER 3 | 4 | /// The actual parameter value for a grid function 5 | struct GridFunctionParameter 6 | { 7 | GridFunctionParameter() 8 | : value0(0.0f), value1(0.0) {} 9 | GridFunctionParameter(float v0, float v1) 10 | : value0(v0), value1(v1) {} 11 | 12 | inline void set(float v0, float v1) 13 | { 14 | value0 = v0; 15 | value1 = v1; 16 | } 17 | 18 | float value0; 19 | float value1; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/ParallelAnimationGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_PARALLELANIMATIONGROUP 2 | #define CLASS_PARALLELANIMATIONGROUP 3 | 4 | #include "AnimationGroup.h" 5 | 6 | /// The parallel animation group 7 | class ParallelAnimationGroup : public AnimationGroup 8 | { 9 | public: 10 | nctl::UniquePtr clone() const override; 11 | 12 | inline Type type() const override { return Type::PARALLEL_GROUP; } 13 | 14 | void pause() override; 15 | void play() override; 16 | 17 | void update(float deltaTime) override; 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /cmake/custom_iconfontcppheaders_download.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | 3 | project(iconfontcppheaders-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(iconfontcppheaders 7 | GIT_REPOSITORY https://github.com/juliettef/IconFontCppHeaders.git 8 | GIT_TAG "${ICONFONTCPPHEADERS_VERSION_TAG}" 9 | GIT_SHALLOW TRUE 10 | SOURCE_DIR "${CMAKE_BINARY_DIR}/iconfontcppheaders-src" 11 | CONFIGURE_COMMAND "" 12 | BUILD_COMMAND "" 13 | INSTALL_COMMAND "" 14 | TEST_COMMAND "" 15 | ) 16 | -------------------------------------------------------------------------------- /include/SequentialAnimationGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SEQUENTIALANIMATIONGROUP 2 | #define CLASS_SEQUENTIALANIMATIONGROUP 3 | 4 | #include "AnimationGroup.h" 5 | 6 | /// The sequential animation group class 7 | class SequentialAnimationGroup : public AnimationGroup 8 | { 9 | public: 10 | nctl::UniquePtr clone() const override; 11 | 12 | inline Type type() const override { return Type::SEQUENTIAL_GROUP; } 13 | 14 | void pause() override; 15 | void play() override; 16 | 17 | void update(float deltaTime) override; 18 | 19 | private: 20 | int nextPlayingIndex(int playingIndex); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/singletons.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETONS_H 2 | #define SINGLETONS_H 3 | 4 | #include 5 | #include "Configuration.h" 6 | 7 | class Canvas; 8 | class SpriteManager; 9 | class AnimationManager; 10 | class UserInterface; 11 | class LuaSaver; 12 | class ScriptManager; 13 | 14 | extern Configuration theCfg; 15 | extern nctl::UniquePtr theCanvas; 16 | extern nctl::UniquePtr theResizedCanvas; 17 | extern nctl::UniquePtr theSpritesheet; 18 | extern nctl::UniquePtr theSpriteMgr; 19 | extern nctl::UniquePtr theAnimMgr; 20 | extern nctl::UniquePtr theSaver; 21 | extern nctl::UniquePtr theScriptingMgr; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /.itch.toml: -------------------------------------------------------------------------------- 1 | [[actions]] 2 | name = "play" 3 | path = "bin/spookyghost.exe" 4 | platform = "windows" 5 | 6 | [[actions]] 7 | name = "play" 8 | path = "SpookyGhost.app" 9 | platform = "osx" 10 | 11 | [[actions]] 12 | name = "play" 13 | path = "launch.sh" 14 | platform = "linux" 15 | 16 | [[prereqs]] 17 | name = "vcredist-2019-x64" 18 | 19 | [[actions]] 20 | name = "manual" 21 | path = "docs/documentation.html" 22 | platform = "windows" 23 | 24 | [[actions]] 25 | name = "manual" 26 | path = "SpookyGhost.app/Contents/Resources/docs/documentation.html" 27 | platform = "osx" 28 | 29 | [[actions]] 30 | name = "manual" 31 | path = "share/doc/spookyghost/documentation.html" 32 | platform = "linux" 33 | 34 | [[actions]] 35 | name = "forums" 36 | path = "https://encelo.itch.io/SpookyGhost/community" 37 | -------------------------------------------------------------------------------- /src/gui/openfile.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #endif 9 | 10 | #include "gui/UserInterface.h" 11 | 12 | void UserInterface::openFile(const char *filename) 13 | { 14 | #if defined(_WIN32) 15 | static char buffer[256]; 16 | _fullpath(buffer, filename, 256); 17 | ShellExecute(NULL, "open", buffer, NULL, NULL, SW_SHOWNORMAL); 18 | #elif defined(__APPLE__) 19 | static nctl::String execString(256); 20 | execString.format("open %s", filename); 21 | system(execString.data()); 22 | #elif defined(__linux__) 23 | static nctl::String execString(256); 24 | execString.format("xdg-open %s", filename); 25 | system(execString.data()); 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /include/gui/gui_common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_GUI_H 2 | #define COMMON_GUI_H 3 | 4 | #include 5 | #include 6 | 7 | namespace nc = ncine; 8 | 9 | namespace ncine { 10 | class DropEvent; 11 | } 12 | 13 | namespace ui { 14 | 15 | static const unsigned int MaxStringLength = 256; 16 | 17 | extern nctl::String comboString; 18 | extern nctl::String auxString; 19 | 20 | #ifdef __ANDROID__ 21 | extern nctl::String androidCfgDir; 22 | extern nctl::String androidSaveDir; 23 | #endif 24 | 25 | extern nctl::String projectsDataDir; 26 | extern nctl::String texturesDataDir; 27 | extern nctl::String scriptsDataDir; 28 | 29 | int inputTextCallback(ImGuiInputTextCallbackData *data); 30 | 31 | extern const nc::DropEvent *dropEvent; 32 | extern unsigned int dropUpdateFrames; 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/AnimationGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_ANIMATIONGROUP 2 | #define CLASS_ANIMATIONGROUP 3 | 4 | #include 5 | #include "IAnimation.h" 6 | #include "LoopComponent.h" 7 | 8 | /// The animation group abstract class 9 | class AnimationGroup : public IAnimation 10 | { 11 | public: 12 | AnimationGroup(); 13 | 14 | inline nctl::Array> &anims() { return anims_; } 15 | inline const nctl::Array> &anims() const { return anims_; } 16 | 17 | inline const LoopComponent &loop() const { return loop_; } 18 | inline LoopComponent &loop() { return loop_; } 19 | 20 | void stop() override; 21 | 22 | protected: 23 | LoopComponent loop_; 24 | nctl::Array> anims_; 25 | 26 | void cloneTo(AnimationGroup &other) const; 27 | 28 | void stopAnimations(); 29 | bool shouldReverseAnimDirection(); 30 | void reverseAnimDirection(IAnimation &anim); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/Script.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SCRIPT 2 | #define CLASS_SCRIPT 3 | 4 | #include 5 | #include 6 | 7 | struct lua_State; 8 | 9 | class Sprite; 10 | 11 | namespace nc = ncine; 12 | 13 | /// The class representing a single Lua script 14 | class Script 15 | { 16 | public: 17 | Script(); 18 | Script(const char *filename); 19 | 20 | inline bool canRun() const { return canRun_; } 21 | 22 | inline const nctl::String &name() const { return name_; } 23 | inline void setName(const nctl::String &name) { name_ = name; } 24 | 25 | inline const char *errorMsg() const { return errorMessage_.data(); } 26 | 27 | bool load(const char *filename); 28 | bool reload(); 29 | 30 | private: 31 | bool canRun_; 32 | nctl::String name_; 33 | nctl::String errorMessage_; 34 | nc::LuaStateManager luaState_; 35 | 36 | bool run(const char *filename, const char *chunkName); 37 | 38 | friend class ScriptAnimation; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/gui/gui_common.cpp: -------------------------------------------------------------------------------- 1 | #include "gui/gui_common.h" 2 | 3 | namespace ui { 4 | 5 | nctl::String comboString(1024 * 4); 6 | nctl::String auxString(MaxStringLength); 7 | 8 | #ifdef __ANDROID__ 9 | nctl::String androidCfgDir(MaxStringLength); 10 | nctl::String androidSaveDir(MaxStringLength); 11 | #endif 12 | 13 | nctl::String projectsDataDir(MaxStringLength); 14 | nctl::String texturesDataDir(MaxStringLength); 15 | nctl::String scriptsDataDir(MaxStringLength); 16 | 17 | int inputTextCallback(ImGuiInputTextCallbackData *data) 18 | { 19 | nctl::String *string = reinterpret_cast(data->UserData); 20 | if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) 21 | { 22 | // Resize string callback 23 | ASSERT(data->Buf == string->data()); 24 | string->setLength(static_cast(data->BufTextLen)); 25 | data->Buf = string->data(); 26 | } 27 | return 0; 28 | } 29 | 30 | const nc::DropEvent *dropEvent = nullptr; 31 | unsigned int dropUpdateFrames = 0; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /include/SerializerContext.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SERIALIZERCONTEXT 2 | #define CLASS_SERIALIZERCONTEXT 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct SerializerContext 9 | { 10 | nctl::UniquePtr> textureHash; 11 | nctl::UniquePtr> spriteEntryHash; 12 | nctl::UniquePtr> scriptHash; 13 | nctl::UniquePtr> animationHash; 14 | }; 15 | 16 | struct DeserializerContext 17 | { 18 | int version = 0; 19 | nctl::Array> *textures = nullptr; 20 | nctl::Array> *spriteEntries = nullptr; 21 | nctl::Array> *scripts = nullptr; 22 | nctl::Array> *animations = nullptr; 23 | nctl::HashMap *functionHash = nullptr; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/ScriptAnimation.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SCRIPTANIMATION 2 | #define CLASS_SCRIPTANIMATION 3 | 4 | #include "CurveAnimation.h" 5 | 6 | class Sprite; 7 | class Script; 8 | 9 | /// The script animation class 10 | class ScriptAnimation : public CurveAnimation 11 | { 12 | public: 13 | ScriptAnimation(); 14 | ScriptAnimation(Sprite *sprite, Script *script); 15 | 16 | nctl::UniquePtr clone() const override; 17 | 18 | inline Type type() const override { return Type::SCRIPT; } 19 | 20 | void play() override; 21 | void perform() override; 22 | 23 | inline const Sprite *sprite() const { return sprite_; } 24 | inline Sprite *sprite() { return sprite_; } 25 | void setSprite(Sprite *sprite); 26 | 27 | inline const Script *script() const { return script_; } 28 | inline Script *script() { return script_; } 29 | void setScript(Script *script); 30 | 31 | private: 32 | Sprite *sprite_; 33 | Script *script_; 34 | 35 | bool runScript(const char *functionName, float value); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/main.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_MYEVENTHANDLER 2 | #define CLASS_MYEVENTHANDLER 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ncine { 9 | 10 | class AppConfiguration; 11 | 12 | } 13 | 14 | class UserInterface; 15 | 16 | namespace nc = ncine; 17 | 18 | /// My nCine event handler 19 | class MyEventHandler : 20 | public nc::IAppEventHandler, 21 | public nc::IInputEventHandler 22 | { 23 | public: 24 | void onPreInit(nc::AppConfiguration &config) override; 25 | void onInit() override; 26 | void onShutdown() override; 27 | void onFrameStart() override; 28 | void onChangeScalingFactor(float factor) override; 29 | 30 | void onKeyPressed(const nc::KeyboardEvent &event) override; 31 | void onKeyReleased(const nc::KeyboardEvent &event) override; 32 | void onFilesDropped(const nc::DropEvent &event) override; 33 | bool onQuitRequest() override; 34 | 35 | private: 36 | nctl::UniquePtr ui_; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2025 Angelo Theodorou 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /include/CurveAnimation.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_CURVEANIMATION 2 | #define CLASS_CURVEANIMATION 3 | 4 | #include "IAnimation.h" 5 | #include "EasingCurve.h" 6 | 7 | /// The curve animation abstract class 8 | class CurveAnimation : public IAnimation 9 | { 10 | public: 11 | CurveAnimation(); 12 | CurveAnimation(EasingCurve::Type curveType, Loop::Mode loopMode); 13 | 14 | /// Returns true if the curve value is applied at every update even if the animation is stopped 15 | inline bool isLocked() const { return isLocked_; } 16 | void setLocked(bool locked) { isLocked_ = locked; } 17 | 18 | void stop() override; 19 | void play() override; 20 | 21 | void update(float deltaTime) override; 22 | virtual void perform() = 0; 23 | 24 | inline const EasingCurve &curve() const { return curve_; } 25 | inline EasingCurve &curve() { return curve_; } 26 | 27 | inline float speed() const { return speed_; } 28 | inline float &speed() { return speed_; } 29 | inline void setSpeed(float speed) { speed_ = speed; } 30 | 31 | protected: 32 | bool isLocked_; 33 | EasingCurve curve_; 34 | float speed_; 35 | 36 | void cloneTo(CurveAnimation &other) const; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/GridAnimation.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_GRIDANIMATION 2 | #define CLASS_GRIDANIMATION 3 | 4 | #include 5 | #include 6 | #include "CurveAnimation.h" 7 | #include "GridFunctionParameter.h" 8 | 9 | class Sprite; 10 | class GridFunction; 11 | 12 | /// The grid animation class 13 | class GridAnimation : public CurveAnimation 14 | { 15 | public: 16 | GridAnimation(); 17 | GridAnimation(Sprite *sprite); 18 | 19 | nctl::UniquePtr clone() const override; 20 | 21 | inline Type type() const override { return Type::GRID; } 22 | 23 | void perform() override; 24 | 25 | inline const Sprite *sprite() const { return sprite_; } 26 | inline Sprite *sprite() { return sprite_; } 27 | void setSprite(Sprite *sprite); 28 | 29 | inline const GridFunction *function() const { return gridFunction_; } 30 | void setFunction(const GridFunction *function); 31 | 32 | inline const nctl::Array ¶meters() const { return params_; } 33 | inline nctl::Array ¶meters() { return params_; } 34 | 35 | private: 36 | Sprite *sprite_; 37 | const GridFunction *gridFunction_; 38 | nctl::Array params_; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/gui/CanvasGuiSection.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_CANVASGUISECTION 2 | #define CLASS_CANVASGUISECTION 3 | 4 | #include 5 | 6 | namespace nc = ncine; 7 | 8 | class Canvas; 9 | 10 | /// The class handling the zoom controls of the canvas window 11 | class CanvasGuiSection 12 | { 13 | public: 14 | void create(Canvas &canvas); 15 | 16 | void setResize(const nc::Vector2i &size); 17 | void setResize(int width, int height); 18 | float zoomAmount() const; 19 | 20 | void resetZoom(); 21 | void increaseZoom(); 22 | void decreaseZoom(); 23 | 24 | inline bool showBorders() const { return showBorders_; } 25 | 26 | private: 27 | enum ZoomLevel 28 | { 29 | X1_8, 30 | X1_4, 31 | X1_2, 32 | X1, 33 | X2, 34 | X4, 35 | X8 36 | }; 37 | 38 | enum ResizePreset 39 | { 40 | SIZE16, 41 | SIZE32, 42 | SIZE64, 43 | SIZE128, 44 | SIZE256, 45 | SIZE512, 46 | CUSTOM 47 | }; 48 | 49 | ZoomLevel zoomLevel_ = ZoomLevel::X1; 50 | ResizePreset resizePreset_ = ResizePreset::SIZE256; 51 | nc::Vector2i customCanvasSize_; 52 | int canvasZoomRadio_ = CanvasGuiSection::ZoomLevel::X1; 53 | bool showBorders_ = false; 54 | 55 | nc::Vector2i resizeVector(ResizePreset resizePreset); 56 | nc::Vector2i resizeVector(); 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/SpriteManager.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SPRITEMANAGER 2 | #define CLASS_SPRITEMANAGER 3 | 4 | #include 5 | 6 | class SpriteEntry; 7 | class SpriteGroup; 8 | class Sprite; 9 | class Texture; 10 | 11 | /// The sprite manager class 12 | class SpriteManager 13 | { 14 | public: 15 | SpriteManager(); 16 | 17 | inline nctl::Array> &textures() { return textures_; } 18 | inline const nctl::Array> &textures() const { return textures_; } 19 | 20 | inline SpriteGroup &root() { return *root_; } 21 | inline const SpriteGroup &root() const { return *root_; } 22 | 23 | nctl::Array> &children(); 24 | const nctl::Array> &children() const; 25 | 26 | inline nctl::Array &sprites() { return spritesArray_; } 27 | inline const nctl::Array &sprites() const { return spritesArray_; } 28 | 29 | void updateSpritesArray(); 30 | void update(); 31 | 32 | int textureIndex(const Texture *texture) const; 33 | 34 | SpriteGroup *addGroup(SpriteEntry *selected); 35 | Sprite *addSprite(SpriteEntry *selected, Texture *texture); 36 | void clear(); 37 | 38 | private: 39 | nctl::Array> textures_; 40 | nctl::UniquePtr root_; 41 | 42 | nctl::Array spritesWithoutParent_; 43 | nctl::Array spritesArray_; 44 | 45 | void transform(Sprite *sprite); 46 | void draw(Sprite *sprite); 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Linux](https://github.com/SpookyGhost2D/SpookyGhost/workflows/Linux/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=Linux) 2 | [![macOS](https://github.com/SpookyGhost2D/SpookyGhost/workflows/macOS/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=macOS) 3 | [![Windows](https://github.com/SpookyGhost2D/SpookyGhost/workflows/Windows/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=Windows) 4 | [![MinGW](https://github.com/SpookyGhost2D/SpookyGhost/workflows/MinGW/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=MinGW) 5 | [![Emscripten](https://github.com/SpookyGhost2D/SpookyGhost/workflows/Emscripten/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=Emscripten) 6 | [![Android](https://github.com/SpookyGhost2D/SpookyGhost/workflows/Android/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=Android) 7 | [![CodeQL](https://github.com/SpookyGhost2D/SpookyGhost/workflows/CodeQL/badge.svg)](https://github.com/SpookyGhost2D/SpookyGhost/actions?workflow=CodeQL) 8 | 9 | # SpookyGhost 10 | ![Screenshot](https://spookyghost2d.github.io/spookyghost.png "Screenshot") 11 | 12 | A procedural sprite animation tool made with the [nCine](https://ncine.github.io/). 13 | 14 | You can read the manual [online](https://spookyghost2d.github.io/docs/) or you can access it by pressing F1 in the program. 15 | 16 | For more information: https://encelo.itch.io/spookyghost 17 | -------------------------------------------------------------------------------- /include/RenderingResources.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_RENDERINGRESOURCES 2 | #define CLASS_RENDERINGRESOURCES 3 | 4 | #include 5 | #include 6 | 7 | namespace ncine { 8 | 9 | class GLShaderProgram; 10 | 11 | } 12 | 13 | namespace nc = ncine; 14 | 15 | /// The class that creates and handles some common rendering resources 16 | class RenderingResources 17 | { 18 | public: 19 | static inline nc::GLShaderProgram *spriteShaderProgram() { return spriteShaderProgram_.get(); } 20 | static inline nc::GLShaderProgram *meshSpriteShaderProgram() { return meshSpriteShaderProgram_.get(); } 21 | static inline const nc::Matrix4x4f &projectionMatrix() { return projectionMatrix_; } 22 | 23 | static inline const nc::Vector2f &canvasSize() { return canvasSize_; } 24 | static void setCanvasSize(int width, int height); 25 | 26 | static void create(); 27 | static void dispose(); 28 | 29 | private: 30 | static nctl::UniquePtr spriteShaderProgram_; 31 | static nctl::UniquePtr meshSpriteShaderProgram_; 32 | 33 | static nc::Vector2f canvasSize_; 34 | static nc::Matrix4x4f projectionMatrix_; 35 | 36 | /// Static class, deleted constructor 37 | RenderingResources() = delete; 38 | /// Static class, deleted copy constructor 39 | RenderingResources(const RenderingResources &other) = delete; 40 | /// Static class, deleted assignement operator 41 | RenderingResources &operator=(const RenderingResources &other) = delete; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/Canvas.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_CANVAS 2 | #define CLASS_CANVAS 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ncine { 9 | 10 | class GLTexture; 11 | class GLFramebufferObject; 12 | 13 | } 14 | 15 | namespace nc = ncine; 16 | 17 | /// The canvas texture to display the results 18 | class Canvas 19 | { 20 | public: 21 | nc::Colorf backgroundColor; 22 | 23 | Canvas(); 24 | Canvas(int width, int height); 25 | 26 | inline void resizeTexture(const nc::Vector2i &size) { resizeTexture(size.x, size.y); } 27 | void resizeTexture(int width, int height); 28 | 29 | void bindTexture(); 30 | void unbindTexture(); 31 | 32 | void bindRead(); 33 | void bindDraw(); 34 | void bind(); 35 | void unbind(); 36 | 37 | void save(const char *filename); 38 | 39 | inline int maxTextureSize() const { return maxTextureSize_; } 40 | 41 | inline int texWidth() const { return texWidth_; } 42 | inline int texHeight() const { return texHeight_; } 43 | inline nc::Vector2i size() const { return nc::Vector2i(texWidth_, texHeight_); } 44 | 45 | inline unsigned int texSizeInBytes() const { return texSizeInBytes_; } 46 | inline unsigned char *texPixels() { return pixels_.get(); } 47 | 48 | void *imguiTexId(); 49 | 50 | private: 51 | int maxTextureSize_; 52 | int texWidth_; 53 | int texHeight_; 54 | unsigned int texSizeInBytes_; 55 | 56 | nctl::UniquePtr pixels_; 57 | nctl::UniquePtr texture_; 58 | 59 | nctl::UniquePtr fbo_; 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/Texture.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_TEXTURE 2 | #define CLASS_TEXTURE 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ncine { 9 | 10 | class GLTexture; 11 | class ITextureLoader; 12 | 13 | } 14 | 15 | namespace nc = ncine; 16 | 17 | /// The texture wrapper class 18 | class Texture 19 | { 20 | public: 21 | static const unsigned int MaxNameLength = 64; 22 | 23 | Texture(const char *filename); 24 | Texture(const char *bufferName, const unsigned char *bufferPtr, unsigned long int bufferSize); 25 | 26 | inline const nctl::String &name() const { return name_; } 27 | inline void setName(const nctl::String &name) { name_ = name; } 28 | 29 | inline nc::Vector2i size() const { return nc::Vector2i(width_, height_); } 30 | inline int width() const { return width_; } 31 | inline int height() const { return height_; } 32 | 33 | inline unsigned int numChannels() const { return numChannels_; } 34 | inline unsigned int dataSize() const { return dataSize_; } 35 | 36 | bool loadFromFile(const char *filename); 37 | bool loadFromMemory(const char *bufferName, const unsigned char *bufferPtr, unsigned long int bufferSize); 38 | 39 | void bind(); 40 | void *imguiTexId(); 41 | 42 | private: 43 | nctl::UniquePtr glTexture_; 44 | nctl::String name_; 45 | int width_; 46 | int height_; 47 | unsigned int numChannels_; 48 | unsigned long dataSize_; 49 | 50 | void initialize(const nc::ITextureLoader &texLoader); 51 | void load(const nc::ITextureLoader &texLoader); 52 | 53 | friend class Sprite; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/Configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_CONFIGURATION 2 | #define CLASS_CONFIGURATION 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "gui/gui_common.h" 9 | 10 | namespace nc = ncine; 11 | 12 | /// The configuration to be loaded or saved 13 | struct Configuration 14 | { 15 | const int version = 6; 16 | 17 | int width = 1280; 18 | int height = 720; 19 | float refreshRate = 0.0f; // Added in version 6 20 | int windowPositionX = nc::AppConfiguration::WindowPositionIgnore; // Added in version 6 21 | int windowPositionY = nc::AppConfiguration::WindowPositionIgnore; // Added in version 6 22 | bool fullScreen = false; 23 | bool resizable = true; 24 | 25 | bool withVSync = true; 26 | int frameLimit = 0; 27 | 28 | int canvasWidth = 256; 29 | int canvasHeight = 256; 30 | 31 | bool autoGuiScaling = true; // Added in version 6 32 | #ifdef __ANDROID__ 33 | float guiScaling = 2.0f; // Added in version 2 34 | #else 35 | float guiScaling = 1.0f; // Added in version 2 36 | #endif 37 | nctl::String startupProjectName = nctl::String(ui::MaxStringLength); // Renamed in version 3 38 | bool autoPlayOnStart = true; 39 | 40 | nctl::String projectsPath = nctl::String(ui::MaxStringLength); // Renamed in version 3 41 | nctl::String texturesPath = nctl::String(ui::MaxStringLength); 42 | nctl::String scriptsPath = nctl::String(ui::MaxStringLength); // Added in version 3 43 | 44 | bool showTipsOnStart = true; // Added in version 4 45 | nctl::Array pinnedDirectories = nctl::Array(8); // Added in version 5 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/PropertyAnimation.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_PROPERTYANIMATION 2 | #define CLASS_PROPERTYANIMATION 3 | 4 | #include 5 | #include "CurveAnimation.h" 6 | 7 | class Sprite; 8 | 9 | namespace Properties { 10 | 11 | const unsigned int Count = 12; 12 | static const char *Strings[Count] = { "None", "Position X", "Position Y", "Rotation", 13 | "Scale X", "Scale Y", "AnchorPoint X", "AnchorPoint Y", 14 | "Opacity", "Red Channel", "Green Channel", "Blue Channel" }; 15 | 16 | enum Types 17 | { 18 | NONE, 19 | POSITION_X, 20 | POSITION_Y, 21 | ROTATION, 22 | SCALE_X, 23 | SCALE_Y, 24 | ANCHOR_X, 25 | ANCHOR_Y, 26 | OPACITY, 27 | COLOR_R, 28 | COLOR_G, 29 | COLOR_B 30 | }; 31 | 32 | } 33 | 34 | /// The property animation class 35 | class PropertyAnimation : public CurveAnimation 36 | { 37 | public: 38 | PropertyAnimation(); 39 | PropertyAnimation(Sprite *sprite); 40 | 41 | nctl::UniquePtr clone() const override; 42 | 43 | inline Type type() const override { return Type::PROPERTY; } 44 | 45 | void perform() override; 46 | 47 | inline Properties::Types propertyType() const { return propertyType_; } 48 | const char *propertyName() const; 49 | void setProperty(Properties::Types propertyType); 50 | void setProperty(const char *name); 51 | 52 | inline const Sprite *sprite() const { return sprite_; } 53 | inline Sprite *sprite() { return sprite_; } 54 | void setSprite(Sprite *sprite); 55 | 56 | inline const float *property() const { return property_; } 57 | 58 | private: 59 | Properties::Types propertyType_; 60 | float *property_; 61 | Sprite *sprite_; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/LoopComponent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "LoopComponent.h" 3 | 4 | /////////////////////////////////////////////////////////// 5 | // CONSTRUCTORS and DESTRUCTOR 6 | /////////////////////////////////////////////////////////// 7 | 8 | LoopComponent::LoopComponent(Loop::Mode mode, Loop::Direction direction) 9 | : mode_(mode), direction_(direction), 10 | forward_(true), hasJustReset_(false), 11 | delay_(0.0f), currentDelay_(0.0f), waitDelay_(false) 12 | { 13 | } 14 | 15 | LoopComponent::LoopComponent(Loop::Mode mode) 16 | : LoopComponent(mode, Loop::Direction::FORWARD) 17 | { 18 | } 19 | 20 | LoopComponent::LoopComponent() 21 | : LoopComponent(Loop::Mode::DISABLED, Loop::Direction::FORWARD) 22 | { 23 | } 24 | 25 | /////////////////////////////////////////////////////////// 26 | // PUBLIC FUNCTIONS 27 | /////////////////////////////////////////////////////////// 28 | 29 | void LoopComponent::reverseDirection() 30 | { 31 | if (direction_ == Loop::Direction::FORWARD) 32 | direction_ = Loop::Direction::BACKWARD; 33 | else 34 | direction_ = Loop::Direction::FORWARD; 35 | } 36 | 37 | void LoopComponent::resetDelay() 38 | { 39 | hasJustReset_ = false; 40 | currentDelay_ = 0.0f; 41 | waitDelay_ = false; 42 | } 43 | 44 | bool LoopComponent::shouldWaitDelay(float deltaTime) 45 | { 46 | if (waitDelay_) 47 | { 48 | currentDelay_ += deltaTime; 49 | if (currentDelay_ >= delay_) 50 | { 51 | currentDelay_ = 0.0f; 52 | waitDelay_ = false; 53 | } 54 | else 55 | return true; 56 | } 57 | 58 | if (waitDelay_ == false && hasJustReset_) 59 | { 60 | waitDelay_ = true; 61 | hasJustReset_ = false; 62 | } 63 | 64 | return false; 65 | } 66 | -------------------------------------------------------------------------------- /include/LuaSaver.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_LUASAVER 2 | #define CLASS_LUASAVER 3 | 4 | #include 5 | #include 6 | 7 | class LuaSerializer; 8 | class UserInterface; 9 | class Canvas; 10 | class SpriteManager; 11 | class ScriptManager; 12 | class AnimationManager; 13 | struct Configuration; 14 | 15 | /// The class that helps with Lua serialization 16 | class LuaSaver 17 | { 18 | public: 19 | struct Data 20 | { 21 | Data(Canvas &ca, SpriteManager &spm, ScriptManager &scm, AnimationManager &am) 22 | : canvas(ca), spriteMgr(spm), scriptMgr(scm), animMgr(am) {} 23 | 24 | Canvas &canvas; 25 | SpriteManager &spriteMgr; 26 | ScriptManager &scriptMgr; 27 | AnimationManager &animMgr; 28 | }; 29 | 30 | LuaSaver(unsigned int bufferSize); 31 | 32 | bool load(const char *filename, Data &data); 33 | void save(const char *filename, const Data &data); 34 | 35 | bool loadCfg(const char *filename, Configuration &cfg); 36 | void saveCfg(const char *filename, const Configuration &cfg); 37 | 38 | /// Returns the default configuration file 39 | static const nctl::String &defaultCfgFile() { return defaultCfgFile_; } 40 | /// Sets the default configuration file 41 | static void setDefaultCfgFile(const char *filename) { defaultCfgFile_ = filename; } 42 | 43 | /// Loads the configuration using the default file 44 | inline bool loadCfg(Configuration &cfg) { return loadCfg(defaultCfgFile_.data(), cfg); } 45 | /// Saves the configuration using the default file 46 | inline void saveCfg(const Configuration &cfg) { saveCfg(defaultCfgFile_.data(), cfg); } 47 | 48 | private: 49 | nctl::UniquePtr serializer_; 50 | static nctl::String defaultCfgFile_; 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/AnimationManager.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_ANIMATIONMANAGER 2 | #define CLASS_ANIMATIONMANAGER 3 | 4 | #include 5 | #include "AnimationGroup.h" 6 | 7 | class Sprite; 8 | class Script; 9 | 10 | /// The animation manager class 11 | class AnimationManager 12 | { 13 | public: 14 | AnimationManager(); 15 | 16 | inline AnimationGroup &animGroup() { return *animGroup_; } 17 | inline const AnimationGroup &animGroup() const { return *animGroup_; } 18 | 19 | inline nctl::Array> &anims() { return (*animGroup_).anims(); } 20 | inline const nctl::Array> &anims() const { return (*animGroup_).anims(); } 21 | 22 | inline IAnimation::State state() const { return animGroup_->state(); } 23 | 24 | inline float speedMultiplier() const { return speedMultiplier_; } 25 | inline float &speedMultiplier() { return speedMultiplier_; } 26 | inline void setSpeedMultiplier(float speedMultiplier) { speedMultiplier_ = speedMultiplier; } 27 | 28 | inline void stop() { animGroup_->stop(); } 29 | inline void pause() { animGroup_->pause(); } 30 | inline void play() { animGroup_->play(); } 31 | 32 | void update(float deltaTime); 33 | void clear(); 34 | 35 | void removeAnimation(IAnimation *anim); 36 | void removeSprite(Sprite *sprite); 37 | void assignGridAnchorToParameters(Sprite *sprite); 38 | void removeScript(Script *script); 39 | void reloadScript(Script *script); 40 | void initScriptsForSprite(Sprite *sprite); 41 | void overrideSprite(AnimationGroup &animGroup, Sprite *sprite); 42 | void cloneSpriteAnimations(const Sprite *fromSprite, Sprite *toSprite); 43 | 44 | private: 45 | float speedMultiplier_; 46 | nctl::UniquePtr animGroup_; 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/gui/RenderGuiWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_RENDERGUIWINDOW 2 | #define CLASS_RENDERGUIWINDOW 3 | 4 | #include 5 | #include "gui/gui_common.h" 6 | 7 | namespace nc = ncine; 8 | 9 | class UserInterface; 10 | 11 | struct SaveAnim 12 | { 13 | inline float inverseFps() const { return 1.0f / static_cast(fps); } 14 | 15 | nctl::String filename = nctl::String(ui::MaxStringLength); 16 | unsigned int numSavedFrames = 0; 17 | int numFrames = 60; 18 | int fps = 60; 19 | float canvasResize = 1.0f; 20 | nc::Vector2i sheetDestPos; 21 | }; 22 | 23 | /// The render gui window class 24 | class RenderGuiWindow 25 | { 26 | public: 27 | enum ResizeLevel 28 | { 29 | X1_8, 30 | X1_4, 31 | X1_2, 32 | X1, 33 | X2, 34 | X4, 35 | X8 36 | }; 37 | 38 | enum SpritesheetLayout 39 | { 40 | HRECTANGLE, 41 | VRECTANGLE, 42 | HSTRIP, 43 | VSTRIP, 44 | CUSTOM, 45 | }; 46 | 47 | ResizeLevel resizeLevel = ResizeLevel::X1; 48 | SpritesheetLayout layout = SpritesheetLayout::HRECTANGLE; 49 | nctl::String directory = nctl::String(ui::MaxStringLength); 50 | nctl::String filename = nctl::String(ui::MaxStringLength); 51 | 52 | RenderGuiWindow(UserInterface &ui); 53 | 54 | inline const SaveAnim &saveAnimStatus() const { return saveAnimStatus_; } 55 | inline SaveAnim &saveAnimStatus() { return saveAnimStatus_; } 56 | inline bool shouldSaveFrames() const { return shouldSaveFrames_; } 57 | inline bool shouldSaveSpritesheet() const { return shouldSaveSpritesheet_; } 58 | 59 | static float resizeAmount(ResizeLevel rl); 60 | float resizeAmount() const; 61 | void setResize(float resizeAmount); 62 | 63 | void create(); 64 | void signalFrameSaved(); 65 | void cancelRender(); 66 | 67 | private: 68 | UserInterface &ui_; 69 | SaveAnim saveAnimStatus_; 70 | bool shouldSaveFrames_ = false; 71 | bool shouldSaveSpritesheet_ = false; 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/GridFunction.cpp: -------------------------------------------------------------------------------- 1 | #include "GridFunction.h" 2 | 3 | /////////////////////////////////////////////////////////// 4 | // CONSTRUCTORS and DESTRUCTOR 5 | /////////////////////////////////////////////////////////// 6 | 7 | GridFunction::GridFunction() 8 | : name_(MaxNameLength), parametersInfo_(4), callback_(nullptr) 9 | { 10 | } 11 | 12 | /////////////////////////////////////////////////////////// 13 | // PUBLIC FUNCTIONS 14 | /////////////////////////////////////////////////////////// 15 | 16 | const GridFunction::ParameterInfo &GridFunction::parameterInfo(unsigned int index) const 17 | { 18 | FATAL_ASSERT(index < parametersInfo_.size()); 19 | return parametersInfo_[index]; 20 | } 21 | 22 | const char *GridFunction::parameterName(unsigned int index) const 23 | { 24 | FATAL_ASSERT(index < parametersInfo_.size()); 25 | return parametersInfo_[index].name.data(); 26 | } 27 | 28 | GridFunction::ParameterType GridFunction::parameterType(unsigned int index) const 29 | { 30 | FATAL_ASSERT(index < parametersInfo_.size()); 31 | return parametersInfo_[index].type; 32 | } 33 | 34 | GridFunctionParameter &GridFunction::parameterInitialValue(unsigned int index) 35 | { 36 | FATAL_ASSERT(index < parametersInfo_.size()); 37 | return parametersInfo_[index].initialValue; 38 | } 39 | 40 | GridFunction::ParameterInfo &GridFunction::addParameter(const char *name, ParameterType type, float initialValue0) 41 | { 42 | parametersInfo_.pushBack(ParameterInfo(name, type, initialValue0)); 43 | return parametersInfo_.back(); 44 | } 45 | 46 | GridFunction::ParameterInfo &GridFunction::addParameter(const char *name, ParameterType type, float initialValue0, float initialValue1) 47 | { 48 | parametersInfo_.pushBack(ParameterInfo(name, type, initialValue0, initialValue1)); 49 | return parametersInfo_.back(); 50 | } 51 | 52 | void GridFunction::execute(GridAnimation &animation) const 53 | { 54 | if (callback_ != nullptr) 55 | callback_(animation); 56 | } 57 | -------------------------------------------------------------------------------- /include/LoopComponent.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_LOOPCOMPONENT 2 | #define CLASS_LOOPCOMPONENT 3 | 4 | namespace Loop { 5 | 6 | enum class Direction 7 | { 8 | FORWARD, 9 | BACKWARD 10 | }; 11 | 12 | enum class Mode 13 | { 14 | DISABLED, 15 | REWIND, 16 | PING_PONG 17 | }; 18 | 19 | } 20 | 21 | /// The composition class to add looping functionality 22 | class LoopComponent 23 | { 24 | public: 25 | LoopComponent(Loop::Mode mode, Loop::Direction direction); 26 | LoopComponent(Loop::Mode mode); 27 | LoopComponent(); 28 | 29 | inline Loop::Direction direction() const { return direction_; } 30 | inline void setDirection(Loop::Direction direction) { direction_ = direction; } 31 | void reverseDirection(); 32 | 33 | inline Loop::Mode mode() const { return mode_; } 34 | inline void setMode(Loop::Mode mode) { mode_ = mode; } 35 | 36 | inline bool isGoingForward() const { return forward_; } 37 | inline void goForward(bool forward) { forward_ = forward; } 38 | inline void toggleForward() { forward_ = !forward_; } 39 | 40 | /// Returns true if the loop is starting again this frame 41 | inline bool hasJustReset() const { return hasJustReset_; }; 42 | inline void justResetNow() { hasJustReset_ = true; }; 43 | 44 | inline float delay() const { return delay_; } 45 | inline void setDelay(float loopDelay) { delay_ = loopDelay; } 46 | inline float currentDelay() const { return currentDelay_; } 47 | 48 | void resetDelay(); 49 | bool shouldWaitDelay(float deltaTime); 50 | 51 | private: 52 | Loop::Mode mode_; 53 | Loop::Direction direction_; 54 | bool forward_; 55 | /// A flag to indicate that a loop has just reset this frame 56 | bool hasJustReset_; 57 | 58 | /// Delay amount in seconds before an animation loops again 59 | float delay_; 60 | /// The amount of time in seconds waited until now for the loop delay 61 | float currentDelay_; 62 | /// A flag indicating if an animation should wait for the loop delay 63 | bool waitDelay_; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/IAnimation.cpp: -------------------------------------------------------------------------------- 1 | #include "IAnimation.h" 2 | #include "AnimationGroup.h" 3 | 4 | /////////////////////////////////////////////////////////// 5 | // CONSTRUCTORS and DESTRUCTOR 6 | /////////////////////////////////////////////////////////// 7 | 8 | IAnimation::IAnimation() 9 | : state_(State::STOPPED), parent_(nullptr), 10 | delay_(0.0f), currentDelay_(0.0f) 11 | {} 12 | 13 | /////////////////////////////////////////////////////////// 14 | // PUBLIC FUNCTIONS 15 | /////////////////////////////////////////////////////////// 16 | 17 | void IAnimation::stop() 18 | { 19 | state_ = State::STOPPED; 20 | currentDelay_ = 0.0f; 21 | } 22 | 23 | bool IAnimation::shouldWaitDelay(float deltaTime) 24 | { 25 | currentDelay_ += deltaTime; 26 | if (currentDelay_ < delay_) 27 | return true; 28 | else 29 | { 30 | currentDelay_ = delay_; 31 | return false; 32 | } 33 | } 34 | 35 | int IAnimation::indexInParent() const 36 | { 37 | if (parent_ == nullptr) 38 | return -1; 39 | 40 | int index = -1; 41 | const nctl::Array> &anims = parent_->anims(); 42 | for (unsigned int i = 0; i < anims.size(); i++) 43 | { 44 | if (anims[i].get() == this) 45 | { 46 | index = static_cast(i); 47 | break; 48 | } 49 | } 50 | 51 | return index; 52 | } 53 | 54 | /////////////////////////////////////////////////////////// 55 | // PROTECTED FUNCTIONS 56 | /////////////////////////////////////////////////////////// 57 | 58 | void IAnimation::cloneTo(IAnimation &other) const 59 | { 60 | other.name = name; 61 | other.enabled = enabled; 62 | // Animation state is not cloned 63 | other.state_ = State::STOPPED; 64 | other.parent_ = parent_; 65 | other.delay_ = delay_; 66 | other.currentDelay_ = 0.0f; 67 | } 68 | 69 | bool IAnimation::insideSequential() const 70 | { 71 | IAnimation *parent = parent_; 72 | while (parent != nullptr) 73 | { 74 | if (parent->type() == Type::SEQUENTIAL_GROUP) 75 | return true; 76 | parent = parent->parent_; 77 | } 78 | 79 | return false; 80 | } 81 | -------------------------------------------------------------------------------- /include/EasingCurve.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_EASINGCURVE 2 | #define CLASS_EASINGCURVE 3 | 4 | #include "LoopComponent.h" 5 | 6 | /// The easing curve class 7 | class EasingCurve 8 | { 9 | public: 10 | enum class Type 11 | { 12 | LINEAR, 13 | QUAD, 14 | CUBIC, 15 | QUART, 16 | QUINT, 17 | SINE, 18 | EXPO, 19 | CIRC, 20 | }; 21 | 22 | EasingCurve(Type type, Loop::Mode loopMode); 23 | 24 | inline Type type() const { return type_; } 25 | inline void setType(Type type) { type_ = type; } 26 | 27 | inline const LoopComponent &loop() const { return loop_; } 28 | inline LoopComponent &loop() { return loop_; } 29 | 30 | inline bool hasInitialValue() const { return withInitialValue_; } 31 | inline bool &hasInitialValue() { return withInitialValue_; } 32 | inline void enableInitialValue(bool withInitialValue) { withInitialValue_ = withInitialValue; } 33 | 34 | inline float time() const { return time_; } 35 | inline float &time() { return time_; } 36 | void setTime(float time); 37 | 38 | inline float initialValue() const { return initialValue_; } 39 | inline float &initialValue() { return initialValue_; } 40 | void setInitialValue(float initialValue); 41 | 42 | inline float start() const { return start_; } 43 | inline float &start() { return start_; } 44 | inline void setStart(float start) { start_ = start; } 45 | 46 | inline float end() const { return end_; } 47 | inline float &end() { return end_; } 48 | inline void setEnd(float end) { end_ = end; } 49 | 50 | inline float scale() const { return scale_; } 51 | inline float &scale() { return scale_; } 52 | void setScale(float scale) { scale_ = scale; } 53 | 54 | inline float shift() const { return shift_; } 55 | inline float &shift() { return shift_; } 56 | void setShift(float shift) { shift_ = shift; } 57 | 58 | void reset(); 59 | float value(); 60 | void next(float deltaTime); 61 | 62 | private: 63 | Type type_; 64 | LoopComponent loop_; 65 | bool withInitialValue_; 66 | 67 | float time_; 68 | float initialValue_; 69 | float start_; 70 | float end_; 71 | 72 | float scale_; 73 | float shift_; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/Script.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "singletons.h" 4 | #include "Script.h" 5 | #include "ScriptManager.h" 6 | 7 | /////////////////////////////////////////////////////////// 8 | // CONSTRUCTORS and DESTRUCTOR 9 | /////////////////////////////////////////////////////////// 10 | 11 | Script::Script() 12 | : canRun_(false), name_(256), errorMessage_(256), 13 | luaState_(nc::LuaStateManager::ApiType::NONE, 14 | nc::LuaStateManager::StatisticsTracking::DISABLED, 15 | nc::LuaStateManager::StandardLibraries::LOADED) 16 | { 17 | } 18 | 19 | Script::Script(const char *filename) 20 | : Script() 21 | { 22 | load(filename); 23 | } 24 | 25 | /////////////////////////////////////////////////////////// 26 | // PUBLIC FUNCTIONS 27 | /////////////////////////////////////////////////////////// 28 | 29 | bool Script::load(const char *filename) 30 | { 31 | const bool hasLoaded = nc::fs::isReadableFile(filename); 32 | if (hasLoaded) 33 | { 34 | name_ = filename; 35 | run(filename, nc::fs::baseName(filename).data()); 36 | } 37 | 38 | return hasLoaded; 39 | } 40 | 41 | bool Script::reload() 42 | { 43 | nctl::String filename = name_; 44 | // Resolve relative path made to allow for relocatable project files 45 | if (nc::fs::isReadableFile(nc::fs::joinPath(theCfg.scriptsPath, name_.data()).data())) 46 | filename = nc::fs::joinPath(theCfg.scriptsPath, name_.data()); 47 | 48 | const bool hasLoaded = nc::fs::isReadableFile(filename.data()); 49 | if (hasLoaded) 50 | { 51 | luaState_.reopen(); 52 | run(filename.data(), name_.data()); 53 | } 54 | 55 | return hasLoaded; 56 | } 57 | 58 | /////////////////////////////////////////////////////////// 59 | // PRIVATE FUNCTIONS 60 | /////////////////////////////////////////////////////////// 61 | 62 | bool Script::run(const char *filename, const char *chunkName) 63 | { 64 | ScriptManager::exposeConstants(luaState_.state()); 65 | ScriptManager::exposeFunctions(luaState_.state()); 66 | canRun_ = luaState_.runFromFile(filename, chunkName, &errorMessage_); 67 | 68 | return canRun_; 69 | } 70 | -------------------------------------------------------------------------------- /src/GridAnimation.cpp: -------------------------------------------------------------------------------- 1 | #include "GridAnimation.h" 2 | #include "Sprite.h" 3 | #include "GridFunction.h" 4 | #include "GridFunctionLibrary.h" 5 | #include "AnimationGroup.h" 6 | 7 | /////////////////////////////////////////////////////////// 8 | // CONSTRUCTORS and DESTRUCTOR 9 | /////////////////////////////////////////////////////////// 10 | 11 | GridAnimation::GridAnimation() 12 | : GridAnimation(nullptr) 13 | { 14 | } 15 | 16 | GridAnimation::GridAnimation(Sprite *sprite) 17 | : CurveAnimation(EasingCurve::Type::LINEAR, Loop::Mode::DISABLED), 18 | sprite_(nullptr), gridFunction_(nullptr), params_(4) 19 | { 20 | setSprite(sprite); 21 | } 22 | 23 | /////////////////////////////////////////////////////////// 24 | // PUBLIC FUNCTIONS 25 | /////////////////////////////////////////////////////////// 26 | 27 | nctl::UniquePtr GridAnimation::clone() const 28 | { 29 | nctl::UniquePtr anim = nctl::makeUnique(sprite_); 30 | CurveAnimation::cloneTo(*anim); 31 | 32 | anim->setSprite(sprite_); 33 | anim->gridFunction_ = gridFunction_; 34 | anim->params_ = params_; 35 | 36 | return nctl::move(anim); 37 | } 38 | 39 | void GridAnimation::perform() 40 | { 41 | if (sprite_ && sprite_->visible && gridFunction_) 42 | gridFunction_->execute(*this); 43 | } 44 | 45 | void GridAnimation::setSprite(Sprite *sprite) 46 | { 47 | if (sprite_ != sprite) 48 | { 49 | if (sprite_) 50 | sprite_->decrementGridAnimCounter(); 51 | if (sprite) 52 | sprite->incrementGridAnimCounter(); 53 | 54 | sprite_ = sprite; 55 | } 56 | } 57 | 58 | void GridAnimation::setFunction(const GridFunction *function) 59 | { 60 | if (function) 61 | { 62 | if (function->numParameters() != params_.size()) 63 | params_.setSize(function->numParameters()); 64 | 65 | for (unsigned int i = 0; i < function->numParameters(); i++) 66 | { 67 | const GridFunction::ParameterInfo ¶mInfo = function->parameterInfo(i); 68 | params_[i].value0 = paramInfo.initialValue.value0; 69 | params_[i].value1 = paramInfo.initialValue.value1; 70 | } 71 | } 72 | else 73 | params_.clear(); 74 | 75 | gridFunction_ = function; 76 | } 77 | -------------------------------------------------------------------------------- /include/IAnimation.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_IANIMATION 2 | #define CLASS_IANIMATION 3 | 4 | #include 5 | 6 | class AnimationGroup; 7 | 8 | /// The animation interface class 9 | class IAnimation 10 | { 11 | public: 12 | enum class Type 13 | { 14 | PROPERTY, 15 | GRID, 16 | SCRIPT, 17 | SEQUENTIAL_GROUP, 18 | PARALLEL_GROUP 19 | }; 20 | 21 | enum class State 22 | { 23 | STOPPED, 24 | PAUSED, 25 | PLAYING 26 | }; 27 | 28 | IAnimation(); 29 | virtual ~IAnimation() {} 30 | 31 | virtual nctl::UniquePtr clone() const = 0; 32 | 33 | static const unsigned int MaxNameLength = 64; 34 | nctl::String name; 35 | bool enabled = true; 36 | 37 | virtual Type type() const = 0; 38 | inline State state() const { return state_; } 39 | inline bool isGroup() const { return type() == Type::SEQUENTIAL_GROUP || type() == Type::PARALLEL_GROUP; } 40 | inline bool isStopped() const { return state_ == State::STOPPED; } 41 | inline bool isPaused() const { return state_ == State::PAUSED; } 42 | inline bool isPlaying() const { return state_ == State::PLAYING; } 43 | 44 | virtual void stop(); 45 | inline virtual void pause() { state_ = State::PAUSED; } 46 | inline virtual void play() { state_ = State::PLAYING; } 47 | 48 | virtual void update(float deltaTime) = 0; 49 | 50 | inline AnimationGroup *parent() { return parent_; } 51 | inline const AnimationGroup *parent() const { return parent_; } 52 | inline void setParent(AnimationGroup *parent) { parent_ = parent; } 53 | 54 | inline float delay() const { return delay_; } 55 | inline void setDelay(float delay) { delay_ = delay; } 56 | inline float currentDelay() const { return currentDelay_; } 57 | 58 | inline void resetDelay() { currentDelay_ = 0.0f; } 59 | bool shouldWaitDelay(float deltaTime); 60 | 61 | int indexInParent() const; 62 | 63 | protected: 64 | State state_; 65 | AnimationGroup *parent_; 66 | 67 | /// Delay amount in seconds before an animation begins to update 68 | float delay_; 69 | /// The amount of time in seconds waited until now for the delay 70 | float currentDelay_; 71 | 72 | void cloneTo(IAnimation &other) const; 73 | 74 | bool insideSequential() const; 75 | }; 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /include/SpriteEntry.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SPRITEENTRY 2 | #define CLASS_SPRITEENTRY 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace nc = ncine; 9 | 10 | class Sprite; 11 | class SpriteGroup; 12 | 13 | /// The class that contains information about an entry in the Sprites window 14 | class SpriteEntry 15 | { 16 | public: 17 | enum class Type 18 | { 19 | GROUP, 20 | SPRITE 21 | }; 22 | 23 | SpriteEntry(Type type); 24 | SpriteEntry(Type type, nc::Colorf entryColor); 25 | 26 | inline Type type() const { return type_; } 27 | 28 | inline bool isGroup() const { return type_ == Type::GROUP; } 29 | inline bool isSprite() const { return type_ == Type::SPRITE; } 30 | 31 | const SpriteGroup *toGroup() const; 32 | SpriteGroup *toGroup(); 33 | const Sprite *toSprite() const; 34 | Sprite *toSprite(); 35 | 36 | unsigned int spriteId() const; 37 | void setSpriteId(unsigned int spriteId); 38 | 39 | inline const SpriteGroup *parentGroup() const { return parentGroup_; } 40 | inline SpriteGroup *parentGroup() { return parentGroup_; } 41 | inline void setParentGroup(SpriteGroup *parentGroup) { parentGroup_ = parentGroup; } 42 | 43 | inline const nc::Colorf &entryColor() const { return entyrColor_; } 44 | inline nc::Colorf &entryColor() { return entyrColor_; } 45 | 46 | int indexInParent() const; 47 | 48 | protected: 49 | const Type type_; 50 | /// Not used if the entry is a group 51 | unsigned int spriteId_; 52 | SpriteGroup *parentGroup_ = nullptr; 53 | nc::Colorf entyrColor_; 54 | }; 55 | 56 | class SpriteGroup : public SpriteEntry 57 | { 58 | public: 59 | SpriteGroup(); 60 | SpriteGroup(const char *name); 61 | SpriteGroup(nc::Colorf entryColor, const char *name); 62 | 63 | nctl::UniquePtr clone() const; 64 | 65 | inline const nctl::String &name() const { return name_; } 66 | inline nctl::String &name() { return name_; } 67 | 68 | inline nctl::Array> &children() { return children_; } 69 | inline const nctl::Array> &children() const { return children_; } 70 | 71 | private: 72 | nctl::String name_; 73 | nctl::Array> children_; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/Serializers.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_SERIALIZERS 2 | #define CLASS_SERIALIZERS 3 | 4 | #include 5 | 6 | class LuaSerializer; 7 | class Canvas; 8 | class Texture; 9 | class SpriteEntry; 10 | class SpriteGroup; 11 | class Sprite; 12 | class Script; 13 | 14 | class LoopComponent; 15 | class IAnimation; 16 | class AnimationGroup; 17 | class PropertyAnimation; 18 | class GridAnimation; 19 | class ScriptAnimation; 20 | 21 | class SaveAnim; 22 | 23 | class Configuration; 24 | 25 | namespace Serializers { 26 | 27 | void serialize(LuaSerializer &ls, const char *name, const Canvas &canvas); 28 | void serialize(LuaSerializer &ls, const Texture &texture); 29 | void serialize(LuaSerializer &ls, const SpriteEntry *spriteEntry); 30 | void serialize(LuaSerializer &ls, const SpriteGroup &spriteGroup); 31 | void serialize(LuaSerializer &ls, const Sprite &sprite); 32 | void serialize(LuaSerializer &ls, const Script &script); 33 | 34 | void serialize(LuaSerializer &ls, const IAnimation *anim); 35 | void serialize(LuaSerializer &ls, const AnimationGroup &anim); 36 | void serialize(LuaSerializer &ls, const PropertyAnimation &anim); 37 | void serialize(LuaSerializer &ls, const GridAnimation &anim); 38 | void serialize(LuaSerializer &ls, const ScriptAnimation &anim); 39 | 40 | void serialize(LuaSerializer &ls, const char *name, const SaveAnim &saveAnim); 41 | 42 | void serialize(LuaSerializer &ls, const Configuration &cf); 43 | 44 | } 45 | 46 | namespace Deserializers { 47 | 48 | bool deserialize(LuaSerializer &ls, const char *name, Canvas &canvas); 49 | void deserialize(LuaSerializer &ls, nctl::UniquePtr &texture); 50 | void deserialize(LuaSerializer &ls, nctl::UniquePtr &spriteEntry); 51 | void deserialize(LuaSerializer &ls, nctl::UniquePtr &spriteGroup); 52 | void deserialize(LuaSerializer &ls, nctl::UniquePtr &sprite); 53 | void deserialize(LuaSerializer &ls, nctl::UniquePtr