#include #include #include #include #include #include #include #include #include #include #include "src/terrain/terrain.h" #include "water/water.h" class App; class SkyRenderer : public Ogre::SceneManager::Listener { protected: Ogre::SceneManager *mSceneManager; virtual void _updateRenderQueue(Ogre::RenderQueue *queue) = 0; public: enum BoxPlane { BP_FRONT = 0, BP_BACK = 1, BP_LEFT = 2, BP_RIGHT = 3, BP_UP = 4, BP_DOWN = 5 }; SkyRenderer(Ogre::SceneManager *owner) : mSceneManager(owner) , mSceneNode(0) , mEnabled(false) { } virtual ~SkyRenderer() { setEnabled(false); if (mSceneNode) mSceneManager->destroySceneNode(mSceneNode); } Ogre::SceneNode *mSceneNode; bool mEnabled; void setEnabled(bool enable) { if (enable == mEnabled) return; mEnabled = enable; enable ? mSceneManager->addListener(this) : mSceneManager->removeListener(this); } void postFindVisibleObjects(Ogre::SceneManager *source, Ogre::SceneManager::IlluminationRenderStage irs, Ogre::Viewport *vp) override { // Queue skies, if viewport seems it if (!vp->getSkiesEnabled() || irs == Ogre::SceneManager::IRS_RENDER_TO_TEXTURE) return; if (!mEnabled || !mSceneNode) return; // Update nodes // Translate the box by the camera position (constant distance) mSceneNode->setPosition(vp->getCamera()->getDerivedPosition()); _updateRenderQueue(source->getRenderQueue()); } }; class SkyBoxRenderer : public SkyRenderer { std::unique_ptr mSkyBoxObj; Ogre::Quaternion mSkyBoxOrientation; void _updateRenderQueue(Ogre::RenderQueue *queue) override { if (mSkyBoxObj->isVisible()) { mSkyBoxObj->_updateRenderQueue(queue); } } public: SkyBoxRenderer(Ogre::SceneManager *owner) : SkyRenderer(owner) { } Ogre::SceneManager::SkyBoxGenParameters mSkyBoxGenParameters; void create(const Ogre::String &materialName, Ogre::Real distance, uint8_t renderQueue, const Ogre::Quaternion &orientation, const Ogre::String &groupName) { Ogre::MaterialPtr m = Ogre::MaterialManager::getSingleton().getByName( materialName, groupName); OgreAssert(m, "Sky box material '" + materialName + "' not found."); // Ensure loaded m->load(); bool valid = m->getBestTechnique() && m->getBestTechnique()->getNumPasses(); #if 0 if (valid) { Pass *pass = m->getBestTechnique()->getPass(0); valid = valid && pass->getNumTextureUnitStates() && pass->getTextureUnitState(0)->getTextureType() == TEX_TYPE_CUBE_MAP; } if (!valid) { LogManager::getSingleton().logWarning( "skybox material " + materialName + " is not supported, defaulting"); m = MaterialManager::getSingleton().getDefaultSettings(); } #endif OgreAssert(valid, "Bad material" + materialName); // Create node mSceneNode = mSceneManager->createSceneNode(); // Create object mSkyBoxObj = std::make_unique("SkyBox"); mSkyBoxObj->setCastShadows(false); mSceneNode->attachObject(mSkyBoxObj.get()); mSkyBoxObj->setRenderQueueGroup(renderQueue); mSkyBoxObj->begin(materialName, Ogre::RenderOperation::OT_TRIANGLE_STRIP, groupName); // rendering cube, only using 14 vertices const Ogre::Vector3 cube_strip[14] = { { -1.f, 1.f, 1.f }, // Front-top-left { 1.f, 1.f, 1.f }, // Front-top-right { -1.f, -1.f, 1.f }, // Front-bottom-left { 1.f, -1.f, 1.f }, // Front-bottom-right { 1.f, -1.f, -1.f }, // Back-bottom-right { 1.f, 1.f, 1.f }, // Front-top-right { 1.f, 1.f, -1.f }, // Back-top-right { -1.f, 1.f, 1.f }, // Front-top-left { -1.f, 1.f, -1.f }, // Back-top-left { -1.f, -1.f, 1.f }, // Front-bottom-left { -1.f, -1.f, -1.f }, // Back-bottom-left { 1.f, -1.f, -1.f }, // Back-bottom-right { -1.f, 1.f, -1.f }, // Back-top-left { 1.f, 1.f, -1.f } // Back-top-right }; for (const auto &vtx : cube_strip) { mSkyBoxObj->position(orientation * (vtx * distance)); // Note UVs mirrored front/back mSkyBoxObj->textureCoord(vtx.normalisedCopy() * Ogre::Vector3(1, 1, -1)); } mSkyBoxObj->end(); mSkyBoxGenParameters.skyBoxDistance = distance; } }; class EditUI : public Ogre::RenderTargetListener { App *m_app; Ogre::SceneManager *mScnMgr; Ogre::ImGuiOverlay *mGuiOverlay; OgreBites::ImGuiInputListener *mGuiListener; void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override { preview(evt); } public: EditUI(App *app) : Ogre::RenderTargetListener() , m_app(app) { } void position_editor(Ogre::SceneNode *node) { Ogre::Vector3 position = node->getPosition(); float v[3] = { position.x, position.y, position.z }; ImGui::InputFloat3("position", v); position.x = v[0]; position.y = v[1]; position.z = v[2]; node->setPosition(position); } void orientation_editor(Ogre::SceneNode *node) { Ogre::Quaternion q = node->getOrientation(); float yaw = Ogre::Radian(q.getYaw()).valueDegrees(); float pitch = Ogre::Radian(q.getPitch()).valueDegrees(); float roll = Ogre::Radian(q.getRoll()).valueDegrees(); bool m1 = ImGui::InputFloat("yaw", &yaw); bool m2 = ImGui::InputFloat("pitch", &pitch); bool m3 = ImGui::InputFloat("roll", &roll); if (m1 || m2 || m3) { Ogre::Quaternion q1(Ogre::Radian(Ogre::Degree(yaw)), Ogre::Vector3::UNIT_Y); Ogre::Quaternion q2(Ogre::Degree(pitch), Ogre::Vector3::UNIT_X); Ogre::Quaternion q3(Ogre::Degree(roll), Ogre::Vector3::UNIT_Z); node->setOrientation(q1 * q2 * q3); } } void attachments_editor(Ogre::SceneNode *node) { const Ogre::SceneNode::ObjectMap &pmap = node->getAttachedObjects(); int i; for (i = 0; i < pmap.size(); i++) { const Ogre::MovableObject *mobj = pmap[i]; const Ogre::String &pname = mobj->getName(); ImGui::Text("Name: %s", pname.c_str()); } } std::vector glb_names; void init_glb_list() { int i; const std::vector &groups = Ogre::ResourceGroupManager::getSingleton() .getResourceGroups(); for (i = 0; i < groups.size(); i++) { std::vector names = *Ogre::ResourceGroupManager::getSingleton() .findResourceNames(groups[i], "*.glb"); glb_names.insert(glb_names.end(), names.begin(), names.end()); } } void buildings_editor(); void buttons_panel(); void preview(const Ogre::RenderTargetViewportEvent &evt); float panel_width; void initGui(); }; class App : public OgreBites::ApplicationContext { std::unique_ptr mDynWorld; std::unique_ptr mDbgDraw; Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal; Ogre::Camera *mCamera; Ogre::Real mPivotPitch; Ogre::SceneManager *mScnMgr; OgreBites::InputListenerChain mInput; Ogre::Viewport *mViewport; EditUI m_edit_ui; TerrainSetup m_terrain; Ogre::Light *mSun; SkyBoxRenderer *sky; Water m_water; // OgreBites::TrayManager *mTrayMgr; class KeyboardListener : public OgreBites::InputListener, public Ogre::FrameListener { App *mApp; public: Ogre::Vector3 motion; bool gui_active; Ogre::Timer fps_timer; bool fast; KeyboardListener(App *app) : OgreBites::InputListener() , Ogre::FrameListener() , mApp(app) , gui_active(false) , fast(false) { } bool keyPressed(const OgreBites::KeyboardEvent &evt) override { if (gui_active) return false; if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) { gui_active = true; // std::cout << "Escape!\n"; // Ogre::Root::getSingleton().queueEndRendering(); mApp->setWindowGrab(false); } if (evt.keysym.sym == 'w') motion.z = -1.0f; if (evt.keysym.sym == 's') motion.z = 1.0f; if (evt.keysym.sym == 'a') motion.x = -1.0f; if (evt.keysym.sym == 'd') motion.x = 1.0f; if (evt.keysym.sym == OgreBites::SDLK_LSHIFT) fast = true; // std::cout << "motion: " << motion << "\n"; return true; } bool keyReleased(const OgreBites::KeyboardEvent &evt) override { if (gui_active) return false; if (evt.keysym.sym == 'w' && motion.z < 0.0f) motion.z = 0.0f; if (evt.keysym.sym == 's' && motion.z > 0.0f) motion.z = 0.0f; if (evt.keysym.sym == 'a' && motion.x < 0.0f) motion.x = 0.0f; if (evt.keysym.sym == 'd' && motion.x > 0.0f) motion.x = 0.0f; if (evt.keysym.sym == OgreBites::SDLK_LSHIFT) fast = false; return true; } bool mouseMoved(const OgreBites::MouseMotionEvent &evt) { if (gui_active) return false; // update camera goal based on mouse movement mApp->updateCameraGoal(-0.18f * evt.xrel, -0.12f * evt.yrel, 0); return true; } bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) { if (gui_active) return false; // update camera goal based on mouse movement mApp->updateCameraGoal(0, 0, -0.15f * evt.y); return true; } void update(float delta) { return; // float fade = (1.0f - delta) * 0.98f; // motion *= fade; } void frameRendered(const Ogre::FrameEvent &evt) override { if (fps_timer.getMilliseconds() > 1000.0f) { std::cout << "FPS: " << mApp->getRenderWindow() ->getStatistics() .lastFPS << " "; std::cout << "Draw calls: " << mApp->getRenderWindow() ->getStatistics() .batchCount << " "; fps_timer.reset(); std::cout << "Drops: " << mApp->getRenderWindow() ->getStatistics() .vBlankMissCount << "\n"; fps_timer.reset(); } update(evt.timeSinceLastFrame); if (!gui_active) { mApp->updateMotion(evt.timeSinceLastFrame); mApp->updateCamera(evt.timeSinceLastFrame); mApp->updateSun(evt.timeSinceLastFrame); mApp->updateTerrain(evt.timeSinceLastFrame); } } }; KeyboardListener mKbd; public: App() : OgreBites::ApplicationContext("GuiTest") , mKbd(this) , m_edit_ui(this) , mDynWorld(new Ogre::Bullet::DynamicsWorld( Ogre::Vector3(0, -9.8, 0))) , m_terrain(mDynWorld->getBtWorld()) { } virtual ~App() { } void setup() { OgreBites::ApplicationContext::setup(); Ogre::Root *root = getRoot(); Ogre::SceneManager *scnMgr = root->createSceneManager(); mScnMgr = scnMgr; Ogre::OverlaySystem *pOverlaySystem = getOverlaySystem(); mScnMgr->addRenderQueueListener(pOverlaySystem); // mTrayMgr = new OgreBites::TrayManager("AppTrays", // getRenderWindow()); mDbgDraw.reset(new Ogre::Bullet::DebugDrawer( mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld())); } void locateResources() { OgreBites::ApplicationContext::locateResources(); } void initCamera() { mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode( "CameraNode"); mCameraNode->setPosition(0, 2, 3); mCameraNode->lookAt(Ogre::Vector3(0, 1, -1), Ogre::Node::TS_PARENT); // create the camera mCamera = mScnMgr->createCamera("fps_camera"); mCamera->setNearClipDistance(0.05f); mCamera->setAutoAspectRatio(true); mCameraNode->attachObject(mCamera); // and tell it to render into the main window mViewport = getRenderWindow()->addViewport(mCamera); mCameraPivot = mScnMgr->getRootSceneNode()->createChildSceneNode( "FPSCameraPivot"); mCameraGoal = mCameraPivot->createChildSceneNode( "FPSCameraGoal", Ogre::Vector3(0, 2, 3)); mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition()); mCameraPivot->setFixedYawAxis(true); mCameraGoal->setFixedYawAxis(true); mCameraNode->setFixedYawAxis(true); // our model is quite small, so reduce the clipping planes mCamera->setNearClipDistance(0.1f); mCamera->setFarClipDistance(800); mPivotPitch = 0; // mKeyDirection = Ogre::Vector3::ZERO; // mVerticalVelocity = 0; Ogre::ManualObject *mobj = mScnMgr->createManualObject("cursorGen"); #if 0 Ogre::MaterialPtr mat = Ogre::static_pointer_cast( Ogre::MaterialManager::getSingleton() .createOrRetrieve("Debug/Red2", "General") .first); mat->removeAllTechniques(); Ogre::Technique *tech = mat->createTechnique(); tech->setDiffuse(Ogre::ColourValue(1, 0, 0, 1)); tech->setName("Debug/S"); tech->setDepthCheckEnabled(false); tech->setLightingEnabled(false); mobj->begin(mat, Ogre::RenderOperation::OT_LINE_LIST); #endif mobj->begin("Debug/Red", Ogre::RenderOperation::OT_LINE_LIST); mobj->position(0, 0, 0); mobj->colour(Ogre::ColourValue(1, 0, 0)); mobj->position(0, 2, 0); mobj->colour(Ogre::ColourValue(1, 0, 0)); mobj->position(-1, 1, 0); mobj->colour(Ogre::ColourValue(1, 0, 0)); mobj->position(1, 1, 0); mobj->colour(Ogre::ColourValue(1, 0, 0)); mobj->index(0); mobj->index(1); mobj->index(2); mobj->index(3); mobj->end(); mCameraPivot->attachObject(mobj); } Ogre::SceneManager *getSceneManager() { return mScnMgr; } void updateMotion(float delta) { if (delta == 0.0f) return; Ogre::Vector3 move(mCameraNode->getOrientation().zAxis() * mKbd.motion.z); move += Ogre::Vector3(mCameraNode->getOrientation().xAxis() * mKbd.motion.x); move.y = 0.0f; float speed = 15.0f; if (mKbd.fast) speed = 40.0f; Ogre::Vector3 opos = mCameraPivot->getPosition(); Ogre::Vector3 pos = mCameraPivot->getPosition() + move * speed * delta; float y = m_terrain.get_height(pos); pos.y = y; mCameraPivot->translate(pos - opos); // mKbd.motion = Ogre::Vector3(0, 0, 0); // if (move.squaredLength() > 0) // std::cout << move << "\n"; } void updateCamera(Ogre::Real delta) { if (delta == 0.0f) return; // place the camera pivot roughly at the character's shoulder // mCameraPivot->setPosition(mBodyNode->getPosition() + // Ogre::Vector3::UNIT_Y * CAM_HEIGHT); // move the camera smoothly to the goal Ogre::Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition(); float l = goalOffset.squaredLength(); Ogre::Vector3 v = goalOffset * 10.0 * delta; if (v.squaredLength() > l * 0.5f - delta) v = goalOffset * delta; mCameraNode->translate(v); // mCameraNode->translate(goalOffset); // always look at the pivot mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Ogre::Node::TS_PARENT); } void updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom) { mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_PARENT); if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) && !(mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) { mCameraPivot->pitch(Ogre::Degree(deltaPitch), Ogre::Node::TS_LOCAL); mPivotPitch += deltaPitch; } Ogre::Real dist = mCameraGoal->_getDerivedPosition().distance( mCameraPivot->_getDerivedPosition()); Ogre::Real distChange = deltaZoom * dist * 0.5f; if (distChange > 0 && dist + distChange > 30) distChange *= 0.3f; if (distChange < 0 && dist + distChange < 5) distChange *= 0.2f; // bound the zoom if (!(dist + distChange < 3 && distChange < 0) && !(dist + distChange > 60 && distChange > 0)) mCameraGoal->translate(0, 0, distChange, Ogre::Node::TS_LOCAL); Ogre::Vector3 mh = mCameraGoal->_getDerivedPosition(); float h = m_terrain.get_height(mh); if (h + 10 > mh.y) mCameraGoal->translate(0, 10.0f * deltaZoom, distChange, Ogre::Node::TS_LOCAL); } Ogre::SceneNode *mSunGoal; Ogre::SceneNode *mSunNode; Ogre::SceneNode *mSunTarget; Ogre::Timer mSunUpdate; void createSun() { Ogre::Light *light = mScnMgr->createLight("Sun"); mSunNode = mScnMgr->getRootSceneNode()->createChildSceneNode( "SunPivot"); mSunGoal = mScnMgr->getRootSceneNode()->createChildSceneNode( "SunGoal"); mSunTarget = mSunGoal->createChildSceneNode( "SunGoalTarget", Ogre::Vector3(100.0f, -400.0f, -400.0f), Ogre::Quaternion::IDENTITY); // mSunNode->setAutoTracking(true, sun_target); // lightNode->setPosition(0, 10, 15); mSunNode->attachObject(light); light->setType(Ogre::Light::LT_DIRECTIONAL); light->setDiffuseColour(Ogre::ColourValue::White); light->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4)); mSunNode->setDirection(Ogre::Vector3(100.0f, -400.0f, -400.f)); mSun = light; } void updateSun(float delta) { static const float sun_speed = 1.0f; float uangle = M_PI * 2.0f / 24.0f / 60.0f; mSunNode->pitch(Ogre::Radian(uangle) * sun_speed * delta); if (mSunUpdate.getMilliseconds() > 1000) { Ogre::TerrainGlobalOptions::getSingleton() .setCompositeMapAmbient( mScnMgr->getAmbientLight()); Ogre::TerrainGlobalOptions::getSingleton() .setCompositeMapDiffuse( mSun->getDiffuseColour()); Ogre::TerrainGlobalOptions::getSingleton() .setLightMapDirection( mSun->getDerivedDirection()); std::cout << "sun pitch: " << mSunNode->getOrientation().getPitch() << "\n"; mSunUpdate.reset(); } if (mSunNode->getOrientation().getPitch().valueRadians() > 0) mScnMgr->setAmbientLight( Ogre::ColourValue(0.0f, 0.0f, 0.2f, 1.0f)); else mScnMgr->setAmbientLight( Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f)); } Ogre::Timer mTerrainUpd; void updateTerrain(float delta) { mDbgDraw->update(); #if 0 if (mTerrainUpd.getMilliseconds() > 1000) { m_terrain.create_colliders(); mTerrainUpd.reset(); } #endif } void createContent() { int i; m_edit_ui.init_glb_list(); m_edit_ui.initGui(); createSun(); mInput = OgreBites::InputListenerChain( { getImGuiInputListener(), &mKbd }); addInputListener(&mInput); getRoot()->addFrameListener(&mKbd); // mTrayMgr->showCursor(); // OgreBites::TrayManager *mTrayMgr = new OgreBites::TrayManager( // "InterfaceName", getRenderWindow()); // mScnMgr->setSkyBox(true, "Skybox/Dynamic", 490); // /* mCamera->getCameraToViewportRay(left, top); */ sky = new SkyBoxRenderer(getSceneManager()); bool drawFirst = true; uint8_t renderQueue = drawFirst ? Ogre::RENDER_QUEUE_SKIES_EARLY : Ogre::RENDER_QUEUE_SKIES_LATE; sky->create("Skybox/Dynamic", 450, renderQueue, Ogre::Quaternion::IDENTITY, Ogre::ResourceGroupManager:: AUTODETECT_RESOURCE_GROUP_NAME); sky->setEnabled(true); Ogre::MaterialPtr m = Ogre::MaterialManager::getSingleton().getByName( "Skybox/Dynamic", "General"); OgreAssert(m, "Sky box material not found."); m->load(); m_water.createWater(mCamera); getRoot()->addFrameListener(&m_water); } void create_entity_node(const Ogre::String &name, int key) { Ogre::Entity *ent = mScnMgr->createEntity(name); Ogre::SceneNode *pnode = mScnMgr->getRootSceneNode()->createChildSceneNode( "ent:" + name + Ogre::StringConverter::toString(key), mCameraPivot->getPosition(), mCameraPivot->getOrientation()); pnode->attachObject(ent); Ogre::Quaternion q = pnode->getOrientation(); Ogre::Radian yaw = q.getYaw(); Ogre::Quaternion nq(yaw, Ogre::Vector3(0, 1, 0)); pnode->setOrientation(nq); mKbd.gui_active = false; setWindowGrab(true); } bool get_gui_active() { return mKbd.gui_active; } void set_gui_active(bool active) { mKbd.gui_active = active; } Ogre::Camera *getCamera() { return mCamera; } void setupTerrain() { m_terrain.setupTerrain(mCamera, mSun, mDynWorld.get(), mDbgDraw.get()); } }; void EditUI::buildings_editor() { int i; ImVec2 size = ImGui::GetMainViewport()->Size; float window_width = size.x * 0.2f; if (window_width > panel_width) window_width = panel_width; float window_height = size.y * 0.5 - 20; ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(window_width, window_height), ImGuiCond_Always); ImGui::Begin("Droppings..."); for (i = 0; i < glb_names.size(); i++) { Ogre::String id_button = "Create entity: " + glb_names[i] + "##ent:" + glb_names[i]; if (ImGui::Button(id_button.c_str())) { m_app->create_entity_node(glb_names[i], i); } } ImGui::End(); } void EditUI::buttons_panel() { ImVec2 size = ImGui::GetMainViewport()->Size; float window_width = size.x * 0.2f; if (window_width > panel_width) window_width = panel_width; float window_height = size.y * 0.5f - 20; ImGui::SetNextWindowPos(ImVec2(0, size.y * 0.5f + 20), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(window_width, window_height), ImGuiCond_Always); ImGui::Begin("Dumb and Stupid"); if (!m_app->get_gui_active()) m_app->setWindowGrab(true); if (ImGui::Button("Shitty Quit button")) Ogre::Root::getSingleton().queueEndRendering(); if (ImGui::Button("Chick-chick")) { m_app->set_gui_active(false); m_app->setWindowGrab(true); } ImGui::Text("We do stoopid..."); ImGui::End(); } void EditUI::preview(const Ogre::RenderTargetViewportEvent &evt) { int i; Ogre::ImGuiOverlay::NewFrame(); if (m_app->get_gui_active()) { buttons_panel(); buildings_editor(); ImVec2 size = ImGui::GetMainViewport()->Size; float window_width = size.x * 0.2f; if (window_width > panel_width) window_width = panel_width; float window_height = size.y * 0.5f - 20; ImGui::SetNextWindowPos(ImVec2(size.x - window_width, size.y * 0.5f + 20), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(window_width, window_height), ImGuiCond_Always); // ImGui::Begin("Dumb and Stupid", &mKbd.gui_active); ImGui::Begin("Panel..."); std::deque tree_input_queue, tree_output_queue; std::vector tree_list; tree_input_queue.push_back(mScnMgr->getRootSceneNode()); tree_input_queue.push_back(nullptr); std::set visited; while (true) { int new_nodes_count = 0; while (!tree_input_queue.empty()) { int child; Ogre::SceneNode *item = tree_input_queue.front(); tree_input_queue.pop_front(); if (item && visited.find(item) == visited.end()) { // new node new_nodes_count++; tree_output_queue.push_back(item); visited.insert(item); const Ogre::Node::ChildNodeMap &children = item->getChildren(); for (child = 0; child < children.size(); child++) { tree_output_queue.push_back( static_cast( children[child])); tree_output_queue.push_back( nullptr); } } else tree_output_queue.push_back(item); } if (new_nodes_count == 0) break; tree_input_queue = tree_output_queue; tree_output_queue.clear(); } tree_list.insert(tree_list.begin(), tree_output_queue.begin(), tree_output_queue.end()); int count = 0; int depth = 0; std::vector check_depth; int max_depth = 0; check_depth.push_back(0); for (count = 0; count < tree_list.size(); count++) { int t; Ogre::SceneNode *node = tree_list[count]; if (node && max_depth >= depth) { Ogre::String name = node->getName(); if (name.length() == 0) { name = "Node #" + Ogre::StringConverter::toString( count); } if (ImGui::TreeNode(name.c_str())) { check_depth.push_back(max_depth); max_depth++; ImGui::Text( "%s", (name + "##caption").c_str()); position_editor(node); ImGui::Separator(); orientation_editor(node); ImGui::Separator(); ImGui::Text("Attachments"); attachments_editor(node); } } else if (!node && max_depth >= depth) { max_depth = check_depth.back(); check_depth.pop_back(); ImGui::TreePop(); } if (tree_list[count]) depth++; else depth--; } ImGui::Spacing(); ImGui::End(); } } void EditUI::initGui() { mScnMgr = m_app->getSceneManager(); float vpScale = m_app->getDisplayDPI() / 96 * (float)m_app->getRenderWindow()->getWidth() / 1280; panel_width = 380.0f * (float)m_app->getRenderWindow()->getWidth() / 1280; Ogre::OverlayManager::getSingleton().setPixelRatio(vpScale); mGuiOverlay = m_app->initialiseImGui(); // float vpScale = // Ogre::OverlayManager::getSingleton().getPixelRatio(); ImGui::GetIO().FontGlobalScale = std::round(vpScale); mGuiOverlay->setZOrder(300); mGuiOverlay->show(); m_app->getRenderWindow()->addListener(this); } int main() { App ctx; ctx.initApp(); // ctx.runRenderingSettingsDialog(); // get a pointer to the already created root Ogre::Root *root = ctx.getRoot(); Ogre::SceneManager *scnMgr = ctx.getSceneManager(); // register our scene with the RTSS Ogre::RTShader::ShaderGenerator *shadergen = Ogre::RTShader::ShaderGenerator::getSingletonPtr(); shadergen->addSceneManager(scnMgr); ctx.setWindowGrab(true); ctx.initCamera(); ctx.createContent(); ctx.setupTerrain(); // register for input events // KeyHandler keyHandler; // ctx.addInputListener(&keyHandler); ctx.getRoot()->startRendering(); ctx.setWindowGrab(false); ctx.closeApp(); return 0; }