From 8c2dfb042a1e45e1be1aaea32921dc5f2b985c63 Mon Sep 17 00:00:00 2001 From: kts Date: Fri, 6 Mar 2015 21:39:07 -0800 Subject: [PATCH] Added Program HashTable to core. Some delete/remove functionality added to various Render* classes. Gui/GuiList somewhat works. GUI is now specified in terms of (0,0) being at the top-left of the screen. Need to recode so GuiElement contains majority of the needed functionality for updating (and that even GuiList(s) contain proper positioning and sizing. Embedding elements in elements will be much easier and more functional if it's abstracted to the base class rather than a specific subclass. --- build/linux/Makefile | 6 +- src/AssetCache.cpp | 2 +- src/Core.cpp | 38 +++++++++++- src/Core.hpp | 4 ++ src/Gui.cpp | 23 +++++++- src/Gui.hpp | 1 + src/Program.cpp | 13 ++++- src/RenderScene.cpp | 12 +++- src/RenderScene.hpp | 1 + src/RenderSet.cpp | 23 +++++++- src/RenderSet.hpp | 2 + src/gui/GuiButton.cpp | 24 +------- src/gui/GuiButton.hpp | 3 +- src/gui/GuiElement.cpp | 108 +++++++++++++++++++++++----------- src/gui/GuiElement.hpp | 16 +++-- src/gui/GuiList.cpp | 122 +++++++++++++++++++++++++++++++-------- src/gui/GuiList.hpp | 16 ++++- src/states/MenuState.cpp | 66 ++++++++++++++++++++- src/states/MenuState.hpp | 9 +++ src/states/TestState.cpp | 35 ++++------- 20 files changed, 398 insertions(+), 126 deletions(-) diff --git a/build/linux/Makefile b/build/linux/Makefile index 9051926..69cd592 100644 --- a/build/linux/Makefile +++ b/build/linux/Makefile @@ -11,10 +11,10 @@ endif CXX=g++ DEBUG=-g CXXFLAGS+=$(DEBUG) -Wall `sdl2-config --cflags` -I../../src -I../../src/states -I../../src/gui -c -LDFLAGS+= -Wall -L../../../sdl/$(LIB_DIR) -Wl,-rpath=$(LIB_DIR)/ -lSDL2 -lSDL2_image -lpthread -Wl,--no-undefined -lm -ldl -pthread -lrt -Wl,-Bstatic -lGLEW -Wl,-Bdynamic -lGL +LDFLAGS+= -Wall -L../../../sdl/$(LIB_DIR) -Wl,-rpath=$(LIB_DIR)/ -lSDL2 -lSDL2_image -lSDL2_ttf -lpthread -Wl,--no-undefined -lm -ldl -pthread -lrt -Wl,-Bstatic -lGLEW -Wl,-Bdynamic -lGL VPATH=../../src BINARY=RtB$(BITS) -OBJ=main.o Asset.o AssetCache.o AssetManager.o Core.o fio.o checksum.o Log.o Quat.o Mat4.o Vec.o Mesh.o Texture.o Program.o RenderScene.o RenderSet.o RenderObject.o RenderCamera.o RenderView.o states/TestState.o states/MenuState.o SysInfo.o Gui.o gui/GuiElement.o gui/GuiButton.o gui/GuiList.o +OBJ=main.o Asset.o AssetCache.o AssetManager.o Core.o fio.o checksum.o Log.o Quat.o Mat4.o Vec.o Mesh.o Texture.o Program.o RenderScene.o RenderSet.o RenderObject.o RenderCamera.o RenderView.o states/TestState.o states/MenuState.o SysInfo.o Font.o Gui.o gui/GuiElement.o gui/GuiButton.o gui/GuiList.o OBJ_DIR=obj $(BINARY): $(patsubst %,$(OBJ_DIR)/%,$(OBJ)) @@ -41,5 +41,5 @@ $(OBJ_DIR)/%.o: %.cpp $(CXX) $(CXXFLAGS) $< -o $@ clean: - rm -f $(OBJ_DIR)/*.o + rm -rf $(OBJ_DIR)/* rm -rf build/* diff --git a/src/AssetCache.cpp b/src/AssetCache.cpp index 2cc9b88..b10f498 100644 --- a/src/AssetCache.cpp +++ b/src/AssetCache.cpp @@ -247,7 +247,7 @@ int AssetCache::toFile(const char *cache_file) { #else fprintf(file, "%s %u %jd\n", asset->filename.c_str(), asset->data_checksum, (intmax_t)asset->data_length); #endif - LOG(LOG_DEBUG) << ": saving " << asset->filename.c_str() << " bytes " << asset->data_length; + //LOG(LOG_DEBUG) << ": saving " << asset->filename.c_str() << " bytes " << asset->data_length; } fclose(file); return 0; diff --git a/src/Core.cpp b/src/Core.cpp index 13ed015..360c616 100644 --- a/src/Core.cpp +++ b/src/Core.cpp @@ -193,6 +193,31 @@ int Core::initSystem() { default_font = new Font("fonts/default.ttf", 16, asset->getData(), asset->getDataLength()); font_table = new HashTable(8); font_table->setnull(default_font); + // Program Management + program_table = new HashTable(16); + program_table->setnull(NULL); + // ** FRAMEBUFFER PROGRAM ** + // Load in our Framebuffer program (who else is to manage?) + Program *program = new Program(); + std::string shader_file; + shader_file = "shaders/" + core.shader_version + "/fb_fs.glsl"; + Asset *shader_asset = asset_manager->loadFile(shader_file.c_str()); + if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_FRAGMENT_SHADER) != 0) { + LOG(LOG_ERROR) << "Failed to add Shader!"; + return 1; + } + shader_asset->unloadData(); + shader_file = "shaders/" + core.shader_version + "/fb_vs.glsl"; + shader_asset = asset_manager->loadFile(shader_file.c_str()); + if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_VERTEX_SHADER) != 0) { + LOG(LOG_ERROR) << FUNC_NAME << "Failed to add Shader" << shader_file << "!"; + } + shader_asset->unloadData(); + if (program->doCompile() != 0) { + LOG(LOG_ERROR) << FUNC_NAME << ": Failed to compile framebuffer GLSL Program!"; + } + setProgram("fb", program); + //asset->unloadData(); // Create our basic RenderScene @@ -207,9 +232,8 @@ int Core::initSystem() { tick_delta = 0; tick_accumulator = tick_rate; - pushState(new TestState()); - flags |= IS_RUNNING; + pushState(new MenuState()); return 0; } int Core::closeSystem() { @@ -385,3 +409,13 @@ Font* Core::getFont(const char *font_name) { } return font; } +Program* Core::getProgram(const char *program_name) { + return program_table->get(program_name); +} +int Core::setProgram(const char *program_name, Program *program) { + Program *old_prog = program_table->get(program_name); + if (old_prog != NULL) delete old_prog; + program_table->set(program_name, program); + return 0; +} + diff --git a/src/Core.hpp b/src/Core.hpp index 2e859c9..fc30c82 100644 --- a/src/Core.hpp +++ b/src/Core.hpp @@ -44,6 +44,10 @@ class Core { HashTable *font_table; Font *default_font; // + Program *getProgram(const char *program_name); + int setProgram(const char *program_name, Program *program); + HashTable *program_table; + // int pushState(State *state); int popState(); int getWidth(); diff --git a/src/Gui.cpp b/src/Gui.cpp index 7b000d6..df9ea0f 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -124,9 +124,12 @@ int Gui::onEvent(SDL_Event event) { return 0; } int Gui::addElement(GuiElement *element) { + if (element == NULL) { + LOG(LOG_WARNING) << FUNC_NAME << ": NULL element passed"; + return 1; + } // - if (element->object == NULL && !(element->type & GuiElement::LIST)) { - element->object = new RenderObject(); + if (!(element->type & GuiElement::LIST)) { element->object->setMesh(element_mesh); set_basic->addObject(element->object); if (element->flags & GuiElement::HIDDEN) element->object->hide(); @@ -151,6 +154,22 @@ int Gui::addElement(GuiElement *element) { } return elements.size()-1; } +int Gui::delElement(const char *name) { + GuiElement *element; + std::vector::iterator element_it, element_end; + for (element_it = elements.begin(), element_end = elements.end(); element_it != element_end;) { + element = *element_it; + if (strcmp(element->text.c_str(), name) == 0) { + if (element->object != NULL) set_basic->remObject(element->object); + delete element; + element_it = elements.erase(element_it); + return 0; + } else { + ++element_it; + } + } + return 1; +} int Gui::setView(int width, int height) { w = width; h = height; diff --git a/src/Gui.hpp b/src/Gui.hpp index 21bed5c..664dbf5 100644 --- a/src/Gui.hpp +++ b/src/Gui.hpp @@ -17,6 +17,7 @@ class Gui { Gui(); ~Gui(); int addElement(GuiElement *element); + int delElement(const char *name); void updateElements(); int getWidth(); int getHeight(); diff --git a/src/Program.cpp b/src/Program.cpp index 3fe08a4..1666efa 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -94,8 +94,17 @@ int Program::deactivate() { } /* ======== Cleaning ======== */ int Program::doClean() { - // TODO: glDetachShader - // TODO: glDeleteProgram + // detach and delete shader (should actually detach earlier FIXME + size_t i; + for (i = 0; i < shader_prog.size(); i++) { + GLuint shader = shader_prog.at(i); + glDetachShader(program, shader); + glDeleteShader(shader); + } + shader_prog.clear(); + // delete program + glDeleteProgram(program); + program = 0; return 0; } /* ======== Variable interfaces ======== */ diff --git a/src/RenderScene.cpp b/src/RenderScene.cpp index 1ab258a..8bf891e 100644 --- a/src/RenderScene.cpp +++ b/src/RenderScene.cpp @@ -168,7 +168,7 @@ RenderCamera* RenderScene::getCamera(int id) { try { return cameras.at(id-1); } catch (const std::out_of_range& oor) { - LOG(LOG_ERROR) << FUNC_NAME << ": RenderCamera index out of range: " << oor.what(); + LOG(LOG_WARNING) << FUNC_NAME << ": RenderCamera index out of range: " << oor.what(); } return NULL; } @@ -204,6 +204,16 @@ int RenderScene::remSet(RenderSet *set) { LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderSet"; return 1; } +int RenderScene::delSet(RenderSet *set) { + std::vector::iterator it; + if ((it = std::find(sets.begin(), sets.end(), set)) != sets.end()) { + sets.erase(it); + delete set; + return 0; + } + LOG(LOG_WARNING) << FUNC_NAME << ": Could not delete RenderSet"; + return 1; +} RenderSet* RenderScene::getSet(int id) { try { diff --git a/src/RenderScene.hpp b/src/RenderScene.hpp index 35b4fbe..1de7113 100644 --- a/src/RenderScene.hpp +++ b/src/RenderScene.hpp @@ -27,6 +27,7 @@ class RenderScene { std::vector *getCameras(); int addSet(RenderSet *set); int remSet(RenderSet *set); + int delSet(RenderSet *set); int remSet(int id); RenderSet* getSet(int id); std::vector *getSets(); diff --git a/src/RenderSet.cpp b/src/RenderSet.cpp index 99e9ee6..a629bc5 100644 --- a/src/RenderSet.cpp +++ b/src/RenderSet.cpp @@ -5,6 +5,7 @@ This header file defines the RenderSet class. ================================================================ */ #include "RenderSet.hpp" #include "Log.hpp" +#include /* ======== Constructors and Destructors ======== */ RenderSet::RenderSet() { program = NULL; @@ -20,7 +21,27 @@ int RenderSet::addObject(RenderObject *object) { } return 0; } +int RenderSet::remObject(RenderObject *object) { + std::vector::iterator it; + if ((it = std::find(objects.begin(), objects.end(), object)) != objects.end()) { + objects.erase(it); + return 0; + } + LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderObject"; + return 1; +} +int RenderSet::delObject(RenderObject *object) { + std::vector::iterator it; + if ((it = std::find(objects.begin(), objects.end(), object)) != objects.end()) { + objects.erase(it); + delete object; + return 0; + } + LOG(LOG_WARNING) << FUNC_NAME << ": Could not delete RenderObject"; + return 1; +} + int RenderSet::setProgram(Program *prog) { program = prog; return 0; -} \ No newline at end of file +} diff --git a/src/RenderSet.hpp b/src/RenderSet.hpp index 06b203e..6abebc5 100644 --- a/src/RenderSet.hpp +++ b/src/RenderSet.hpp @@ -20,6 +20,8 @@ class RenderSet { RenderSet(); ~RenderSet(); int addObject(RenderObject *object); + int remObject(RenderObject *object); + int delObject(RenderObject *object); int setProgram(Program *prog); private: int mode; // bitflag, 0 = normal, 1 = hide diff --git a/src/gui/GuiButton.cpp b/src/gui/GuiButton.cpp index 0afa0d3..a85324f 100644 --- a/src/gui/GuiButton.cpp +++ b/src/gui/GuiButton.cpp @@ -1,8 +1,8 @@ #include "GuiButton.hpp" #include "Log.hpp" -GuiButton::GuiButton(std::string string, Texture *texture_) { - text.assign(string); +GuiButton::GuiButton(const char *name, Texture *texture_) { + text.assign(name); texture = texture_; } GuiButton::~GuiButton() { @@ -10,25 +10,7 @@ GuiButton::~GuiButton() { } int GuiButton::doUpdate(int c_width, int c_height) { - float ex = x * 2; - float ey = y * 2; - if (pflags & TOP) { - ey = c_height - ey + h - offset_y; - } else if (pflags & BOTTOM) { - ey = -c_height + ey - h + offset_y; - } else if (pflags & VCENTER) { - ey = ey; - } - if (pflags & LEFT) { - ex = -c_width + ex - w + offset_x; - } else if (pflags & RIGHT) { - ex = c_width - ex + w - offset_x; - } else if (pflags & HCENTER) { - ex = ex; - } - if (object == NULL) return 1; // return if we haven't been added to Gui yet - object->setTranslation(ex, 0.0f, ey); - object->calcMatrix(); + GuiElement::doUpdate(c_width, c_height); if (texture != NULL) object->setTexture(texture); return 0; } diff --git a/src/gui/GuiButton.hpp b/src/gui/GuiButton.hpp index 83970a7..e1469a5 100644 --- a/src/gui/GuiButton.hpp +++ b/src/gui/GuiButton.hpp @@ -1,12 +1,11 @@ #ifndef GUIBUTTON_HPP #define GUIBUTTON_HPP #include "GuiElement.hpp" -#include #include "Texture.hpp" class GuiButton : public GuiElement { public: - GuiButton(std::string text, Texture *texture); + GuiButton(const char *name, Texture *texture); ~GuiButton(); virtual int doUpdate(int c_width, int c_height); protected: diff --git a/src/gui/GuiElement.cpp b/src/gui/GuiElement.cpp index 66bcda7..52f1d9f 100644 --- a/src/gui/GuiElement.cpp +++ b/src/gui/GuiElement.cpp @@ -2,31 +2,35 @@ #include "Core.hpp" // UGH #include "Gui.hpp" // UGH x2 #include "Log.hpp" +#include GuiElement::GuiElement(const char *string, GuiElement *parent_) { - parent = parent_; parent->addChild(this); type = DEFAULT; text.assign(string); - object = NULL; + object = new RenderObject(); view = NULL; pflags = 0; flags = 0; - x = 0.25; y = 0.25; + x = y = 0; offset_x = offset_y = 0; - w = 0.25; h = 0.25; + w = 32.0f; h = 32.0f; + margin_l = margin_r = margin_t = margin_b = 0.0f; + padding_l = padding_r = padding_t = padding_b = 0.0f; } GuiElement::GuiElement(const char *string) { parent = NULL; type = DEFAULT; text.assign(string); - object = NULL; + object = new RenderObject(); pflags = 0; flags = 0; view = NULL; offset_x = offset_y = 0; - x = 0.25; y = 0.25; - w = 0.25; h = 0.25; + x = y = 0; + w = 32.0f; h = 32.0f; + margin_l = margin_r = margin_t = margin_b = 0.0f; + padding_l = padding_r = padding_t = padding_b = 0.0f; } GuiElement::GuiElement(const char *string, int group_id, int this_id) { parent = NULL; @@ -34,34 +38,52 @@ GuiElement::GuiElement(const char *string, int group_id, int this_id) { text.assign(string); gid = group_id; id = this_id; - object = NULL; + object = new RenderObject(); view = NULL; pflags = 0; flags = 0; - x = 0.25; y = 0.25; + x = y = 0; offset_x = offset_y = 0; - w = 0.25; h = 0.25; + w = 32.0f; h = 32.0f; + margin_l = margin_r = margin_t = margin_b = 0.0f; + padding_l = padding_r = padding_t = padding_b = 0.0f; } GuiElement::GuiElement() { parent = NULL; type = DEFAULT; - x = 0.25; y = 0.25; + x = y = 0; offset_x = offset_y = 0; - w = 0.25; h = 0.25; - view = NULL; - object = NULL; + w = 32.0f; h = 32.0f; + margin_l = margin_r = margin_t = margin_b = 0.0f; + padding_l = padding_r = padding_t = padding_b = 0.0f; + object = new RenderObject(); view = NULL; pflags = 0; flags = 0; } GuiElement::~GuiElement() { if (view != NULL) delete view; + if (object != NULL) delete object; } /* ======== Relationships ======== */ int GuiElement::addChild(GuiElement *child) { + // adopt the child! + if (child->parent != NULL && child->parent != this) { + child->parent->remChild(child); + } + child->parent = this; children.push_back(child); return children.size()-1; } +int GuiElement::remChild(GuiElement *child) { + child->parent = NULL; + std::vector::iterator it; + if ((it = std::find(children.begin(), children.end(), child)) != children.end()) { + children.erase(it); + return 0; + } + return 1; +} int GuiElement::setParent(GuiElement *parent_) { parent = parent_; // TODO: detach from old parent @@ -104,7 +126,6 @@ int GuiElement::setGeometry(float x_, float y_, float w_, float h_) { x = x_; y = y_; w = w_; h = h_; //view->setView(w, h); - if (object == NULL) return 1; object->setScale(w, 1.0, h); //object->setTranslation(x, 0.0, y); object->calcMatrix(); @@ -113,7 +134,6 @@ int GuiElement::setGeometry(float x_, float y_, float w_, float h_) { void GuiElement::setSize(float width, float height) { w = width; h = height; - if (object == NULL) return; object->setScale(w, 1.0, h); //object->setTranslation(x, 0.0, y); object->calcMatrix(); @@ -130,25 +150,45 @@ void GuiElement::setOffset(float offx, float offy) { offset_x = offx; offset_y = offy; } +void GuiElement::setPadding(float l, float r, float t, float b) { + padding_l = l; + padding_r = r; + padding_t = t; + padding_b = b; +} +void GuiElement::setMargin(float l, float r, float t, float b) { + margin_l = l; + margin_r = r; + margin_t = t; + margin_b = b; +} + /* ======== Render, eugh ======== */ int GuiElement::doUpdate(int c_width, int c_height) { - float ex = x * 2; - float ey = y * 2; - if (pflags & TOP) { - ey = c_height - ey + h; - } else if (pflags & BOTTOM) { - ey = -c_height + ey - h; - } else if (pflags & VCENTER) { - ey = ey; + // if we have no parent, we manage ourselves (poorly) + if (parent == NULL) { + float off_x = x; + float off_y = y; + if (pflags & GuiElement::HCENTER) { + off_x += (c_width/2.0f) - (w/2.0f); + } else if (pflags & GuiElement::RIGHT) { + off_x += c_width - w; + } + if (pflags & GuiElement::VCENTER) { + off_y += (c_height/2.0f) - (h/2.0f); + } else if (pflags & GuiElement::BOTTOM) { + off_y += c_height - h; + } + setPosition(off_x, off_y); } - if (pflags & LEFT) { - ex = -c_width + ex - w; - } else if (pflags & RIGHT) { - ex = c_width - ex + w; - } else if (pflags & HCENTER) { - ex = ex; - } - object->setTranslation(ex, 0.0f, ey); + // mod_x and mod_y are the modifiers to get our pixel origin set to (0, 0) at the top-left of the screen + float mod_x = -c_width + w; + float mod_y = c_height - h; + // real_x and real_y are our x and y coordinates in top-left screen terms + float real_x = x*2; + float real_y = -y*2; + //mod_x -= w*2; + object->setTranslation(mod_x+real_x, 0.0f, mod_y+real_y); object->calcMatrix(); return 0; } @@ -179,11 +219,11 @@ RenderView* GuiElement::getView() { } void GuiElement::hide() { flags |= HIDDEN; - if (object != NULL) object->hide(); + object->hide(); } void GuiElement::show() { flags &= ~HIDDEN; - if (object != NULL) object->show(); + object->show(); } int GuiElement::getFlags() { return flags; diff --git a/src/gui/GuiElement.hpp b/src/gui/GuiElement.hpp index 029da99..2192cba 100644 --- a/src/gui/GuiElement.hpp +++ b/src/gui/GuiElement.hpp @@ -12,6 +12,7 @@ This file describes the GuiElement class. This is the base class for further GUI #include "RenderCamera.hpp" class GuiElement { friend class Gui; + friend class GuiList; public: enum Type { DEFAULT = 0, @@ -43,6 +44,7 @@ class GuiElement { // int setText(const char *string); GuiElement *getHit(float xhit, float yhit); int addChild(GuiElement *child); + int remChild(GuiElement *child); int setParent(GuiElement *parent); int setPFlags(int pflags); RenderView *getView(); @@ -53,22 +55,26 @@ class GuiElement { void setSize(float width, float height); void setPosition(float newx, float newy); void setOffset(float offx, float offy); + void setMargin(float l, float r, float t, float b); + void setPadding(float l, float r, float t, float b); int getFlags(); void hide(); void show(); protected: - std::vector children; // children of this element - RenderView *view; // Ugh, we use FBOs for GUI elements cuz otherwise it's too annoying. - GuiElement *parent; // parent of this element - std::string text; // text of this element int type; // flag for this type int pflags; // positioning flags int flags; // flags + std::string text; // text of this element + GuiElement *parent; // parent of this element + std::vector children; // children of this element + RenderObject *object;// render object + RenderView *view; // Ugh, we use FBOs for GUI elements cuz otherwise it's too annoying. int gid; // group id for this element int id; // id for this element - RenderObject *object;// render object, as set by manager class, Gui // float x, y, w, h; // position and dimensions for this element float offset_x, offset_y; // offset x and y + float margin_l, margin_r, margin_t, margin_b; + float padding_l, padding_r, padding_t, padding_b; }; #endif diff --git a/src/gui/GuiList.cpp b/src/gui/GuiList.cpp index f195308..3f13313 100644 --- a/src/gui/GuiList.cpp +++ b/src/gui/GuiList.cpp @@ -1,46 +1,120 @@ #include "GuiList.hpp" #include "Log.hpp" -GuiList::GuiList(std::string string) { - text.assign(string); +GuiList::GuiList(const char *name) { + text.assign(name); type = LIST; + dflags = HORIZONTAL|RIGHT; } GuiList::~GuiList() { } +int GuiList::setDFlags(int dir_flags_) { + dflags = dir_flags_; + return 0; +} int GuiList::doUpdate(int c_width, int c_height) { - float ex = x * 2; - float ey = y * 2; - if (pflags & TOP) { - ey = c_height - ey + offset_y; - } else if (pflags & BOTTOM) { - ey = -c_height + ey - offset_y; - } else if (pflags & VCENTER) { - ey = ey + offset_y; + float off_x, off_y; + int width, height; + if (parent == NULL) { + LOG(LOG_INFO) << "I yam not a child: " << text; + off_x = 0.0f; + off_y = 0.0f; + width = c_width; + height = c_height; + } else { + LOG(LOG_INFO) << "I yam a child: " << text; + off_x = parent->x; + off_y = parent->y; + width = parent->getWidth(); + height = parent->getHeight(); } - if (pflags & LEFT) { - ex = -c_width + ex + offset_x; - } else if (pflags & RIGHT) { - ex = c_width - ex - offset_x; - } else if (pflags & HCENTER) { - ex = ex + offset_x; + float coff_x = 0.0f; // center position offset for child + float coff_y = 0.0f; // ^ + if (pflags & GuiElement::HCENTER) { + off_x += width/2.0f; + } else if (pflags & GuiElement::RIGHT) { + off_x += width; + off_x -= margin_r; + } else { + off_x += margin_l; } - float off_x = offset_x*2; - float off_y = offset_y*2; + if (pflags & GuiElement::VCENTER) { + off_y += height/2.0f; + } else if (pflags & GuiElement::BOTTOM) { + off_y += height; + off_y -= margin_b; + } else { + off_y += margin_t; + } + if (parent == NULL) { + x = off_x; + y = off_y; + } + + // Set light position offsets for the first element (if one exists) if we're building the list towards a non-standard direction - this is needed for right-origin and bottom-origin position flags (so the first element isn't off-screen/out of place) GuiElement *child; + if (children.size() > 0) { + child = children.front(); + if (pflags & GuiElement::RIGHT && dflags & GuiList::LEFT) { + //off_x -= child->getWidth(); + } + if (pflags & GuiElement::BOTTOM && dflags & GuiList::UP) { + //off_y -= child->getHeight(); + } + } + std::vector::iterator element_it, element_end; for (element_it = children.begin(), element_end = children.end(); element_it != element_end; ++element_it) { child = *element_it; if (child->getFlags() & HIDDEN) continue; - off_x += (child->getWidth()*2); - off_y = child->getHeight()*2; - child->setOffset(off_x, off_y); + if (dflags & GuiList::LEFT) { + off_x -= child->getWidth(); + off_x -= child->margin_r; + } else { + off_x += child->margin_l; + } + if (dflags & GuiList::UP) { + off_y -= child->getHeight(); + off_y -= child->margin_b; + } else { + off_y += child->margin_t; + } + if (pflags & GuiList::HCENTER) { + coff_x = child->getWidth()/2.0f; + } else { + coff_x = 0.0f; + } + if (pflags & GuiList::VCENTER) { + coff_y = child->getHeight()/2.0f; + } else { + coff_y = 0.0f; + } + + child->setPosition(off_x-coff_x, off_y-coff_y); + + if (dflags & GuiList::DOWN) { + off_y += child->getHeight(); + off_y += child->margin_b; + } else { + off_y -= child->margin_t; + } + if (dflags & GuiList::RIGHT) { + off_x += child->getWidth(); + off_x += child->margin_r; + } else { + off_x -= child->margin_l; + } child->doUpdate(c_width, c_height); + setSize(off_x, off_y); + } + if (pflags & GuiList::HCENTER) { + x -= off_x/2; + } + if (pflags & GuiList::VCENTER) { + y -= off_y/2; } - setSize(off_x/2, off_y/2); - if (object == NULL) return 1; // return if we haven't been added to Gui yet - object->setTranslation(ex+offset_x, 0.0f, ey+offset_y); object->calcMatrix(); return 0; } diff --git a/src/gui/GuiList.hpp b/src/gui/GuiList.hpp index 0720ced..f4047af 100644 --- a/src/gui/GuiList.hpp +++ b/src/gui/GuiList.hpp @@ -1,12 +1,22 @@ #ifndef GUILIST_HPP #define GUILIST_HPP #include "GuiElement.hpp" -#include class GuiList : public GuiElement { public: - GuiList(std::string text); + GuiList(const char *name); ~GuiList(); - virtual int doUpdate(int c_width, int c_height); + enum DFlags { + HORIZONTAL = (1 << 1), + VERTICAL = (1 << 2), + UP = (1 << 3), + DOWN = (1 << 4), + LEFT = (1 << 5), + RIGHT = (1 << 6) + }; + int doUpdate(int c_width, int c_height); + int setDFlags(int dir_flags_); + private: + int dflags; }; #endif diff --git a/src/states/MenuState.cpp b/src/states/MenuState.cpp index 773dafd..e3841b7 100644 --- a/src/states/MenuState.cpp +++ b/src/states/MenuState.cpp @@ -1,7 +1,12 @@ #include "MenuState.hpp" +#include "Log.hpp" +#include "Core.hpp" +#include "GuiElement.hpp" +#include "GuiList.hpp" +#include "GuiButton.hpp" /* ======== Construction and Destruction ======== */ MenuState::MenuState() { - + camera = NULL; } MenuState::~MenuState() { @@ -14,11 +19,70 @@ int MenuState::onEvent(SDL_Event event) { return 0; } int MenuState::onCede() { + gui->delElement("menu"); return 0; } int MenuState::onRise() { + // Get our services + gui = core.getGui(); + scene = core.getScene(); + asset_manager = core.getAssetManager(); + // We recreate everything cuz why not + // ** CAMERA CREATION ** + /*camera = new RenderCamera(); + camera->setRenderView(new RenderView(width, height)); + camera->updateProjection(width, height); + camera->setPitch(80.0f); + camera->setPosition(0, 30, 0); + camera->doRefresh(); + + scene->addCamera(camera);*/ + + // create our menu list + GuiList *glist = new GuiList("menu"); + glist->setPFlags(GuiElement::TOP|GuiElement::HCENTER); + glist->setDFlags(GuiList::DOWN); + glist->setGeometry(0.0f, 64.0f, 0.0f, 0.0f); + // Add our menu logo + GuiButton *gbutton = new GuiButton("logo", core.getTexture("ui/icon_isocube.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 128.0f); + glist->addChild(gbutton); + // Add our Create button + gbutton = new GuiButton("Create", core.getTexture("ui/icon_token.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 128.0f); + glist->addChild(gbutton); + // Add our Join button + gbutton = new GuiButton("Join", core.getTexture("ui/icon_token.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 8.0f); + glist->addChild(gbutton); + // Add our Quit button + gbutton = new GuiButton("Quit", core.getTexture("ui/icon_token.png")); + gbutton->setGeometry(0.0f, 0.0f, 64.0f, 64.0f); + glist->addChild(gbutton); + // Add our entire list + GuiList* glist2 = new GuiList("menu2"); + glist2->setPFlags(GuiElement::LEFT|GuiElement::TOP); + glist2->setDFlags(GuiList::RIGHT); + gbutton = new GuiButton("Quit", core.getTexture("ui/icon_perscube.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 128.0f); + glist2->addChild(gbutton); + gbutton = new GuiButton("Quit2", core.getTexture("ui/icon_perscube.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 128.0f); + glist2->addChild(gbutton); + gbutton = new GuiButton("Quit3", core.getTexture("ui/icon_perscube.png")); + gbutton->setGeometry(0.0f, 0.0f, 128.0f, 128.0f); + glist2->addChild(gbutton); + + glist->addChild(glist2); + // Add our entire list + gui->addElement(glist); + // manual update + gui->updateElements(); + + // ** PROGRAM LOADING ** return 0; } int MenuState::onInit() { + return 0; } diff --git a/src/states/MenuState.hpp b/src/states/MenuState.hpp index 8172789..43a4ab0 100644 --- a/src/states/MenuState.hpp +++ b/src/states/MenuState.hpp @@ -6,6 +6,9 @@ MenuState.cpp/MenuState.hpp provide the Main Menu state that the program first a #ifndef MENUSTATE_HPP #define MENUSTATE_HPP #include "State.hpp" +#include "RenderScene.hpp" +#include "AssetManager.hpp" +#include "Gui.hpp" class MenuState : public State { friend class Core; public: @@ -17,5 +20,11 @@ class MenuState : public State { virtual int onInit(); virtual int onCede(); virtual int onRise(); + private: + Program *menu_program; + RenderScene *scene; + RenderCamera *camera; + AssetManager *asset_manager; + Gui *gui; }; #endif diff --git a/src/states/TestState.cpp b/src/states/TestState.cpp index 31b8eef..755518e 100644 --- a/src/states/TestState.cpp +++ b/src/states/TestState.cpp @@ -26,6 +26,7 @@ int TestState::onEvent(SDL_Event event) { if (event.type == SDL_MULTIGESTURE) { LOG(LOG_INFO) << "gesture: " << event.mgesture.x << "x" << event.mgesture.y << ", rot:" << event.mgesture.dTheta << ", pinch:" << event.mgesture.dDist << ", fingers:" << event.mgesture.numFingers; RenderCamera *camera = scene->getCamera(1); + if (camera == NULL) return 0; Vec3 camera_pos = camera->getPosition(); camera_pos.y -= event.mgesture.dDist*128.0f; @@ -39,6 +40,7 @@ int TestState::onEvent(SDL_Event event) { LOG(LOG_INFO) << "finger: " << event.tfinger.fingerId << " " << event.tfinger.x << "x" << event.tfinger.y << " " << event.tfinger.dx << "x" << event.tfinger.dy; RenderCamera *camera = scene->getCamera(1); + if (camera == NULL) return 0; Vec3 camera_pos = camera->getPosition(); int width = core.getWidth(); int height = core.getHeight(); @@ -58,6 +60,7 @@ int TestState::onEvent(SDL_Event event) { } else if (event.type == SDL_MOUSEMOTION && event.motion.which != SDL_TOUCH_MOUSEID) { LOG(LOG_INFO) << "mouse motion: " << event.motion.xrel << "x" << event.motion.yrel << " "; RenderCamera *camera = scene->getCamera(1); + if (camera == NULL) return 0; if (event.motion.state & SDL_BUTTON_MMASK) { camera->setYaw(camera->getYaw() - event.motion.xrel); } else if (event.motion.state & SDL_BUTTON_RMASK) { @@ -75,6 +78,7 @@ int TestState::onEvent(SDL_Event event) { camera->doRefresh(); } else if (event.type == SDL_MOUSEWHEEL) { RenderCamera *camera = scene->getCamera(1); + if (camera == NULL) return 0; Vec3 camera_pos = camera->getPosition(); camera_pos.y -= event.wheel.y; camera->setPosition(camera_pos.x, camera_pos.y, camera_pos.z); @@ -82,6 +86,7 @@ int TestState::onEvent(SDL_Event event) { } else if (event.type == SDL_KEYUP) { if (event.key.keysym.sym == SDLK_SPACE) { RenderCamera *camera = scene->getCamera(1); + if (camera == NULL) return 0; if (camera->getRenderMode() == 0) { camera->setRenderMode(1); } else { @@ -104,29 +109,9 @@ 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 - std::string shader_file; - shader_file = "shaders/" + core.shader_version + "/fb_fs.glsl"; - Asset *shader_asset = asset_manager->loadFile(shader_file.c_str()); - if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_FRAGMENT_SHADER) != 0) { - LOG(LOG_ERROR) << "Failed to add Shader!"; - return 1; - } - shader_asset->unloadData(); - shader_file = "shaders/" + core.shader_version + "/fb_vs.glsl"; - shader_asset = asset_manager->loadFile(shader_file.c_str()); - if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_VERTEX_SHADER) != 0) { - LOG(LOG_ERROR) << "Failed to add Shader!"; - return 1; - } - shader_asset->unloadData(); - if (program->doCompile() != 0) { - LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; - return 1; - } // TEMP: our model rendering program + std::string shader_file; + Asset *shader_asset; Program *program_model = new Program(); shader_file = "shaders/" + core.shader_version + "/default_fs.glsl"; shader_asset = asset_manager->loadFile(shader_file.c_str()); @@ -157,9 +142,11 @@ int TestState::onInit() { camera->setPosition(0, 30, 0); camera->doRefresh(); - scene->addCamera(camera); + //scene->addCamera(camera); + + Program *program = core.getProgram("fb"); - program->attachTexture(0, camera->getRenderView()->getTex()); + //program->attachTexture(0, camera->getRenderView()->getTex()); (camera->getRenderView()->setProgram(program));