diff --git a/build/android/jni/src/Android.mk b/build/android/jni/src/Android.mk index cbb439f..0c3810f 100755 --- a/build/android/jni/src/Android.mk +++ b/build/android/jni/src/Android.mk @@ -9,6 +9,7 @@ SDL_PATH := ../SDL2 LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../src LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../src/states +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../src/gui # Add your application source files here... LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \ @@ -48,11 +49,15 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \ ../../../../src/common.hpp \ ../../../../src/Core.cpp \ ../../../../src/Core.hpp \ + ../../../../src/Gui.cpp \ + ../../../../src/Gui.hpp \ ../../../../src/State.hpp \ ../../../../src/states/MenuState.cpp \ ../../../../src/states/MenuState.hpp \ ../../../../src/states/TestState.cpp \ ../../../../src/states/TestState.hpp \ + ../../../../src/gui/GuiElement.cpp \ + ../../../../src/gui/GuiElement.hpp \ ../../../../src/main.cpp LOCAL_SHARED_LIBRARIES := SDL2 diff --git a/build/ios/Roll them Bones.xcodeproj/project.pbxproj b/build/ios/Roll them Bones.xcodeproj/project.pbxproj index 78787c1..9ae9a52 100755 --- a/build/ios/Roll them Bones.xcodeproj/project.pbxproj +++ b/build/ios/Roll them Bones.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ 2056AE561A8A423E00833760 /* RenderObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2056AE511A8A423E00833760 /* RenderObject.cpp */; }; 2056AE571A8A423E00833760 /* Vec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2056AE531A8A423E00833760 /* Vec.cpp */; }; 205723E11A9B4053001400FA /* chest.obj in Resources */ = {isa = PBXBuildFile; fileRef = 205723DB1A9B4053001400FA /* chest.obj */; }; + 2078E3811AA5CE4700172D34 /* GuiElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2078E37F1AA5CE4700172D34 /* GuiElement.cpp */; }; + 2078E3841AA5CE5500172D34 /* Gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2078E3821AA5CE5500172D34 /* Gui.cpp */; }; 20A7A91D1A89F91300EDC1A0 /* RenderCamera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A7A9151A89F91300EDC1A0 /* RenderCamera.cpp */; }; 20A7A91E1A89F91300EDC1A0 /* RenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A7A9171A89F91300EDC1A0 /* RenderScene.cpp */; }; 20A7A91F1A89F91300EDC1A0 /* RenderSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A7A9191A89F91300EDC1A0 /* RenderSet.cpp */; }; @@ -165,6 +167,10 @@ 2056AE531A8A423E00833760 /* Vec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Vec.cpp; path = ../../src/Vec.cpp; sourceTree = SOURCE_ROOT; }; 2056AE541A8A423E00833760 /* Vec.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Vec.hpp; path = ../../src/Vec.hpp; sourceTree = SOURCE_ROOT; }; 205723DB1A9B4053001400FA /* chest.obj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = chest.obj; path = ../../data/models/chest.obj; sourceTree = SOURCE_ROOT; }; + 2078E37F1AA5CE4700172D34 /* GuiElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GuiElement.cpp; path = ../../src/gui/GuiElement.cpp; sourceTree = SOURCE_ROOT; }; + 2078E3801AA5CE4700172D34 /* GuiElement.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GuiElement.hpp; path = ../../src/gui/GuiElement.hpp; sourceTree = SOURCE_ROOT; }; + 2078E3821AA5CE5500172D34 /* Gui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Gui.cpp; path = ../../src/Gui.cpp; sourceTree = SOURCE_ROOT; }; + 2078E3831AA5CE5500172D34 /* Gui.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Gui.hpp; path = ../../src/Gui.hpp; sourceTree = SOURCE_ROOT; }; 20A7A9151A89F91300EDC1A0 /* RenderCamera.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RenderCamera.cpp; path = ../../src/RenderCamera.cpp; sourceTree = SOURCE_ROOT; }; 20A7A9161A89F91300EDC1A0 /* RenderCamera.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RenderCamera.hpp; path = ../../src/RenderCamera.hpp; sourceTree = SOURCE_ROOT; }; 20A7A9171A89F91300EDC1A0 /* RenderScene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RenderScene.cpp; path = ../../src/RenderScene.cpp; sourceTree = SOURCE_ROOT; }; @@ -341,9 +347,21 @@ path = shaders; sourceTree = ""; }; + 2078E37E1AA5CE3700172D34 /* Gui */ = { + isa = PBXGroup; + children = ( + 2078E37F1AA5CE4700172D34 /* GuiElement.cpp */, + 2078E3801AA5CE4700172D34 /* GuiElement.hpp */, + ); + name = Gui; + sourceTree = ""; + }; 20A7A9131A89F8F600EDC1A0 /* Classes */ = { isa = PBXGroup; children = ( + 2078E3821AA5CE5500172D34 /* Gui.cpp */, + 2078E3831AA5CE5500172D34 /* Gui.hpp */, + 2078E37E1AA5CE3700172D34 /* Gui */, 20FC42231AA460BC0083B64C /* State.hpp */, 20FC421D1AA4607B0083B64C /* States */, 20F7468F1AA3265900F5846A /* HashTable.hpp */, @@ -540,6 +558,8 @@ 20F7466B1AA27B8C00F5846A /* AssetManager.cpp in Sources */, 20FC42201AA460960083B64C /* MenuState.cpp in Sources */, 20FC425D1AA56A150083B64C /* TestState.cpp in Sources */, + 2078E3811AA5CE4700172D34 /* GuiElement.cpp in Sources */, + 2078E3841AA5CE5500172D34 /* Gui.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/build/osx/Roll them Bones.xcodeproj/project.pbxproj b/build/osx/Roll them Bones.xcodeproj/project.pbxproj index ed75dc4..8f03a1b 100644 --- a/build/osx/Roll them Bones.xcodeproj/project.pbxproj +++ b/build/osx/Roll them Bones.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 20F746501AA1DE0F00F5846A /* AssetCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20F7464E1AA1DE0F00F5846A /* AssetCache.cpp */; }; 20FC41F11AA45D880083B64C /* MenuState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20FC41EF1AA45D880083B64C /* MenuState.cpp */; }; 20FC42581AA569FB0083B64C /* TestState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20FC42561AA569FB0083B64C /* TestState.cpp */; }; + 20FC42651AA587F10083B64C /* Gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20FC42631AA587F10083B64C /* Gui.cpp */; }; + 20FC42891AA5C00A0083B64C /* GuiElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20FC42871AA5C00A0083B64C /* GuiElement.cpp */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; /* End PBXBuildFile section */ @@ -124,6 +126,10 @@ 20FC41F01AA45D880083B64C /* MenuState.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = MenuState.hpp; path = ../../src/states/MenuState.hpp; sourceTree = SOURCE_ROOT; }; 20FC42561AA569FB0083B64C /* TestState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestState.cpp; path = ../../src/states/TestState.cpp; sourceTree = SOURCE_ROOT; }; 20FC42571AA569FB0083B64C /* TestState.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TestState.hpp; path = ../../src/states/TestState.hpp; sourceTree = SOURCE_ROOT; }; + 20FC42631AA587F10083B64C /* Gui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Gui.cpp; path = ../../src/Gui.cpp; sourceTree = SOURCE_ROOT; }; + 20FC42641AA587F10083B64C /* Gui.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Gui.hpp; path = ../../src/Gui.hpp; sourceTree = SOURCE_ROOT; }; + 20FC42871AA5C00A0083B64C /* GuiElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GuiElement.cpp; path = ../../src/gui/GuiElement.cpp; sourceTree = SOURCE_ROOT; }; + 20FC42881AA5C00A0083B64C /* GuiElement.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GuiElement.hpp; path = ../../src/gui/GuiElement.hpp; sourceTree = SOURCE_ROOT; }; 8D1107320486CEB800E47090 /* Roll them Bones.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Roll them Bones.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -145,6 +151,9 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 20FC42861AA5BFF50083B64C /* Gui */, + 20FC42631AA587F10083B64C /* Gui.cpp */, + 20FC42641AA587F10083B64C /* Gui.hpp */, 20FC41ED1AA45D650083B64C /* States */, 20F746731AA325C000F5846A /* HashTable.hpp */, 20F7464E1AA1DE0F00F5846A /* AssetCache.cpp */, @@ -268,6 +277,15 @@ name = States; sourceTree = ""; }; + 20FC42861AA5BFF50083B64C /* Gui */ = { + isa = PBXGroup; + children = ( + 20FC42871AA5C00A0083B64C /* GuiElement.cpp */, + 20FC42881AA5C00A0083B64C /* GuiElement.hpp */, + ); + name = Gui; + sourceTree = ""; + }; 29B97314FDCFA39411CA2CEA /* INDIE */ = { isa = PBXGroup; children = ( @@ -398,6 +416,8 @@ 20F746501AA1DE0F00F5846A /* AssetCache.cpp in Sources */, 20FC41F11AA45D880083B64C /* MenuState.cpp in Sources */, 20FC42581AA569FB0083B64C /* TestState.cpp in Sources */, + 20FC42651AA587F10083B64C /* Gui.cpp in Sources */, + 20FC42891AA5C00A0083B64C /* GuiElement.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/Core.cpp b/src/Core.cpp index f153e19..a90c83c 100644 --- a/src/Core.cpp +++ b/src/Core.cpp @@ -7,8 +7,6 @@ Core is somewhat like a service locator, but with larger engine capabilities - i #include "Log.hpp" #include "RenderScene.hpp" #include "RenderCamera.hpp" -#include "RenderSet.hpp" -#include "RenderObject.hpp" #include "State.hpp" #include "MenuState.hpp" #include "TestState.hpp" @@ -122,6 +120,7 @@ int Core::initSystem() { // FIXME: temporary location for adding cameras/etc. for testing // Create our basic RenderScene scene = new RenderScene(); + gui = new Gui(); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); tick_rate = 10; @@ -136,6 +135,7 @@ int Core::initSystem() { } int Core::closeSystem() { LOG(LOG_INFO) << FUNC_NAME << ": adios!"; + delete gui; delete scene; // TODO: delete scene should delete rendercameras, renderviews, rendersets, and renderobjects. // TODO: delete meshes loaded (assets) as well @@ -174,9 +174,12 @@ void Core::doProcess() { } } } else { - if (states.size() > 0) { - State *state = states.back(); - state->onEvent(event); + // send the event to the GUI + if (gui->onEvent(event) == 0) { + if (states.size() > 0) { + State *state = states.back(); + state->onEvent(event); + } } } } @@ -237,3 +240,6 @@ int Core::getHeight() { AssetManager* Core::getAssetManager() { return asset_manager; } +Gui* Core::getGui() { + return gui; +} diff --git a/src/Core.hpp b/src/Core.hpp index 642a0a8..f344977 100644 --- a/src/Core.hpp +++ b/src/Core.hpp @@ -8,6 +8,7 @@ Core is somewhat like a service locator, but with larger engine capabilities - i #include "common.hpp" #include "RenderScene.hpp" #include "AssetManager.hpp" +#include "Gui.hpp" #include "State.hpp" #include class Core { @@ -23,9 +24,9 @@ class Core { SDL_Window* getWindow(); RenderScene *getScene(); AssetManager *getAssetManager(); + Gui* getGui(); // Audio* getAudio(); // Net* getNet(); - // Gui* getGui(); int pushState(State *state); int popState(); int getWidth(); @@ -40,6 +41,7 @@ class Core { int v_flags; // video flags RenderScene *scene; // our current render scene AssetManager *asset_manager; // our asset manager service + Gui *gui; // our GUI service std::vector states; // our record of states // Audio *audio_service; // Net *net_service; diff --git a/src/Gui.cpp b/src/Gui.cpp new file mode 100644 index 0000000..32e58ae --- /dev/null +++ b/src/Gui.cpp @@ -0,0 +1,64 @@ +/* ================================================================ +GUI +---------------- +Gui.cpp/Gui.hpp provide the class responsible for creating, destroying, and handling GUI elements. +================================================================ */ +#include "Gui.hpp" +#include "Core.hpp" +#include "Log.hpp" + +Gui::Gui() { +} +Gui::~Gui() { +} +/* onEvent +This function is called by Core::doProcess and receives: + * keypresses + * motion events (touch, mouse, etc.) + +If the event is to be passed to the State, this function returns 0. If the event is to be nommed, a non-zero value is returned + +NOTE: element processing is started at the end of the vector and works its way to the beginning. This seems to be an okay approach to handling element priority without dealing with special "z" ordering. +*/ +int Gui::onEvent(SDL_Event event) { + std::vector::reverse_iterator element_it, element_end; + GuiElement *element = NULL; + float x, y; + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + x = float(event.button.x) / float(core.getWidth()); + y = float(event.button.y) / float(core.getHeight()); + LOG(LOG_INFO) << FUNC_NAME << ": CHECK: " << x << "x" << y; + for (element_it = elements.rbegin(), element_end = elements.rend(); element_it != element_end; ++element_it) { + element = (*element_it)->getHit(x, y); + if (element != NULL) break; + } + break; + case SDL_FINGERDOWN: + case SDL_FINGERUP: + x = event.tfinger.x; + y = event.tfinger.y; + LOG(LOG_INFO) << FUNC_NAME << ": CHECK: " << x << "x" << y; + for (element_it = elements.rbegin(), element_end = elements.rend(); element_it != element_end; ++element_it) { + element = (*element_it)->getHit(x, y); + if (element != NULL) break; + } + break; + default: + break; + } + if (element != NULL) return 1; + return 0; +} +int Gui::addElement(GuiElement *element) { + // Get the top-most (parent) element and only add that. + GuiElement *top_element = element->parent; + while (top_element != NULL) { + element = top_element; + top_element = top_element->parent; + } + elements.push_back(element); + LOG(LOG_INFO) << FUNC_NAME << " added element " << element->text; + return elements.size()-1; +} diff --git a/src/Gui.hpp b/src/Gui.hpp new file mode 100644 index 0000000..34ee82f --- /dev/null +++ b/src/Gui.hpp @@ -0,0 +1,22 @@ +/* ================================================================ +GUI +---------------- +Gui.cpp/Gui.hpp provide the class responsible for creating, destroying, and handling GUI elements. +================================================================ */ +#ifndef GUI_HPP +#define GUI_HPP +#include "SDL.h" +#include "GuiElement.hpp" +#include +class Gui { + friend class Core; + public: + Gui(); + ~Gui(); + int addElement(GuiElement *element); + protected: + int onEvent(SDL_Event event); + private: + std::vector elements; +}; +#endif diff --git a/src/gui/GuiElement.cpp b/src/gui/GuiElement.cpp new file mode 100644 index 0000000..1db7845 --- /dev/null +++ b/src/gui/GuiElement.cpp @@ -0,0 +1,65 @@ +#include "GuiElement.hpp" +#include "Log.hpp" + +GuiElement::GuiElement(const char *string, GuiElement *parent_) { + parent = parent_; + parent->addChild(this); + type = DEFAULT; + text.assign(string); + x = 0.25; y = 0.25; + w = 0.25; h = 0.25; +} +GuiElement::GuiElement(const char *string) { + parent = NULL; + type = DEFAULT; + text.assign(string); + x = 0.25; y = 0.25; + w = 0.25; h = 0.25; +} +GuiElement::GuiElement(const char *string, int group_id, int this_id) { + parent = NULL; + type = DEFAULT; + text.assign(string); + gid = group_id; + id = this_id; + x = 0.25; y = 0.25; + w = 0.25; h = 0.25; +} +GuiElement::GuiElement() { + parent = NULL; + type = DEFAULT; + x = 0.25; y = 0.25; + w = 0.25; h = 0.25; +} +GuiElement::~GuiElement() { +} +/* ======== Relationships ======== */ +int GuiElement::addChild(GuiElement *child) { + children.push_back(child); + return children.size()-1; +} +/* ======== Interactions ======== */ +/* getHit + This function takes in normalized coordinates and returns either NULL or the element hit if within the element's bounding box. If this element is hit, it will call getHit to all children elements until either a match is found or NULL is returned. If a match is found, that is returned, otherwise this element is returned. +*/ +GuiElement* GuiElement::getHit(float xhit, float yhit) { + GuiElement *element = NULL; + if ( (xhit >= x && xhit <= x+w) && (yhit >= y && yhit <= y+h) ) { + LOG(LOG_INFO) << FUNC_NAME << ": HIT " << text <<": " << xhit << "x" << yhit; + // check the children for hits and return them if so + GuiElement *child_element = NULL; + // Start from the end of the vector and walk backwards + std::vector::reverse_iterator element_it, element_end; + for (element_it = children.rbegin(), element_end = children.rend(); element_it != element_end; ++element_it) { + child_element = (*element_it)->getHit(xhit, yhit); + } + if (child_element != NULL) { + element = child_element; + } else { + element = this; + } + } else { + element = NULL; + } + return element; +} diff --git a/src/gui/GuiElement.hpp b/src/gui/GuiElement.hpp new file mode 100644 index 0000000..17d3729 --- /dev/null +++ b/src/gui/GuiElement.hpp @@ -0,0 +1,41 @@ +/* ================================================================ +GuiElement +---------------- +This file describes the GuiElement class. This is the base class for further GUI Elements such as buttons, text input, or otherwise. +================================================================ */ +#ifndef GUIELEMENT_HPP +#define GUIELEMENT_HPP +#include +#include +class GuiElement { + friend class Gui; + public: + enum Type { + DEFAULT = 0, + BUTTON, + TEXT, + TEXTINPUT, + TEXTAREA, + CHECKBOX + }; + GuiElement(); + GuiElement(const char *string); + GuiElement(const char *string, GuiElement *parent_); + GuiElement(const char *string, int group_id, int this_id); + ~GuiElement(); + // + // int setGeometry(float x, float y, float w, float h); + // int setText(const char *string); + GuiElement *getHit(float xhit, float yhit); + int addChild(GuiElement *child); + protected: + std::vector children; // children of this element + GuiElement *parent; // parent of this element + std::string text; // text of this element + int type; // flag for this type + int gid; // group id for this element + int id; // id for this element + // + float x, y, w, h; // position and dimensions for this element +}; +#endif diff --git a/src/states/TestState.cpp b/src/states/TestState.cpp index ae429bb..57b27d9 100644 --- a/src/states/TestState.cpp +++ b/src/states/TestState.cpp @@ -9,6 +9,7 @@ /* ======== Construction and Destruction ======== */ TestState::TestState() { scene = NULL; + gui = NULL; } TestState::~TestState() { @@ -83,6 +84,7 @@ int TestState::onEvent(SDL_Event event) { int TestState::onRise() { scene = core.getScene(); asset_manager = core.getAssetManager(); + gui = core.getGui(); return 0; } int TestState::onCede() { @@ -91,6 +93,7 @@ int TestState::onCede() { int TestState::onInit() { // Get our services asset_manager = core.getAssetManager(); + gui = core.getGui(); // TEMP: our framebuffer rendering program Program *program = new Program(); // FIXME: check for GLSL version and automagically load the appropriate shader file @@ -207,5 +210,8 @@ int TestState::onInit() { scene->addSet(sert); + // GUI testing + gui->addElement(new GuiElement("test", 10, 1)); + return 0; } diff --git a/src/states/TestState.hpp b/src/states/TestState.hpp index 19a9cf2..cf83127 100644 --- a/src/states/TestState.hpp +++ b/src/states/TestState.hpp @@ -8,6 +8,7 @@ TestState.cpp/TestState.hpp provide the Main Test state that the program first a #include "State.hpp" #include "RenderScene.hpp" #include "AssetManager.hpp" +#include "Gui.hpp" class TestState : public State { friend class Core; public: @@ -22,5 +23,6 @@ class TestState : public State { private: RenderScene *scene; AssetManager *asset_manager; + Gui *gui; }; #endif