diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d575ce..25165ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(RPGEDIT CXX) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_image) -pkg_check_modules(LUA REQUIRED lua>=5.2) +find_package(Lua 5.3 EXACT REQUIRED) add_subdirectory(src) diff --git a/resources/script/interact.lua b/resources/script/interact.lua new file mode 100644 index 0000000..98bb34f --- /dev/null +++ b/resources/script/interact.lua @@ -0,0 +1,3 @@ +function interact(entity, time) + print('Interact! ' .. time) +end diff --git a/resources/script/test.lua b/resources/script/test.lua index f78cf13..1dc1fc4 100644 --- a/resources/script/test.lua +++ b/resources/script/test.lua @@ -1,14 +1,20 @@ -function print_table(foo, bar) +local function print_table(foo, bar) for k, v in pairs(foo) do print(bar .. k, v) - if type(v) == 'table' and bar .. k ~= '_G' then - print_table(v, bar .. k .. '.') - end + --if type(v) == 'table' and bar .. k ~= '_G' then + -- print_table(v, bar .. k .. '.') + --end end end -print_table(_G, '') +--print(getmetatable(_G)) +--setmetatable(_G, {}) +--print_table(_G, '') -print(getmetatable('').__index) -print(string) +print(bar) +print(getmetatable(bar)) + +--print(getmetatable('').bar) +--getmetatable('').bar = 'bar' +--print(getmetatable('').bar) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a38474..46eb1a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,14 +1,16 @@ -include_directories(${SDL2_INCLUDE_DIRS} ${LUA_INCLUDE_DIRS}) -link_directories(${SDL2_LIBRARY_DIRS} ${LUA_LIBRARY_DIRS}) +include_directories(${SDL2_INCLUDE_DIRS} ${LUA_INCLUDE_DIR}) +link_directories(${SDL2_LIBRARY_DIRS}) add_executable(rpgedit rpgedit.cpp control/MapContext.cpp control/RPGEdit.cpp + control/ScriptContext.cpp model/Map.cpp + model/Scriptable.cpp view/MapView.cpp view/SpriteCache.cpp ) -set_target_properties(rpgedit PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall ${SDL2_CFLAGS_OTHER} ${LUA_CFLAGS_OTHER}") -set_target_properties(rpgedit PROPERTIES LINK_FLAGS "${SDL2_LDFLAGS_OTHER} ${LUA_LDFLAGS_OTHER}") +set_target_properties(rpgedit PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall ${SDL2_CFLAGS_OTHER}") +set_target_properties(rpgedit PROPERTIES LINK_FLAGS "${SDL2_LDFLAGS_OTHER}") target_link_libraries(rpgedit ${SDL2_LIBRARIES} ${LUA_LIBRARIES}) diff --git a/src/control/EventBus.hpp b/src/control/EventBus.hpp index 7284883..e94c494 100644 --- a/src/control/EventBus.hpp +++ b/src/control/EventBus.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/control/InputHandler.hpp b/src/control/InputHandler.hpp index 7eb98a9..ecb7876 100644 --- a/src/control/InputHandler.hpp +++ b/src/control/InputHandler.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/control/MapContext.cpp b/src/control/MapContext.cpp index 6ba3b6b..246ee96 100644 --- a/src/control/MapContext.cpp +++ b/src/control/MapContext.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,10 +31,13 @@ namespace RPGEdit { namespace Control { -MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr &window, const Model::Map &map0) - : eventBus(eventBus0), inputHandler(inputHandler0), map(map0) { +MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, ScriptContext *scriptContext0, const std::shared_ptr &window, const Model::Map &map0) + : eventBus(eventBus0), inputHandler(inputHandler0), scriptContext(scriptContext0), map(map0) { view = std::unique_ptr(new View::MapView(window, map.getTileset())); + Model::Entity *square = map.addEntity("square", Model::Position{10, 10}); + square->setScriptInteract("interact", "interact"); + playerEntity = map.addEntity("square", Model::Position{8, 8}); view->updateEntities(map.getEntities()); @@ -80,7 +83,11 @@ void MapContext::interact(uint64_t time) { if (!target) return; - target->interact(time); + const std::pair &interactScript = target->getScriptInteract(); + if (interactScript.first.empty()) + return; + + scriptContext->run(interactScript.first, interactScript.second, nullptr, time); } void MapContext::keyPressed(uint16_t key, uint64_t time) { diff --git a/src/control/MapContext.hpp b/src/control/MapContext.hpp index 18d4cfe..316f70b 100644 --- a/src/control/MapContext.hpp +++ b/src/control/MapContext.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ #include "EventBus.hpp" #include "InputHandler.hpp" +#include "ScriptContext.hpp" #include "../model/Map.hpp" #include "../view/MapView.hpp" @@ -43,6 +44,7 @@ class MapContext { private: EventBus *const eventBus; InputHandler *const inputHandler; + ScriptContext *const scriptContext; std::unique_ptr view; @@ -59,7 +61,7 @@ private: } public: - MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr &window, const Model::Map &map0); + MapContext(EventBus *eventBus0, InputHandler *inputHandler0, ScriptContext *scriptContext0, const std::shared_ptr &window, const Model::Map &map0); void render(uint64_t time) { view->render(&map, getViewPosition(time), time); diff --git a/src/control/RPGEdit.cpp b/src/control/RPGEdit.cpp index a1a699f..71f7dcf 100644 --- a/src/control/RPGEdit.cpp +++ b/src/control/RPGEdit.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -26,7 +26,6 @@ #include "RPGEdit.hpp" #include "MapContext.hpp" -#include "ScriptContext.hpp" #include "../view/MapView.hpp" @@ -106,7 +105,7 @@ void RPGEdit::run() { window = std::make_shared(); - ctx = std::make_shared(&eventBus, &inputHandler, window, *map); + ctx = std::make_shared(&eventBus, &inputHandler, &scriptContext, window, *map); eventThread = std::thread([this] { eventLoop(); }); diff --git a/src/control/RPGEdit.hpp b/src/control/RPGEdit.hpp index 6011ecd..e1f1731 100644 --- a/src/control/RPGEdit.hpp +++ b/src/control/RPGEdit.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,6 +46,8 @@ private: EventBus eventBus; InputHandler inputHandler; + ScriptContext scriptContext; + std::shared_ptr window; std::shared_ptr ctx; diff --git a/src/control/ScriptContext.cpp b/src/control/ScriptContext.cpp new file mode 100644 index 0000000..e92e275 --- /dev/null +++ b/src/control/ScriptContext.cpp @@ -0,0 +1,92 @@ +/* + Copyright (c) 2014-2015, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "ScriptContext.hpp" + + +namespace RPGEdit { + +namespace Control { + +void ScriptContext::setupEnv() { + const std::pair libs[] = { + {"_G", luaopen_base}, + {"math", luaopen_math}, + {"string", luaopen_string}, + {"table", luaopen_table}, + {"utf8", luaopen_utf8}, + }; + + for (auto &lib : libs) { + lua_pushcfunction(L, lib.second); + lua_pushstring(L, lib.first); + lua_call(L, 1, 1); + lua_setglobal(L, lib.first); + } + + for (const char *f : {"dofile", "loadfile", "require"}) { + lua_pushnil(L); + lua_setglobal(L, f); + } +} + +void ScriptContext::cleanupEnv() { + lua_pushglobaltable(L); + + lua_pushnil(L); + lua_setmetatable(L, -2); + + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + lua_pop(L, 1); + + lua_pushvalue(L, -1); + lua_pushnil(L); + + lua_rawset(L, -4); + } + + lua_pop(L, 1); +} + +void ScriptContext::load(const std::string &script) { + if (loadedScripts.count(script)) + return; + + std::string filename = "../resources/script/" + script + ".lua"; + + lua_rawgetp(L, LUA_REGISTRYINDEX, this); + lua_pushstring(L, script.c_str()); + luaL_loadfile(L, filename.c_str()); + lua_rawset(L, -3); + lua_pop(L, 1); + + loadedScripts.insert(script); +} + +} + +} diff --git a/src/control/ScriptContext.hpp b/src/control/ScriptContext.hpp index 23f0fab..191be92 100644 --- a/src/control/ScriptContext.hpp +++ b/src/control/ScriptContext.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -26,6 +26,8 @@ #pragma once +#include "../model/ScriptValue.hpp" + extern "C" { #include #include @@ -34,6 +36,8 @@ extern "C" { #include #include +#include +#include namespace RPGEdit { @@ -44,43 +48,44 @@ class ScriptContext { private: lua_State *L; - void setupEnv() { - const std::pair libs[] = { - {"_G", luaopen_base}, - {"bit32", luaopen_bit32}, - {"math", luaopen_math}, - {"string", luaopen_string}, - {"table", luaopen_table}, - }; + std::unordered_set loadedScripts; - for (auto &lib : libs) { - luaL_requiref(L, lib.first, lib.second, 1); - lua_pop(L, 1); - } + void setupEnv(); + void cleanupEnv(); - for (const char *f : {"dofile", "loadfile", "require"}) { - lua_pushnil(L); - lua_setglobal(L, f); - } + void load(const std::string &script); + + + void pushArg(std::nullptr_t __attribute__((unused)) v) { + lua_pushnil(L); } - void cleanupEnv() { - lua_pushglobaltable(L); + void pushArg(const std::string &v) { + lua_pushstring(L, v.c_str()); + } - lua_pushnil(L); - lua_setmetatable(L, -2); + template::value>::type> + void pushArg(T v) { + lua_pushnumber(L, v); + } - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - lua_pop(L, 1); + void pushArg(bool v) { + lua_pushboolean(L, v); + } - lua_pushvalue(L, -1); - lua_pushnil(L); + void pushArg(Model::ScriptValue &v) { + v.push(L); + } - lua_rawset(L, -4); - } - lua_pop(L, 1); + size_t pushArgs() { + return 0; + } + + template + size_t pushArgs(T v, Args ...args) { + pushArg(v); + return pushArgs(args...) + 1; } public: @@ -100,25 +105,26 @@ public: lua_close(L); } - void load(const std::string &name) { - std::string filename = "../resources/script/" + name + ".lua"; - - lua_rawgetp(L, LUA_REGISTRYINDEX, this); - lua_pushstring(L, name.c_str()); - luaL_loadfile(L, filename.c_str()); - lua_rawset(L, -3); - lua_pop(L, 1); + void setGlobal(const std::string &key, Model::ScriptValue *value) { + value->push(L); + lua_setglobal(L, key.c_str()); } - void run(const std::string &name) { + template + void run(const std::string &script, const std::string &name, Args ...args) { + load(script); + setupEnv(); lua_rawgetp(L, LUA_REGISTRYINDEX, this); - lua_getfield(L, -1, name.c_str()); + lua_getfield(L, -1, script.c_str()); lua_remove(L, -2); lua_call(L, 0, 0); + lua_getglobal(L, name.c_str()); + lua_call(L, pushArgs(args...), 0); + cleanupEnv(); } }; diff --git a/src/control/TimeProvider.hpp b/src/control/TimeProvider.hpp index 1880f7b..2278114 100644 --- a/src/control/TimeProvider.hpp +++ b/src/control/TimeProvider.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/model/CollisionType.hpp b/src/model/CollisionType.hpp index 50bb608..d44c2dc 100644 --- a/src/model/CollisionType.hpp +++ b/src/model/CollisionType.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/model/Direction.hpp b/src/model/Direction.hpp index e817170..a9c4776 100644 --- a/src/model/Direction.hpp +++ b/src/model/Direction.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/model/Entity.hpp b/src/model/Entity.hpp index 677eeb5..169b54d 100644 --- a/src/model/Entity.hpp +++ b/src/model/Entity.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ #include "Direction.hpp" -#include "Position.hpp" +#include "Scriptable.hpp" #include @@ -39,10 +39,12 @@ namespace RPGEdit { namespace Model { -class Entity { +class Entity : public Scriptable { private: std::string name; + std::pair scriptInteract; + Direction direction; public: @@ -62,8 +64,13 @@ public: direction = dir; } - void interact(uint64_t time) { - std::fprintf(stderr, "Tried to interact with `%s' entity at %llu\n", name.c_str(), (unsigned long long)time); + const std::pair & getScriptInteract() const { + return scriptInteract; + } + + void setScriptInteract(const std::string &script, const std::string &name) { + scriptInteract.first = script; + scriptInteract.second = name; } }; diff --git a/src/model/Map.cpp b/src/model/Map.cpp index 2df54b7..191297a 100644 --- a/src/model/Map.cpp +++ b/src/model/Map.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/model/Map.hpp b/src/model/Map.hpp index ed58fd6..3786d1d 100644 --- a/src/model/Map.hpp +++ b/src/model/Map.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ #include "CollisionType.hpp" #include "Entity.hpp" +#include "Position.hpp" namespace RPGEdit { diff --git a/src/model/Position.hpp b/src/model/Position.hpp index c8fc477..a2f5c6f 100644 --- a/src/model/Position.hpp +++ b/src/model/Position.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/model/ScriptValue.hpp b/src/model/ScriptValue.hpp new file mode 100644 index 0000000..7a2e0b4 --- /dev/null +++ b/src/model/ScriptValue.hpp @@ -0,0 +1,143 @@ +/* + Copyright (c) 2014-2015, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#pragma once + +extern "C" { +#include +#include +#include +} + +#include +#include +#include + +namespace RPGEdit { + +namespace Model { + +class ScriptValue { +public: + virtual void push(lua_State *L) = 0; + + virtual ~ScriptValue() {} +}; + + +class ScriptBoolean : public ScriptValue { +private: + bool value; + +public: + ScriptBoolean(bool value0) : value(value0) { + } + + ScriptBoolean & operator=(bool newValue) { + value = newValue; + return *this; + } + + operator bool() const { + return value; + } + + virtual void push(lua_State *L) { + lua_pushboolean(L, value); + } +}; + +class ScriptNumber : public ScriptValue { +private: + lua_Number value; + +public: + ScriptNumber(lua_Number value0) : value(value0) { + } + + ScriptNumber & operator=(lua_Number newValue) { + value = newValue; + return *this; + } + + operator lua_Number() const { + return value; + } + + virtual void push(lua_State *L) { + lua_pushnumber(L, value); + } +}; + +class ScriptString : public ScriptValue { +private: + std::string value; + +public: + ScriptString(std::string &value0) : value(value0) { + } + + ScriptString & operator=(std::string &newValue) { + value = newValue; + return *this; + } + + operator std::string &() { + return value; + } + + virtual void push(lua_State *L) { + lua_pushstring(L, value.c_str()); + } +}; + +class ScriptTable : public ScriptValue { +public: + typedef std::unordered_map, std::shared_ptr> MapType; + +private: + MapType value; + +public: + std::shared_ptr & operator[](const std::shared_ptr &key) { + return value[key]; + } + + virtual void push(lua_State *L) { + lua_createtable(L, 0, value.size()); + + for (const auto &entry : value) { + entry.first->push(L); + entry.second->push(L); + + lua_settable(L, -3); + } + } +}; + +} + +} diff --git a/src/model/Scriptable.cpp b/src/model/Scriptable.cpp new file mode 100644 index 0000000..f2deee2 --- /dev/null +++ b/src/model/Scriptable.cpp @@ -0,0 +1,58 @@ +/* + Copyright (c) 2014-2015, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "Scriptable.hpp" + + +namespace RPGEdit { + +namespace Model { + +int Scriptable::gc(lua_State *L) { + std::shared_ptr *value = static_cast *>(lua_touserdata(L, -1)); + + value->~shared_ptr(); + + return 0; +} + +void Scriptable::setupMetatable(lua_State *L) { + if (luaL_newmetatable(L, "RPGEdit::Model::Scriptable")) { + lua_pushstring(L, "__metatable"); + lua_pushstring(L, "protected"); + lua_rawset(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, &gc); + lua_rawset(L, -3); + } + + lua_setmetatable(L, -2); +} + +} + +} diff --git a/src/model/Scriptable.hpp b/src/model/Scriptable.hpp new file mode 100644 index 0000000..473a50a --- /dev/null +++ b/src/model/Scriptable.hpp @@ -0,0 +1,57 @@ +/* + Copyright (c) 2014-2015, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#pragma once + + +#include "ScriptValue.hpp" + +#include + + +namespace RPGEdit { + +namespace Model { + +class Scriptable : public ScriptValue, public std::enable_shared_from_this { +private: + static int gc(lua_State *L); + + void setupMetatable(lua_State *L); + +public: + virtual void push(lua_State *L) { + + void *ptr = lua_newuserdata(L, sizeof(std::shared_ptr)); + setupMetatable(L); + + new (ptr) std::shared_ptr(shared_from_this()); + } +}; + +} + +} diff --git a/src/rpgedit.cpp b/src/rpgedit.cpp index 6ef5dd3..54c34fc 100644 --- a/src/rpgedit.cpp +++ b/src/rpgedit.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,15 +27,27 @@ #include "control/RPGEdit.hpp" #include +#include #include +#include + extern "C" int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) { - SDL_Init(SDL_INIT_VIDEO); + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + std::cerr << "Unable to initialize SDL" << std::endl; + return 1; + } + + if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) { + std::cerr << "Unable to initialize PNG loader" << std::endl; + return 1; + } RPGEdit::Control::RPGEdit().run(); + IMG_Quit(); SDL_Quit(); return 0; diff --git a/src/view/MapView.cpp b/src/view/MapView.cpp index 20d5af5..b8bc25b 100644 --- a/src/view/MapView.cpp +++ b/src/view/MapView.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/view/MapView.hpp b/src/view/MapView.hpp index c5867cc..fdd30aa 100644 --- a/src/view/MapView.hpp +++ b/src/view/MapView.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/view/SpriteCache.cpp b/src/view/SpriteCache.cpp index bd67346..a7018f7 100644 --- a/src/view/SpriteCache.cpp +++ b/src/view/SpriteCache.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without @@ -70,6 +70,8 @@ SpriteCache::sprite_value SpriteCache::load(const std::string &id, unsigned rota uint8_t *src = reinterpret_cast(base->pixels); uint8_t *dst = reinterpret_cast(surface->pixels); + int pitch = base->pitch; + int pitch2 = surface->pitch; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { @@ -89,7 +91,7 @@ SpriteCache::sprite_value SpriteCache::load(const std::string &id, unsigned rota y2 = x; } - std::memcpy(dst + d * (y2*w2 + x2), src + d * (y*w + x), d); + std::memcpy(dst + y2*pitch2 + d*x2, src + y*pitch + d*x, d); } } diff --git a/src/view/SpriteCache.hpp b/src/view/SpriteCache.hpp index ae01887..151fe19 100644 --- a/src/view/SpriteCache.hpp +++ b/src/view/SpriteCache.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/view/Window.hpp b/src/view/Window.hpp index 8c4c7a7..9bfcbb4 100644 --- a/src/view/Window.hpp +++ b/src/view/Window.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2014, Matthias Schiffer + Copyright (c) 2014-2015, Matthias Schiffer All rights reserved. Redistribution and use in source and binary forms, with or without