/* ================================================================ 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" #include "RenderSet.hpp" #include "RenderObject.hpp" #include "Mesh.hpp" #include "Texture.hpp" Gui::Gui() { w = core.getWidth(); h = core.getHeight(); scene = new RenderScene(); camera = new RenderCamera(); camera->setRenderMode(1); // Use orthographic mode camera->setPitch(90.0f); // look down camera->setPosition(0, 0, 0); camera->setNear(-1.0f); camera->setFar(1.0f); camera->setRenderFlags(RenderCamera::CLEAR_DEPTH); // only clear the depth before rendering camera->setRenderView(core.getWindowView()); // set the camera's render view to point to the main render view camera->setSize(h*2); // set our vertical size to the height of the window - this means 1 unit will correspond to 1 pixel camera->updateProjection(w, h); // ensure our projection is good camera->doRefresh(); // aaand update scene->addCamera(camera); // This is a strange thing - we use this camera for the rendering of all children. The children modify it to match their render dimensions (so that 1 unit == 1px) child_camera = new RenderCamera(); child_camera->setRenderMode(1); // Use orthographic mode child_camera->setPitch(90.0f); // look down child_camera->setPosition(0, 0, 0); child_camera->setNear(-1.0f); child_camera->setFar(1.0f); child_camera->setRenderFlags(RenderCamera::CLEAR_DEPTH); // only clear the depth before rendering child_camera->setRenderView(core.getWindowView()); // set the child_camera's render view to point to the main render view child_camera->setSize(h*2); // set our vertical size to the height of the window - this means 1 unit will correspond to 1 pixel child_camera->updateProjection(w, h); // ensure our projection is good child_camera->doRefresh(); // aaand update // asset_manager = core.getAssetManager(); // compile our GUI program std::string shader_file; Asset* shader_asset; program = new Program(); shader_file = "shaders/" + core.shader_version + "/gui_fs.glsl"; shader_asset = asset_manager->loadFile(shader_file.c_str()); if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_FRAGMENT_SHADER) != 0) { //return 1; } shader_asset->unloadData(); shader_file = "shaders/" + core.shader_version + "/gui_vs.glsl"; shader_asset = asset_manager->loadFile(shader_file.c_str()); if (program->addShader(shader_asset->getData(), shader_asset->getDataLength(), GL_VERTEX_SHADER) != 0) { // return 1; } shader_asset->unloadData(); if (program->doCompile() != 0) { // return 1; } set_basic = new RenderSet(); // create a new basic render set set_basic->setProgram(program); // set the set's program to gui_* scene->addSet(set_basic); // add set to the scene // load and build our basic element mesh Asset *asset = asset_manager->loadFile("models/plane.obj"); element_mesh = new Mesh(asset->getData(), asset->getDataLength()); element_mesh->buildMesh(); asset->unloadData(); } Gui::~Gui() { delete camera; delete scene; GuiElement *element = NULL; std::vector::iterator element_it, element_end; for (element_it = elements.begin(), element_end = elements.end(); element_it != element_end; ++element_it) { element = *element_it; delete element; } } /* 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); y = float(event.button.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) { if ((*element_it)->getFlags() & GuiElement::HIDDEN) continue; element = (*element_it)->getHit(x, y); if (element != NULL) break; } break; case SDL_FINGERDOWN: case SDL_FINGERUP: x = event.tfinger.x * core.getWidth(); y = event.tfinger.y * 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) { if ((*element_it)->getFlags() & GuiElement::HIDDEN) continue; 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) { // if (element->object == NULL && !(element->type & GuiElement::LIST)) { element->object = new RenderObject(); element->object->setMesh(element_mesh); set_basic->addObject(element->object); if (element->flags & GuiElement::HIDDEN) element->object->hide(); // FIXME: calling this here for now element->setGeometry(element->x, element->y, element->w, element->h); } //element->view = new RenderView(element->w, element->h); // Add the children as well std::vector::iterator element_it, element_end; for (element_it = element->children.begin(), element_end = element->children.end(); element_it != element_end; ++element_it) { addElement(*element_it); } /*// 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; }*/ if (element->parent == NULL) { elements.push_back(element); LOG(LOG_INFO) << FUNC_NAME << " added element " << element->text; } return elements.size()-1; } int Gui::setView(int width, int height) { w = width; h = height; camera->setSize(h*2); // update vertical size camera->updateProjection(w, h); // update projection camera->doRefresh(); // resize and position elements updateElements(); return 0; } int Gui::getWidth() { return w; } int Gui::getHeight() { return h; } RenderCamera* Gui::getChildCamera() { return child_camera; } void Gui::updateElements() { std::vector::iterator element_it, element_end; GuiElement *p_element = NULL; GuiElement *c_element = NULL; for (element_it = elements.begin(), element_end = elements.end(); element_it != element_end; ++element_it) { p_element = *element_it; if (p_element->getFlags() & GuiElement::HIDDEN) continue; p_element->doUpdate(w, h); } } int Gui::doRender() { scene->doRender(); return 0; } Program* Gui::getProgram() { return program; }