From b77797ddb37c4825844ff7242b8782b9570fa753 Mon Sep 17 00:00:00 2001 From: Jacob Jensen Date: Sat, 5 Jul 2014 16:43:53 +0200 Subject: [PATCH] Added Microbe saving/loading in editor. Uses existing serialization to read/write foo.microbe files in creations/microbe. Uses new version file to record save versions, in case of backwards-compatibility issues. --- .gitignore | 4 + CMakeLists.txt | 7 ++ scripts/microbe_editor/microbe_editor.lua | 13 ++ scripts/microbe_editor/microbe_editor_hud.lua | 72 ++++++++++- scripts/microbe_stage/microbe_stage_hud.lua | 2 + src/engine/engine.cpp | 116 +++++++++++++++++- src/engine/engine.h | 92 ++++++++++++++ src/engine/entity_manager.cpp | 34 ++++- src/engine/entity_manager.h | 32 +++++ src/engine/game_state.cpp | 1 + src/engine/game_state.h | 1 + src/gui/CEGUIWindow.cpp | 47 ++++++- src/gui/CEGUIWindow.h | 68 +++++++++- src/gui/script_bindings.cpp | 50 ++++++++ thriveversion.ver | 1 + 15 files changed, 527 insertions(+), 13 deletions(-) create mode 100644 thriveversion.ver diff --git a/.gitignore b/.gitignore index 287d4cc0124..6765b8119cf 100644 --- a/.gitignore +++ b/.gitignore @@ -85,5 +85,9 @@ nbproject/ # Vim swap files *.swp + +# Version file + +!thriveversion.ver # Temporary/backup files *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b143d9a629..0d8441dc3e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,6 +317,13 @@ install(EXPORT lua DESTINATION bin ) +# Version file + +install(FILES + ${CMAKE_SOURCE_DIR}/thriveversion.ver + DESTINATION bin +) + # OGRE config and media install(FILES diff --git a/scripts/microbe_editor/microbe_editor.lua b/scripts/microbe_editor/microbe_editor.lua index a6c93609e03..46ed2659310 100644 --- a/scripts/microbe_editor/microbe_editor.lua +++ b/scripts/microbe_editor/microbe_editor.lua @@ -138,6 +138,19 @@ function MicrobeEditor:addNucleus() self.currentMicrobe:addOrganelle(0, 0, nucleusOrganelle) end +function MicrobeEditor:loadMicrobe(entityId) + self.organelleCount = 0 + if self.currentMicrobe ~= nil then + self.currentMicrobe.entity:destroy() + end + self.currentMicrobe = Microbe(Entity(entityId)) + self.currentMicrobe.entity:stealName("working_microbe") + self.currentMicrobe.sceneNode.transform.orientation = Quaternion(Radian(Degree(180)), Vector3(0, 0, 1))-- Orientation + self.currentMicrobe.sceneNode.transform:touch() + self.currentMicrobe.collisionHandler:addCollisionGroup("powerupable") + Engine:playerData():setActiveCreature(entityId) +end + function MicrobeEditor:createNewMicrobe() self.organelleCount = 0 if self.currentMicrobe ~= nil then diff --git a/scripts/microbe_editor/microbe_editor_hud.lua b/scripts/microbe_editor/microbe_editor_hud.lua index 384e9ad1472..85a6851772f 100644 --- a/scripts/microbe_editor/microbe_editor_hud.lua +++ b/scripts/microbe_editor/microbe_editor_hud.lua @@ -7,6 +7,9 @@ function MicrobeEditorHudSystem:__init() self.initialized = false self.editor = MicrobeEditor(self) self.hoverHex = nil + self.saveLoadPanel = nil + self.creationsListbox = nil + self.creationFileMap = {} -- Map from player creation name to filepath self.activeButton = nil -- stores button, not name end @@ -43,16 +46,23 @@ function MicrobeEditorHudSystem:init(gameState) --aminoSynthesizerButton:getChild("AminoSynthesizer"):registerEventHandler("Clicked", aminoSynthesizerClicked) removeButton:getChild("Remove"):registerEventHandler("Clicked", removeClicked) - + self.saveLoadPanel = root:getChild("SaveLoadPanel") + self.creationsListbox = self.saveLoadPanel:getChild("SavedCreations") + root:getChild("BottomSection"):getChild("MicrobeStageButton"):registerEventHandler("Clicked", playClicked) root:getChild("BottomSection"):getChild("MenuButton"):registerEventHandler("Clicked", menuButtonClicked) - root:getChild("MenuPanel"):getChild("MainMenuButton"):registerEventHandler("Clicked", menuMainMenuClicked) root:getChild("MenuPanel"):getChild("PlayButton"):registerEventHandler("Clicked", menuPlayClicked) root:getChild("MenuPanel"):getChild("ReturnButton"):registerEventHandler("Clicked", returnButtonClicked) root:getChild("MenuPanel"):getChild("QuitButton"):registerEventHandler("Clicked", quitButtonClicked) + root:getChild("BottomSection"):getChild("SaveButton"):registerEventHandler("Clicked", rootSaveCreationClicked) + root:getChild("BottomSection"):getChild("LoadButton"):registerEventHandler("Clicked", rootLoadCreationClicked) + root:getChild("SaveLoadPanel"):getChild("ReturnButton"):registerEventHandler("Clicked", returnButtonClicked) + root:getChild("SaveLoadPanel"):getChild("SaveButton"):registerEventHandler("Clicked", saveCreationClicked) + root:getChild("SaveLoadPanel"):getChild("LoadButton"):registerEventHandler("Clicked", loadCreationClicked) end + function MicrobeEditorHudSystem:activate() global_activeMicrobeEditorHudSystem = self -- Global reference for event handlers self.editor:activate() @@ -62,8 +72,7 @@ function MicrobeEditorHudSystem:activate() else button:enable() end - end - + end end function MicrobeEditorHudSystem:setActiveAction(actionName) @@ -77,7 +86,7 @@ end function MicrobeEditorHudSystem:update(milliseconds) self.editor:update(milliseconds) - -- Render the hex under the cursor + -- Render the hex under the cursor local x, y = axialToCartesian(self.editor:getMouseHex()) local translation = Vector3(-x, -y, 0) local sceneNode = self.hoverHex:getComponent(OgreSceneNodeComponent.TYPE_ID) @@ -195,6 +204,59 @@ function removeClicked() global_activeMicrobeEditorHudSystem:setActiveAction("remove") end +function rootSaveCreationClicked() + panel = global_activeMicrobeEditorHudSystem.saveLoadPanel + panel:getChild("SaveButton"):show() + panel:getChild("NameTextbox"):show() + panel:getChild("CreationNameDialogLabel"):show() + panel:getChild("LoadButton"):hide() + panel:getChild("SavedCreations"):hide() + panel:show() +end + +function rootLoadCreationClicked() + panel = global_activeMicrobeEditorHudSystem.saveLoadPanel + panel:getChild("SaveButton"):hide() + panel:getChild("NameTextbox"):hide() + panel:getChild("CreationNameDialogLabel"):hide() + panel:getChild("LoadButton"):show() + panel:getChild("SavedCreations"):show() + panel:show() + global_activeMicrobeEditorHudSystem.creationsListbox:itemListboxResetList() + global_activeMicrobeEditorHudSystem.creationFileMap = {} + i = 0 + pathsString = Engine:getCreationFileList("microbe") + -- using pattern matching for splitting on spaces + for path in string.gmatch(pathsString, "%S+") do + item = CEGUIWindow("Thrive/ListboxItem", "creationItems"..i) + pathSep = package.config:sub(1,1) -- / for unix, \ for windows + text = string.sub(path, string.len(path) - string.find(path:reverse(), pathSep) + 2) + item:setText(text) + global_activeMicrobeEditorHudSystem.creationsListbox:itemListboxAddItem(item) + global_activeMicrobeEditorHudSystem.creationFileMap[text] = path + i = i + 1 + end + global_activeMicrobeEditorHudSystem.creationsListbox:itemListboxHandleUpdatedItemData() +end + +function saveCreationClicked() + name = panel:getChild("NameTextbox"):getText() + -- Todo: Additional input sanitation + if string.len(name) > 0 then + Engine:saveCreation(global_activeMicrobeEditorHudSystem.editor.currentMicrobe.entity.id, name, "microbe") + panel:hide() + end +end + +function loadCreationClicked() + item = global_activeMicrobeEditorHudSystem.creationsListbox:itemListboxGetLastSelectedItem() + if not item:isNull() then + entity = Engine:loadCreation(global_activeMicrobeEditorHudSystem.creationFileMap[item:getText()]) + global_activeMicrobeEditorHudSystem.editor:loadMicrobe(entity) + panel:hide() + end +end + function playClicked() Engine:setCurrentGameState(GameState.MICROBE) end diff --git a/scripts/microbe_stage/microbe_stage_hud.lua b/scripts/microbe_stage/microbe_stage_hud.lua index c25c6a1919e..068d73bcb28 100644 --- a/scripts/microbe_stage/microbe_stage_hud.lua +++ b/scripts/microbe_stage/microbe_stage_hud.lua @@ -107,6 +107,8 @@ function returnButtonClicked() if Engine:currentGameState():name() == "microbe" then Engine:currentGameState():rootGUIWindow():getChild("HelpPanel"):hide() Engine:currentGameState():rootGUIWindow():getChild("MessagePanel"):hide() + elseif Engine:currentGameState():name() == "microbe_editor" then + Engine:currentGameState():rootGUIWindow():getChild("SaveLoadPanel"):hide() end end diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 9d17616cb55..175eeb451a8 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -33,11 +33,11 @@ #include "ogre/text_overlay.h" // Scripting +#include #include "scripting/luabind.h" #include "scripting/lua_state.h" #include "scripting/script_initializer.h" - // Microbe #include "microbe_stage/compound.h" @@ -241,6 +241,7 @@ struct Engine::Implementation : public Ogre::WindowEventListener { } savegame.set("gameStates", std::move(gameStates)); savegame.set("playerData", m_playerData.storage()); + savegame.set("thriveversion", m_thriveVersion); std::ofstream stream( m_serialization.saveFile, std::ofstream::trunc | std::ofstream::binary @@ -361,6 +362,18 @@ struct Engine::Implementation : public Ogre::WindowEventListener { ); } + void + loadVersionNumber() { + std::ifstream versionFile ("thriveversion.ver"); + if (versionFile.is_open()) { + std::getline(versionFile, m_thriveVersion); + } + else { + m_thriveVersion = "unknown"; + } + versionFile.close(); + } + void shutdownInputManager() { if (not m_input.inputManager) { @@ -439,6 +452,8 @@ struct Engine::Implementation : public Ogre::WindowEventListener { GameState* m_nextGameState = nullptr; + std::string m_thriveVersion; + struct Serialization { std::string loadFile; @@ -493,9 +508,13 @@ Engine::luaBindings() { .def("playerData", &Engine::playerData) .def("load", &Engine::load) .def("save", &Engine::save) + .def("saveCreation", static_cast(&Engine::saveCreation)) + .def("loadCreation", static_cast(&Engine::loadCreation)) + .def("getCreationFileList", &Engine::getCreationFileList) .def("quit", &Engine::quit) .def("timedSystemShutdown", &Engine::timedSystemShutdown) .def("isSystemTimedShutdown", &Engine::isSystemTimedShutdown) + .def("thriveVersion", &Engine::thriveVersion) .property("componentFactory", &Engine::componentFactory) .property("keyboard", &Engine::keyboard) .property("mouse", &Engine::mouse) @@ -577,6 +596,7 @@ Engine::init() { m_impl->setupInputManager(); m_impl->setupGUI(); m_impl->loadScripts("../scripts"); + m_impl->loadVersionNumber(); GameState* previousGameState = m_impl->m_currentGameState; for (const auto& pair : m_impl->m_gameStates) { const auto& gameState = pair.second; @@ -641,6 +661,94 @@ Engine::save( m_impl->m_serialization.saveFile = filename; } +void +Engine::saveCreation( + EntityId entityId, + std::string name, + std::string type +) const { + saveCreation(entityId, this->currentGameState()->entityManager(), name, type); +} + +void +Engine::saveCreation( + EntityId entityId, + const EntityManager& entityManager, + std::string name, + std::string type +) const { + namespace fs = boost::filesystem; + StorageContainer creation = entityManager.storeEntity(entityId); + creation.set("thriveversion", this->thriveVersion()); + std::ofstream stream( + (fs::path("creations") / fs::path(type) / fs::path(name + "." + type)).string(), + std::ofstream::trunc | std::ofstream::binary + ); + stream.exceptions(std::ofstream::failbit | std::ofstream::badbit); + if (stream) { + try { + stream << creation; + stream.flush(); + stream.close(); + } + catch (const std::ofstream::failure& e) { + std::cerr << "Error saving file: " << e.what() << std::endl; + throw; + } + } + else { + std::perror("Could not open file for saving"); + } +} + +EntityId +Engine::loadCreation( + std::string file +) { + return loadCreation(file, this->currentGameState()->entityManager()); +} + +EntityId +Engine::loadCreation( + std::string file, + EntityManager& entityManager +) { + std::ifstream stream( + file, + std::ifstream::binary + ); + stream.clear(); + stream.exceptions(std::ofstream::failbit | std::ofstream::badbit); + StorageContainer creation; + try { + stream >> creation; + } + catch(const std::ofstream::failure& e) { + std::cerr << "Error loading file: " << e.what() << std::endl; + throw; + } + EntityId entityId = entityManager.loadEntity(creation, m_impl->m_componentFactory); + return entityId; +} + +std::string +Engine::getCreationFileList( + std::string stage +) const { + namespace fs = boost::filesystem; + fs::path directory("./creations/" + stage); + fs::directory_iterator end_iter; + std::stringstream stringbuilder; + if ( fs::exists(directory) && fs::is_directory(directory)) { + for( fs::directory_iterator dir_iter(directory) ; dir_iter != end_iter ; ++dir_iter) { + if (fs::is_regular_file(dir_iter->status()) ) + { + stringbuilder << dir_iter->path().string() << " "; + } + } + } + return stringbuilder.str(); +} void Engine::setCurrentGameState( @@ -758,3 +866,9 @@ Engine::isSystemTimedShutdown( ) const { return m_impl->m_prevShutdownSystems->find(&system) != m_impl->m_prevShutdownSystems->end(); } + +const std::string& +Engine::thriveVersion() const { + return m_impl->m_thriveVersion; +} + diff --git a/src/engine/engine.h b/src/engine/engine.h index 9125af5b945..b1571e84619 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -5,6 +5,7 @@ #include #include +#include class btDiscreteDynamicsWorld; class lua_State; @@ -41,6 +42,7 @@ class CollisionSystem; class System; class RNG; + /** * @brief The heart of the game * @@ -63,12 +65,15 @@ class Engine { * - Engine::playerData() * - Engine::load() * - Engine::save() + * - Engine::saveCreation() + * - Engine::loadCreation() * - Engine::quit() * - Engine::timedSystemShutdown() * - Engine::isSystemTimedShutdown() * - Engine::componentFactory() (as property) * - Engine::keyboard() (as property) * - Engine::mouse() (as property) + * - Engine::thriveVersion() * * @return */ @@ -224,6 +229,79 @@ class Engine { std::string filename ); + /** + * @brief Saves a creation to file + * + * @param entityId + * The entity which represents the creation to save + * + * @param entityManager + * The entity manager that manages the entity + * + * @param name + * The name of the file + * + * @param type + * The type of creation. This also becomes the file extension. + */ + void + saveCreation( + EntityId entityId, + const EntityManager& entityManager, + std::string name, + std::string type + ) const; + + /** + * @brief Overload of above + */ + void + saveCreation( + EntityId entityId, + std::string name, + std::string type + ) const; + + /** + * @brief Loads a creation from file + * + * @param file + * The file to load from + * + * @param entityManager + * The entity manager that will manage the loaded entity + * + * @return entityId + */ + EntityId + loadCreation( + std::string file, + EntityManager& entityManager + ); + + /** + * @brief Overload of above + */ + EntityId + loadCreation( + std::string file + ); + + /** + * @brief Obtains a list of filenames for saved creations that match the provided type + * + * @param stage + * The game stage to filter creations on + * + * @return + * A string of concatenated paths separated by spaces. + * Optimally a vector of strings would be returned but luabind causes occasional crashes with that. + */ + std::string + getCreationFileList( + std::string stage + ) const; + /** * @brief Sets the current game state * @@ -328,8 +406,22 @@ class Engine { Ogre::RenderWindow* renderWindow() const; + + /** + * @brief Gets the current version of thrive as a string. + * + * The version is loaded from thriveversion.ver file. + * It returns as "unknown" if that file was not found + * + * @return versionString + */ + const std::string& + thriveVersion() const; + private: + + struct Implementation; std::unique_ptr m_impl; diff --git a/src/engine/entity_manager.cpp b/src/engine/entity_manager.cpp index f5f8a54883b..891056f47ed 100644 --- a/src/engine/entity_manager.cpp +++ b/src/engine/entity_manager.cpp @@ -288,6 +288,39 @@ EntityManager::transferEntity( } } +StorageContainer +EntityManager::storeEntity( + EntityId entityId +) const { + StorageContainer entityStorage; + StorageList componentList; + + for (const auto& pair : m_impl->m_collections) { + Component* component = pair.second->get(entityId); + if (component != nullptr){ + StorageContainer componentStorage = component->storage(); + componentStorage.set("typename", component->typeName()); + componentList.append(componentStorage); + } + } + entityStorage.set("components", std::move(componentList)); + return entityStorage; +} + +EntityId +EntityManager::loadEntity( + StorageContainer storage, + const ComponentFactory& componentFactory +) { + EntityId entityId = this->generateNewId(); + StorageList componentList = storage.get("components"); + for (const StorageContainer& entry : componentList) { + auto component = componentFactory.load(entry.get("typename"), entry); + this->addComponent(entityId, std::move(component)); + } + return entityId; +} + void EntityManager::restore( const StorageContainer& storage, @@ -359,7 +392,6 @@ EntityManager::setVolatile( } } - StorageContainer EntityManager::storage( const ComponentFactory& factory diff --git a/src/engine/entity_manager.h b/src/engine/entity_manager.h index 7b30e57cf27..f73457cf55d 100644 --- a/src/engine/entity_manager.h +++ b/src/engine/entity_manager.h @@ -288,6 +288,38 @@ class EntityManager { GameState* gameState ); + /** + * @brief Stores a single entity + * + * @param entityId + * The entity to store + * + * @return + * A container holding the entity. + */ + StorageContainer + storeEntity( + EntityId entityId + ) const; + + /** + * @brief Loads an entity into this entity manager + * + * @param storage + * The storage to load the entity from + * + * @param componentFactory + * Factory used for loading entity components + * + * @return + * The new entity id in the new gamestate + */ + EntityId + loadEntity( + StorageContainer storage, + const ComponentFactory& componentFactory + ); + /** * @brief Removes all components queued for removal */ diff --git a/src/engine/game_state.cpp b/src/engine/game_state.cpp index 5ed2d2b4a1d..f1af04e0abf 100644 --- a/src/engine/game_state.cpp +++ b/src/engine/game_state.cpp @@ -98,6 +98,7 @@ GameState::luaBindings() { return class_("GameState") .def("name", &GameState::name) .def("rootGUIWindow", &GameState::rootGUIWindow) + .def("entityManager", static_cast(&GameState::entityManager)) ; } diff --git a/src/engine/game_state.h b/src/engine/game_state.h index e64b387f57e..36ccf6c85cf 100644 --- a/src/engine/game_state.h +++ b/src/engine/game_state.h @@ -53,6 +53,7 @@ class GameState { * Exposes: * - GameState::name() * - GameState::rootGUIWindow() + * - GameState::entityManager() // NOTE: Entitymanager class may not be exposed to luabind * * @return */ diff --git a/src/gui/CEGUIWindow.cpp b/src/gui/CEGUIWindow.cpp index 95dc224aa1d..b4927c5102b 100644 --- a/src/gui/CEGUIWindow.cpp +++ b/src/gui/CEGUIWindow.cpp @@ -26,6 +26,13 @@ CEGUIWindow::CEGUIWindow( m_window = CEGUI::WindowManager::getSingleton().loadLayoutFromFile(layoutName + ".layout"); } +CEGUIWindow::CEGUIWindow( + std::string type, + std::string name +){ + m_window = CEGUI::WindowManager::getSingleton().createWindow(type, name); +} + CEGUIWindow::~CEGUIWindow() { } @@ -39,6 +46,8 @@ CEGUIWindow::luaBindings() { // def("getRootWindow", &CEGUIWindow::getRootWindow) //Better to use gameState::rootGUIWindow //] .def(constructor()) + .def(constructor()) + .def("isNull", &CEGUIWindow::isNull) .def("getText", &CEGUIWindow::getText) .def("setText", &CEGUIWindow::setText) .def("appendText", &CEGUIWindow::appendText) @@ -62,10 +71,18 @@ CEGUIWindow::luaBindings() { .def("listboxAddItem", &CEGUIWindow::listboxAddItem) .def("listboxResetList", &CEGUIWindow::listboxResetList) .def("listboxHandleUpdatedItemData", &CEGUIWindow::listboxHandleUpdatedItemData) + .def("itemListboxAddItem", &CEGUIWindow::itemListboxAddItem) + .def("itemListboxResetList", &CEGUIWindow::itemListboxResetList) + .def("itemListboxHandleUpdatedItemData", &CEGUIWindow::itemListboxHandleUpdatedItemData) + .def("itemListboxGetLastSelectedItem", &CEGUIWindow::itemListboxGetLastSelectedItem) .def("progressbarSetProgress", &CEGUIWindow::progressbarSetProgress) ; } +bool +CEGUIWindow::isNull() const { + return m_window == nullptr; +} CEGUIWindow CEGUIWindow::createChildWindow( @@ -120,6 +137,8 @@ CEGUIWindow::listboxAddItem( dynamic_cast(m_window)->addItem(listboxItem); } + + void CEGUIWindow::listboxResetList(){ dynamic_cast(m_window)->resetList(); @@ -130,6 +149,30 @@ CEGUIWindow::listboxHandleUpdatedItemData(){ dynamic_cast(m_window)->handleUpdatedItemData(); } +void +CEGUIWindow::itemListboxAddItem( + CEGUIWindow* item +) { + dynamic_cast(m_window)->addItem(dynamic_cast(item->m_window)); +} + +void +CEGUIWindow::itemListboxResetList(){ + dynamic_cast(m_window)->resetList(); +} + +void +CEGUIWindow::itemListboxHandleUpdatedItemData(){ + dynamic_cast(m_window)->handleUpdatedItemData(); +} + +CEGUIWindow* +CEGUIWindow::itemListboxGetLastSelectedItem(){ + return new CEGUIWindow(dynamic_cast(m_window)-> getLastSelectedItem()); +} + + + void CEGUIWindow::progressbarSetProgress(float progress){ dynamic_cast(m_window)->setProgress(progress); @@ -165,9 +208,9 @@ CEGUIWindow::RegisterEventHandler( const luabind::object& callback ) const { // Lambda must return something to avoid an template error. - auto callbackLambda = [callback](const CEGUI::EventArgs&) -> int + auto callbackLambda = [callback](const CEGUI::EventArgs& args) -> int { - luabind::call_function(callback); + luabind::call_function(callback, CEGUIWindow(static_cast(args).window) ); return 0; }; m_window->subscribeEvent(eventName, callbackLambda); diff --git a/src/gui/CEGUIWindow.h b/src/gui/CEGUIWindow.h index 26bc4636346..bfa849d9921 100644 --- a/src/gui/CEGUIWindow.h +++ b/src/gui/CEGUIWindow.h @@ -16,14 +16,31 @@ class CEGUIWindow { public: /** - * Constructor + * @brief Constructor + * + * @param layoutName + * The name of the layout file to load the window from **/ CEGUIWindow( std::string layoutName ); /** - * Destructor + * @brief Constructor + * + * @param type + * The type of CEGUI window (from .scheme) to create internally + * + * @param name + * name of the window + **/ + CEGUIWindow( + std::string type, + std::string name + ); + + /** + * @brief Destructor **/ virtual ~CEGUIWindow(); @@ -36,6 +53,7 @@ class CEGUIWindow { * * Exposes: * - CEGUIWindow::CEGUIWindow(string) + * - CEGUIWindow::isNull * - CEGUIWindow::getText * - CEGUIWindow::setText * - CEGUIWindow::appendText @@ -59,6 +77,11 @@ class CEGUIWindow { * - CEGUIWindow::listboxResetList * - CEGUIWindow::listboxHandleUpdatedItemData * + * - CEGUIWindow::itemListboxAddItem + * - CEGUIWindow::itemListboxResetList + * - CEGUIWindow::itemListboxHandleUpdatedItemData + * - CEGUIWindow::itemListboxGetLastSelectedItem + * * - CEGUIWindow::progressbarSetProgress * * @return @@ -66,6 +89,15 @@ class CEGUIWindow { static luabind::scope luaBindings(); + + /** + * @brief Returns whether the underlying CEGUI::Window is a nullptr + * + * @return isNull + */ + bool + isNull() const; + /** * @brief Creates a new windows and adds it to the underlying CEGUI window * @@ -142,8 +174,8 @@ class CEGUIWindow { /** * @brief Adds a string to the window if it is a listbox otherwise throws bad_cast exception * - * @param text - * The text to add + * @param listboxItem + * The text item to add */ void listboxAddItem( @@ -162,6 +194,34 @@ class CEGUIWindow { void listboxHandleUpdatedItemData(); + /** + * @brief Adds an item to the window if it is a itemlist otherwise throws bad_cast exception + * + * Register a click event for action on selection + * + * @param listboxItem + * The item to add + */ + void + itemListboxAddItem( + CEGUIWindow* item + ); + + /** + * @brief Clears the list if the window is a itemlist otherwise throws bad_cast exception + */ + void + itemListboxResetList(); + + /** + * @brief Updates the rendering of the itemlist + */ + void + itemListboxHandleUpdatedItemData(); + + CEGUIWindow* + itemListboxGetLastSelectedItem(); + /** * @brief Sets the progress of the progressbar * diff --git a/src/gui/script_bindings.cpp b/src/gui/script_bindings.cpp index 275812f23ee..b69988bba83 100644 --- a/src/gui/script_bindings.cpp +++ b/src/gui/script_bindings.cpp @@ -33,11 +33,61 @@ listboxItemBindings() { ; } +static void +ItemEntry_setText( + CEGUI::ItemEntry* self, + const std::string& text +) { + self->setText(text); +} + +static bool +ItemEntry_isSelected( + CEGUI::ItemEntry* self +) { + return self->isSelected(); +} + +static void +ItemEntry_select( + CEGUI::ItemEntry* self +) { + self->select(); +} + +static void +ItemEntry_deselect( + CEGUI::ItemEntry* self +) { + self->deselect(); +} + +static void +ItemEntry_setSelectable( + CEGUI::ItemEntry* self, + bool setting +) { + self->setSelectable(setting); +} + +static luabind::scope +itemEntryBindings() { + return class_("ItemEntry") + .def(constructor()) + .def("isSelected", &ItemEntry_isSelected) + .def("select", &ItemEntry_select) + .def("deselect", &ItemEntry_deselect) + .def("setSelectable", &ItemEntry_setSelectable) + .def("setText", &ItemEntry_setText) + ; +} + luabind::scope thrive::GuiBindings::luaBindings() { return ( // Other listboxItemBindings(), + itemEntryBindings(), CEGUIWindow::luaBindings() ); } diff --git a/thriveversion.ver b/thriveversion.ver new file mode 100644 index 00000000000..f4778493c50 --- /dev/null +++ b/thriveversion.ver @@ -0,0 +1 @@ +0.2.2 \ No newline at end of file