#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "GameData.h" #include "Components.h" #include "LuaData.h" #include "AppModule.h" #include "TerrainModule.h" #include "StaticGeometryModule.h" #include "EditorGizmoModule.h" #include "PhysicsModule.h" #include "items.h" #include "GUIModule.h" namespace ECS { struct GUIListener; struct EditorGUIListener; struct GUIData { Ogre::ImGuiOverlay *mGuiOverlay; std::vector glb_names; GUIListener *mGUIListener; }; struct EditorGUIData { Ogre::ImGuiOverlay *mGuiOverlay; std::vector glb_names; EditorGUIListener *mGUIListener; }; struct GUIListener : public Ogre::RenderTargetListener { float panel_width; bool enableEditor; bool enableMapEditor; ImFont *smallFont, *midFont, *bigFont; Ogre::FontPtr _smallFont, _midFont, _bigFont; GUIListener() : Ogre::RenderTargetListener() { _midFont = createFont("midFont", "General", "Jupiteroid-Regular.ttf", 18.0f); _smallFont = createFont("smallFont", "General", "Jupiteroid-Regular.ttf", 13.0f); _bigFont = createFont("bigFont", "General", "Kenney Bold.ttf", 32.0f); smallFont = ECS::get().mGuiOverlay->addFont( "smallFont", "General"); OgreAssert(smallFont, "Could not load font"); midFont = ECS::get().mGuiOverlay->addFont("midFont", "General"); OgreAssert(midFont, "Could not load font"); bigFont = ECS::get().mGuiOverlay->addFont("bigFont", "General"); OgreAssert(bigFont, "Could not load font"); #if 0 Ogre::FontPtr _midFont = createFont("midFont", "General", "Kenney Bold.ttf", 28.0f); #endif #if 0 ImGui::GetIO().Fonts->Build(); #endif } Ogre::FontPtr createFont(const Ogre::String &name, const Ogre::String &group, const Ogre::String &ttfname, float fontSize) { Ogre::FontPtr ret = Ogre::FontManager::getSingleton().create(name, group); ret->setType(Ogre::FontType::FT_TRUETYPE); ret->setSource(ttfname); ret->setTrueTypeSize(fontSize); ret->setTrueTypeResolution(75); ret->addCodePointRange(Ogre::Font::CodePointRange(30, 128)); ret->load(); return ret; } void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override { preview(evt); } void 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("Control"); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); if (ImGui::Button("Quit")) Ogre::Root::getSingleton().queueEndRendering(); if (ImGui::Button("Return")) ECS::get().get().finish(); if (ImGui::Button("Enable/Disable item editor")) { enableEditor ^= true; if (enableEditor) enableMapEditor = false; } if (ImGui::Button("Enable/Disable map editor")) { enableMapEditor ^= true; if (enableMapEditor) enableEditor = false; } ImGui::Text("Text message..."); ImGui::End(); } void create_entity_node(const Ogre::String &name, int key) { Ogre::Entity *ent = ECS::get().get().mScnMgr->createEntity( name); Ogre::SceneNode *pnode = ECS::get() .get() .mScnMgr->getRootSceneNode() ->createChildSceneNode( "ent:" + name + Ogre::StringConverter::toString( key), ECS::get() .get() .mCameraPivot->getPosition(), ECS::get() .get() .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); ECS::get().get().finish(); } void 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 < ECS::get().get().glb_names.size(); i++) { Ogre::String id_button = "Create entity: " + ECS::get().get().glb_names[i] + "##ent:" + ECS::get().get().glb_names[i]; if (ImGui::Button(id_button.c_str())) { create_entity_node( ECS::get().get().glb_names[i], i); } } ImGui::End(); } 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()); } } void map_editor() { } void preview(const Ogre::RenderTargetViewportEvent &evt) { int i; Ogre::ImGuiOverlay::NewFrame(); if (ECS::get().get().startupDelay > 0.0f) { ImVec2 size = ImGui::GetMainViewport()->Size; ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(size.x, size.y), ImGuiCond_Always); ImGui::Begin( "StartupScreen", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); ImGui::PushFont(bigFont); ImGui::TextWrapped( "%s", "This game does not autosave. Please use save function to keep your state"); ImGui::PopFont(); ImGui::End(); } else if (ECS::get().get().enabled) { if (ECS::get().get().narrationBox) { ImVec2 size = ImGui::GetMainViewport()->Size; ImGui::SetNextWindowPos(ImVec2(0, size.y * 0.75f), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(size.x, size.y * 0.25f), ImGuiCond_Always); ImGui::Begin("Narration...", NULL, ImGuiWindowFlags_NoTitleBar); ImGui::PushFont(midFont); ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::TextWrapped( "%s", ECS::get() .get() .narrationText.c_str()); if (ECS::get().get().choices.size() == 0) { ImGui::SetCursorScreenPos(p); if (ImGui::InvisibleButton( "Background", ImGui::GetWindowSize())) ECS::get().mLua->call_handler( "narration_progress"); } else { int i; for (i = 0; i < ECS::get() .get() .choices.size(); i++) { if (ImGui::Button( ECS::get() .get() .choices[i] .c_str())) { ECS::get() .get_mut() .narration_answer = i + 1; std::cout << "answer: " << i + 1 << std::endl; ECS::modified(); ECS::get() .mLua ->call_handler( "narration_answered"); } } } ImGui::Spacing(); ImGui::PopFont(); ImGui::End(); } else if (ECS::get().get().mainMenu) { ImVec2 size = ImGui::GetMainViewport()->Size; ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(size.x, size.y), ImGuiCond_Always); ImGui::Begin( "MainMenu", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoFocusOnAppearing | 0); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); ImGui::PushFont(bigFont); ImGui::TextWrapped("%s", "Booo!!!!"); bool pressed = false; bool new_game = false, cont = false, load_game = false, opts = false, quit = false; ImGui::SetCursorPosY(size.y / 2.0f - 300.0f); ImGui::SetCursorPosX(size.x / 2.0f - 300.0f); new_game = ImGui::Button("New Game"); ImGui::SetCursorPosX(size.x / 2.0f - 300.0f); cont = ImGui::Button("Continue"); ImGui::SetCursorPosX(size.x / 2.0f - 300.0f); load_game = ImGui::Button("Load Game"); ImGui::SetCursorPosX(size.x / 2.0f - 300.0f); opts = ImGui::Button("Options"); ImGui::SetCursorPosX(size.x / 2.0f - 300.0f); quit = ImGui::Button("Quit###quit"); pressed = new_game || cont || load_game || opts || quit; ImGui::PopFont(); ImGui::Spacing(); ImGui::End(); if (quit) Ogre::Root::getSingleton() .queueEndRendering(); if (pressed) ECS::get().get().finish(); if (new_game) { ECS::get().mLua->call_handler( "new_game"); } } else { buttons_panel(); if (enableEditor) buildings_editor(); if (enableMapEditor) map_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( ECS::get() .get() .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< Ogre::SceneNode *>( 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(); } } } }; struct EditorGUIListener : public Ogre::RenderTargetListener { float panel_width; bool enableEditor; bool enableMapEditor; ImFont *smallFont, *midFont, *bigFont; Ogre::FontPtr _smallFont, _midFont, _bigFont; Ogre::TexturePtr worldMap; Ogre::Image worldMapImage; EditorGUIListener(Ogre::ImGuiOverlay *overlay) : Ogre::RenderTargetListener() , enableEditor(false) , enableMapEditor(false) , keepCameraAbove(true) , command(COMMAND_NONE) { _midFont = createFont("midFont", "General", "Jupiteroid-Regular.ttf", 18.0f); _smallFont = createFont("smallFont", "General", "Jupiteroid-Regular.ttf", 13.0f); _bigFont = createFont("bigFont", "General", "Kenney Bold.ttf", 32.0f); smallFont = overlay->addFont("smallFont", "General"); OgreAssert(smallFont, "Could not load font"); midFont = overlay->addFont("midFont", "General"); OgreAssert(midFont, "Could not load font"); bigFont = overlay->addFont("bigFont", "General"); OgreAssert(bigFont, "Could not load font"); worldMapImage.load( "world_map.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); #if 0 int x, y, i, j; for (y = 0; y < worldMapImage.getWidth(); y++) for (x = 0; x < worldMapImage.getWidth(); x++) { float r = 0.0f; for (i = -2; i < 3; i++) for (j = -2; j < 3; j++) { int xj = Ogre::Math::Clamp( x + j, 0, (int)worldMapImage .getWidth() - 1); int yi = Ogre::Math::Clamp( y + i, 0, (int)worldMapImage .getHeight() - 1); r += worldMapImage .getColourAt(xj, yi, 0) .r; } r /= 25.0f; Ogre::ColourValue cv = worldMapImage.getColourAt(x, y, 0); cv.r = r; worldMapImage.setColourAt(cv, x, y, 0); } #endif worldMap = Ogre::TextureManager::getSingleton().createManual( "worldMap", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, worldMapImage.getWidth(), worldMapImage.getHeight(), worldMapImage.getNumMipmaps(), worldMapImage.getFormat(), Ogre::TU_DYNAMIC_WRITE_ONLY); worldMap->loadImage(worldMapImage); OgreAssert(worldMap, "could not load world map"); } Ogre::FontPtr createFont(const Ogre::String &name, const Ogre::String &group, const Ogre::String &ttfname, float fontSize) { Ogre::FontPtr ret = Ogre::FontManager::getSingleton().create(name, group); ret->setType(Ogre::FontType::FT_TRUETYPE); ret->setSource(ttfname); ret->setTrueTypeSize(fontSize); ret->setTrueTypeResolution(75); ret->addCodePointRange(Ogre::Font::CodePointRange(30, 128)); ret->load(); return ret; } void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override { preview(evt); } void postViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override { #if 0 if (switchWindow) { ECS::get().set({ 1 }); switchWindow = false; } #endif } #if 0 bool switchWindow = false; #endif void buttons_panel() { bool enableDebugRender = ECS::get().enableDbgDraw; 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("Control"); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); if (ImGui::Button("Quit")) Ogre::Root::getSingleton().queueEndRendering(); if (ImGui::Button("Return")) ECS::get().get().finish(); if (ImGui::Checkbox("Enable physics debug", &enableDebugRender)) { ECS::get_mut().enableDbgDraw = enableDebugRender; ECS::modified(); PhysicsModule::setDebugDraw(enableDebugRender); } #if 0 if (ImGui::Button("AltCam")) { switchWindow = true; } #endif if (ImGui::Button("Deploy config")) { std::function m = [&](const Ogre::String &src, const Ogre::String &dst) { std::ifstream source(src, std::ios::binary); std::ofstream destination(dst, std::ios::binary); OgreAssert(source.is_open(), "Failed to copy files " + src + " -> " + dst); OgreAssert(destination.is_open(), "Failed to copy files " + src + " -> " + dst); OgreAssert(source.is_open() && destination.is_open(), "Failed to copy files " + src + " -> " + dst); destination << source.rdbuf(); destination.close(); source.close(); }; m("resources/buildings/items.list", "../../resources/buildings/items.list"); m("resources/terrain/world_map.png", "../../resources/terrain/world_map.png"); } ImGui::Checkbox("Keep camera above 0", &keepCameraAbove); #if 0 if (ImGui::Button("Enable/Disable item editor")) { enableEditor ^= true; if (enableEditor) enableMapEditor = false; } if (ImGui::Button("Enable/Disable map editor")) { enableMapEditor ^= true; if (enableMapEditor) enableEditor = false; } ImGui::Text("Text message..."); #endif ImGui::Checkbox("Enable Map", &enableMapEditor); ImGui::End(); } void create_entity_node(const Ogre::String &name, int key) { Ogre::Entity *ent = ECS::get().get().mScnMgr->createEntity( name); Ogre::SceneNode *pnode = ECS::get() .get() .mScnMgr->getRootSceneNode() ->createChildSceneNode( "ent:" + name + Ogre::StringConverter::toString( key), ECS::get() .get() .mCameraPivot->getPosition(), ECS::get() .get() .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); ECS::get().get().finish(); } #if 0 void 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 < ECS::get().get().glb_names.size(); i++) { Ogre::String id_button = "Create entity: " + ECS::get().get().glb_names[i] + "##ent:" + ECS::get().get().glb_names[i]; if (ImGui::Button(id_button.c_str())) { create_entity_node(ECS::get() .get() .glb_names[i], i); } } ImGui::End(); } #endif 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()); } } #if 0 void map_editor() { } #endif int pos_x = 0; int pos_y = 0; int top_x = 0; int top_y = 0; int selected_x = 0; int selected_y = 0; bool locationSelected = false; float strength = 0.0f; int size = 0; long slot_x, slot_y; float cursorAngle = 0; void updateWorldTexture() { // Get the hardware pixel buffer Ogre::HardwarePixelBufferSharedPtr pixelBuffer = worldMap->getBuffer(); // Lock the buffer for writing, discarding previous contents for performance pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Get information about the locked region (PixelBox) const Ogre::PixelBox &pixelBox = pixelBuffer->getCurrentLock(); // Ensure the image format matches the texture format OgreAssert(pixelBox.format == worldMapImage.getFormat(), "bad format"); // Copy the image data to the pixel box's data pointer memcpy(pixelBox.data, worldMapImage.getData(), worldMapImage.getSize()); // Unlock the buffer to apply changes to the GPU pixelBuffer->unlock(); } void updateHeightmap() { Ogre::Vector3 worldPos = ECS::get().mCameraPivot->_getDerivedPosition(); TerrainModule::update_heightmap(worldMapImage); long x, y; ECS::get() .mTerrainGroup->convertWorldPositionToTerrainSlot( worldPos, &x, &y); for (auto &slot : ECS::get().mTerrainGroup->getTerrainSlots()) { Ogre::uint32 page = ECS::get().mTerrainGroup->packIndex( slot.second->x, slot.second->y); Ogre::Terrain *terrain = ECS::get().mTerrainGroup->getTerrain( x, y); if (terrain) terrain->waitForDerivedProcesses(); ECS::get() .mTerrainPagedWorldSection->unloadPage(page, false); } ECS::get().mTerrainGroup->update(false); } void setCursorPos(Ogre::Vector3 &cursorPosition, Ogre::Quaternion &orientation) { Ogre::Vector3 worldPos = ECS::get().sceneNode->_getDerivedPosition(); worldPos.x = TerrainModule::get_world_x(selected_x); worldPos.z = TerrainModule::get_world_y(selected_y); worldPos.y = TerrainModule::get_height( ECS::get().mTerrainGroup, worldPos); ECS::get().sceneNode->_setDerivedPosition( worldPos); cursorPosition = worldPos; orientation = ECS::get() .sceneNode->_getDerivedOrientation(); } bool keepCameraAbove = true; void setCameraPos() { Ogre::Vector3 cursorPos; Ogre::Quaternion cursorOrientation; setCursorPos(cursorPos, cursorOrientation); Ogre::Vector3 cameraPos = ECS::get().mCameraPivot->_getDerivedPosition(); Ogre::Vector3 cameraOffset = cursorOrientation * Ogre::Vector3::UNIT_Z * 30.0f; cameraPos.x = cursorPos.x; cameraPos.z = cursorPos.z; cameraPos += cameraOffset; cameraPos.y = TerrainModule::get_height( ECS::get().mTerrainGroup, cameraPos) + 10.0f; if (keepCameraAbove) { if (cameraPos.y < 0.0f) cameraPos.y = 10.0f; } else { Ogre::TerrainGroup *tg = ECS::get().mTerrainGroup; long x, y; tg->convertWorldPositionToTerrainSlot(cameraPos, &x, &y); if (tg->getTerrain(x, y) && tg->getTerrain(x, y)->isLoaded()) { float height = tg->getHeightAtWorldPosition(cameraPos); cameraPos.y = height + 10.0f; } } ECS::get().mCameraPivot->_setDerivedPosition(cameraPos); ECS::get().mCameraPivot->_setDerivedOrientation( cursorOrientation); cameraPos = ECS::get().mCameraGoal->_getDerivedPosition(); ECS::get().mCameraNode->_setDerivedPosition(cameraPos); ECS::get().mCameraNode->_setDerivedOrientation( ECS::get() .mCameraGoal->_getDerivedOrientation()); updateHeightmap(); } void setCursorSelectedPos(flecs::entity e, Ogre::Vector3 &position, Ogre::Quaternion &orientation) { StaticGeometryModule::getItemPositionAndRotation(e, position, orientation); selected_x = TerrainModule::get_img_x(position.x); selected_y = TerrainModule::get_img_y(position.z); ECS::get().sceneNode->_setDerivedPosition( position); ECS::get().sceneNode->_setDerivedOrientation( orientation); } void setCameraSelectedPos(flecs::entity e) { Ogre::Vector3 cursorPos; Ogre::Quaternion cursorOrientation; setCursorSelectedPos(e, cursorPos, cursorOrientation); Ogre::Vector3 cameraPos = ECS::get().mCameraPivot->_getDerivedPosition(); Ogre::Vector3 cameraOffset = cursorOrientation * Ogre::Vector3::UNIT_Z * 30.0f; cameraPos.x = cursorPos.x; cameraPos.z = cursorPos.z; cameraPos += cameraOffset; cameraPos.y = TerrainModule::get_height( ECS::get().mTerrainGroup, cameraPos) + 10.0f; if (keepCameraAbove) { if (cameraPos.y < 0.0f) cameraPos.y = 10.0f; } else { Ogre::TerrainGroup *tg = ECS::get().mTerrainGroup; long x, y; tg->convertWorldPositionToTerrainSlot(cameraPos, &x, &y); if (tg->getTerrain(x, y) && tg->getTerrain(x, y)->isLoaded()) { float height = tg->getHeightAtWorldPosition(cameraPos); cameraPos.y = height + 10.0f; } } ECS::get().mCameraPivot->_setDerivedPosition(cameraPos); ECS::get().mCameraPivot->_setDerivedOrientation( cursorOrientation); cameraPos = ECS::get().mCameraGoal->_getDerivedPosition(); ECS::get().mCameraNode->_setDerivedPosition(cameraPos); ECS::get().mCameraNode->_setDerivedOrientation( ECS::get() .mCameraGoal->_getDerivedOrientation()); updateHeightmap(); } void setSurfaceLevel(int actualSize, int center_x, int center_y, float level) { int i, j; float original = level; if (actualSize == 1) level += 0.4f; else if (actualSize == 2) level += 0.35f; original = Ogre::Math::Clamp(original, 0.0f, 1.0f); for (i = -actualSize; i < actualSize + 1; i++) for (j = -actualSize; j < actualSize + 1; j++) { if (i * i + j * j > actualSize * actualSize) continue; if (center_x + j < 0 || center_x + j >= worldMap->getWidth()) continue; if (center_y + i < 0 || center_y + i >= worldMap->getHeight()) continue; Ogre::ColourValue cv = worldMapImage.getColourAt( center_x + j, center_y + i, 0); cv.r = original; worldMapImage.setColourAt(cv, center_x + j, center_y + i, 0); } updateWorldTexture(); updateHeightmap(); } void setHarbourSurface() { int base_size = 3; float base_height = 0.517f; float base_step = 0.1f; float deep = 0.25f; float shallow = 0.35f; float maxStep = 600.0f; Ogre::Vector3 basePos = ECS::get().sceneNode->_getDerivedPosition(); Ogre::Quaternion baseRot = ECS::get() .sceneNode->_getDerivedOrientation(); float baseOffset = 200.0f; Ogre::Vector3 stepOffset = baseRot * Ogre::Vector3::NEGATIVE_UNIT_Z * baseOffset; std::vector heights = { deep, shallow, base_height, base_height + base_step, base_height + base_step * 2.0f }; int step_count = 0; for (float height : heights) { float localStep = 0.0f; Ogre::Vector3 currentPosition = basePos + stepOffset * (float)step_count - stepOffset * 0.5f; float goTill = maxStep; if (step_count < 2) goTill += 420.0f; while (localStep < goTill - 150.0f * (float)step_count) { localStep += baseOffset; currentPosition += stepOffset; int center_x = TerrainModule::get_img_x( currentPosition.x); int center_y = TerrainModule::get_img_y( currentPosition.z); int size = base_size + 10 - step_count * 2; if (step_count < 2) size = base_size + 14 - step_count * 2; if (step_count == 0) size += 1; setSurfaceLevel(size, center_x, center_y, height); } step_count++; } } static void to_json(nlohmann::json &j, const Ogre::Vector3 &position) { j["x"] = position.x; j["y"] = position.y; j["z"] = position.z; } float setLevelValue = 0.0f; float riseLowerChange = 0.0f; enum { COMMAND_NONE, COMMAND_RISELOWER, COMMAND_RISELOWER2, COMMAND_SMOOTH, COMMAND_SETLEVEL }; int command; void heightmapMenu() { command = COMMAND_NONE; if (ImGui::Button("Elevate")) { riseLowerChange = strength; command = COMMAND_RISELOWER; } ImGui::SameLine(); if (ImGui::Button("Elevate2")) { riseLowerChange = strength; command = COMMAND_RISELOWER2; } ImGui::SameLine(); if (ImGui::Button("Lower")) { riseLowerChange = -strength; command = COMMAND_RISELOWER; } std::pair setLevelCommands[] = { { "Deepest", 0.0f }, { "Deep", 0.25f }, { "Shallow1", 0.35f }, { "Shallow2", 0.47f }, { "Beach", 0.517f }, { "Shore1", 0.536f }, { "Shore2", 0.556f }, { "Shore3", 0.586f }, { "Shore4", 0.606f }, { "Shore5", 0.626f }, { "Shore6", 0.646f }, { "Highest", 1.0f }, }; int buttonCounter = 0; for (const auto &mb : setLevelCommands) { if (ImGui::SmallButton(mb.first.c_str())) { setLevelValue = mb.second; command = COMMAND_SETLEVEL; } if ((buttonCounter & 3) != 0) ImGui::SameLine(); buttonCounter++; } ImGui::Spacing(); if (ImGui::Button("Smooth")) { command = COMMAND_SMOOTH; } ImGui::Separator(); if (ImGui::MenuItem("Save heightmap")) { updateWorldTexture(); updateHeightmap(); TerrainModule::save_heightmap(); } } void executeCommands() { switch (command) { case COMMAND_RISELOWER: { int actualSize = 1 + size * 2; int i, j; for (i = -actualSize; i < actualSize + 1; i++) for (j = -actualSize; j < actualSize + 1; j++) { if (i * i + j * j > actualSize * actualSize) continue; if (selected_x + j < 0 || selected_x + j >= worldMap->getWidth()) continue; if (selected_y + i < 0 || selected_y + i >= worldMap->getHeight()) continue; Ogre::ColourValue cv = worldMapImage.getColourAt( selected_x + j, selected_y + i, 0); float original = cv.r; original += riseLowerChange; original = Ogre::Math::Clamp( original, 0.0f, 1.0f); cv.r = original; worldMapImage.setColourAt( cv, selected_x + j, selected_y + i, 0); } updateWorldTexture(); updateHeightmap(); } break; case COMMAND_RISELOWER2: { int actualSize = 1 + size * 2; int i, j; Ogre::ColourValue maxcv = worldMapImage.getColourAt( selected_x, selected_y, 0); for (i = -actualSize; i < actualSize + 1; i++) for (j = -actualSize; j < actualSize + 1; j++) { if (i * i + j * j > actualSize * actualSize) continue; if (selected_x + j < 0 || selected_x + j >= worldMap->getWidth()) continue; if (selected_y + i < 0 || selected_y + i >= worldMap->getHeight()) continue; float actualStrength = riseLowerChange / (1.0f + (float)(i * i + j * j)); Ogre::ColourValue cv = worldMapImage.getColourAt( selected_x + j, selected_y + i, 0); float original = maxcv.r + actualStrength; original = Ogre::Math::Clamp( original, 0.0f, 1.0f); if (cv.r >= original) continue; cv.r = original; worldMapImage.setColourAt( cv, selected_x + j, selected_y + i, 0); } updateWorldTexture(); updateHeightmap(); } break; case COMMAND_SMOOTH: { int actualSize = 1 + size * 2; int i, j, k, l; for (i = -actualSize; i < actualSize + 1; i++) for (j = -actualSize; j < actualSize + 1; j++) { if (i * i + j * j > actualSize * actualSize) continue; if (selected_x + j < 0 || selected_x + j >= worldMap->getWidth()) continue; if (selected_y + i < 0 || selected_y + i >= worldMap->getHeight()) continue; int kernel = 3; float original = 0.0f; Ogre::ColourValue cv; float count = 0.0f; for (k = -kernel; k < kernel + 1; k++) { if (selected_y + i + k < 0 || selected_y + i + k >= worldMap->getHeight()) continue; for (l = -kernel; l < kernel + 1; l++) { if (selected_x + j + l < 0 || selected_x + j + l >= worldMap->getWidth()) continue; cv = worldMapImage.getColourAt( selected_x + j, selected_y + i, 0); original += cv.r; count += 1.0f; } } original /= count; cv = worldMapImage.getColourAt( selected_x + j, selected_y + i, 0); original = Ogre::Math::Clamp( original, 0.0f, 1.0f); cv.r = original; worldMapImage.setColourAt( cv, selected_x + j, selected_y + i, 0); } updateWorldTexture(); updateHeightmap(); } break; case COMMAND_SETLEVEL: { int actualSize = 1 + size * 2; int i, j; float original = setLevelValue; original = Ogre::Math::Clamp(original, 0.0f, 1.0f); for (i = -actualSize; i < actualSize + 1; i++) for (j = -actualSize; j < actualSize + 1; j++) { if (i * i + j * j > actualSize * actualSize) continue; if (selected_x + j < 0 || selected_x + j >= worldMap->getWidth()) continue; if (selected_y + i < 0 || selected_y + i >= worldMap->getHeight()) continue; Ogre::ColourValue cv = worldMapImage.getColourAt( selected_x + j, selected_y + i, 0); cv.r = original; worldMapImage.setColourAt( cv, selected_x + j, selected_y + i, 0); } updateWorldTexture(); updateHeightmap(); } break; } } void displayItems() { std::pair selected_item; std::list > items; StaticGeometryModule::getItemsProperties(&items); bool item_is_selected = false; for (const auto &item : items) { nlohmann::json j = nlohmann::json::parse(item.second); Ogre::String label = Ogre::StringConverter::toString( item.first.id()); label += ":" + j["type"].get(); if (ImGui::SmallButton(label.c_str())) { /* select */ selected_item = item; item_is_selected = true; } Items::showItemButtons(item); } if (item_is_selected) setCameraSelectedPos(selected_item.first); for (const auto &item : items) Items::showItemPopup(item); } void displayInfo() { ImGui::Text("Position: %d %d", pos_x, pos_y); ImGui::Text("Selected Position: %d %d", selected_x, selected_y); ImGui::Text("Height: %f", worldMapImage.getColourAt(pos_x, pos_y, 0).r); ImGui::Text( "Selected height: %f", worldMapImage.getColourAt(selected_x, selected_y, 0).r); { Ogre::Vector3 position = ECS::get() .sceneNode->_getDerivedPosition(); ImGui::Text("Cursor position %f %f %f", position.x, position.y, position.z); } } void worldMapView() { bool update_cursor_position = false; bool update_cursor_height = false; bool update_cursor_angle = false; OgreAssert(TerrainModule::get_img_x(0) == worldMap->getWidth() / 2, "get_img_x"); OgreAssert(TerrainModule::get_img_y(0) == worldMap->getHeight() / 2, "get_img_x"); OgreAssert(TerrainModule::get_world_x(worldMap->getWidth() / 2) == 0.0f, "get_world_x"); OgreAssert(TerrainModule::get_world_y(worldMap->getHeight() / 2) == 0.0f, "get_world_y"); if (ECS::get().sceneNode) { Ogre::Vector3 worldPos = ECS::get() .sceneNode->_getDerivedPosition(); selected_x = TerrainModule::get_img_x(worldPos.x); selected_y = TerrainModule::get_img_y(worldPos.z); locationSelected = true; OgreAssert(selected_x >= 0 && selected_x < worldMap->getWidth(), "mix width"); OgreAssert(selected_y >= 0 && selected_y < worldMap->getHeight(), "mix height"); ECS::get() .mTerrainGroup ->convertWorldPositionToTerrainSlot( worldPos, &slot_x, &slot_y); } ImGui::SetNextWindowSizeConstraints(ImVec2(512 + 20, 512 + 20), ImVec2(768, 768)); // ImGui::SetNextWindowScroll( // ImVec2(worldMap->getWidth(), worldMap->getHeight())); ImGui::Begin("WorldMap...", nullptr, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Create")) { Items::createItemsMenu(); ImGui::EndMenu(); } if (ImGui::BeginMenu("Heightmap")) { if (ImGui::MenuItem("Update terrain")) ECS::get() .mTerrainGroup->update(false); ImGui::Separator(); ImGui::SliderFloat("Strength...", &strength, 0.0f, 1.0f); ImGui::SliderInt("Size", &size, 0, 32); ImGui::Separator(); heightmapMenu(); ImGui::EndMenu(); } if (ImGui::BeginMenu("Cursor")) { if (ImGui::MenuItem("Update cursor position")) update_cursor_height = true; Ogre::Vector3 cursorPosition = ECS::get() .sceneNode ->_getDerivedPosition(); bool modified = false; if (ImGui::SmallButton("X-1")) { cursorPosition.x -= 1.0f; modified = true; } ImGui::SameLine(); if (ImGui::SmallButton("X+1")) { cursorPosition.x += 1.0f; modified = true; } ImGui::SameLine(); if (ImGui::SmallButton("Y-1")) { cursorPosition.y -= 1.0f; modified = true; } ImGui::SameLine(); if (ImGui::SmallButton("Y+1")) { cursorPosition.y += 1.0f; modified = true; } ImGui::SameLine(); if (ImGui::SmallButton("Z-1")) { cursorPosition.z -= 1.0f; modified = true; } ImGui::SameLine(); if (ImGui::SmallButton("Z+1")) { cursorPosition.z += 1.0f; modified = true; } ImGui::EndMenu(); if (modified) { ECS::get() .sceneNode->_setDerivedPosition( cursorPosition); modified = false; } } if (ImGui::BeginMenu("Furniture")) { if (ImGui::BeginMenu("Create New Furniture")) { static char nameBuffer[32]; static int current_mesh = 0; static std::vector glb_names; const std::vector &groups = Ogre::ResourceGroupManager:: getSingleton() .getResourceGroups(); if (glb_names.size() == 0) { int i; glb_names.push_back(""); for (i = 0; i < groups.size(); i++) { std::vector names = *Ogre::ResourceGroupManager::getSingleton() .findResourceNames( groups[i], "furniture-*.glb"); glb_names.insert( glb_names.end(), names.begin(), names.end()); } } ImGui::InputText( "Furniture Name", nameBuffer, IM_ARRAYSIZE(nameBuffer)); if (glb_names.size() > 0) { if (ImGui::BeginCombo( "Furniture Mesh", glb_names[current_mesh] .c_str())) { int i; for (i = 0; i < glb_names.size(); i++) { bool isSelected = i == current_mesh; if (ImGui::Selectable( (glb_names[i] + "##select" + Ogre::StringConverter:: toString( i)) .c_str(), isSelected)) { current_mesh = i; } if (isSelected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } } else ImGui::Text( "No furniture meshes found"); if (ImGui::MenuItem( "Create Furniture")) { } ImGui::EndMenu(); } if (ImGui::BeginMenu("Edit Furniture")) { if (ImGui::MenuItem("Edit Furniture")) { } ImGui::EndMenu(); } ImGui::EndMenu(); } ImGui::EndMenuBar(); } ImGui::Spacing(); ImGui::BeginChild("WorldMap...", ImVec2(480, 480), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Spacing(); Ogre::ResourceHandle hdl = worldMap->getHandle(); int w = worldMap->getWidth(); int h = worldMap->getHeight(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2((float)5, (float)5)); ImGui::ImageButton("WorldMapPress", (ImTextureID)hdl, ImVec2(w, h)); ImVec2 mouse_absolute_pos = ImGui::GetMousePos(); ImVec2 item_absolute_pos = ImGui::GetItemRectMin(); top_x = item_absolute_pos.x + 5; top_y = item_absolute_pos.y + 5; bool hovered = false; if (ImGui::IsItemHovered()) { ImVec2 mouse_absolute_pos = ImGui::GetMousePos(); ImVec2 item_absolute_pos = ImGui::GetItemRectMin(); pos_x = mouse_absolute_pos.x - item_absolute_pos.x - 5; pos_y = mouse_absolute_pos.y - item_absolute_pos.y - 5; hovered = true; } pos_x = Ogre::Math::Clamp(pos_x, 0, (int)worldMap->getWidth() - 1); pos_y = Ogre::Math::Clamp(pos_y, 0, (int)worldMap->getHeight() - 1); if (pos_x < 0) pos_x = 0; if (pos_x >= worldMap->getWidth()) pos_x = worldMap->getWidth() - 1; if (pos_y < 0) pos_y = 0; if (pos_y >= worldMap->getHeight()) pos_y = worldMap->getHeight() - 1; if (ImGui::IsItemActivated()) { locationSelected = true; selected_x = pos_x; selected_y = pos_y; OgreAssert(selected_x >= 0 && selected_x < worldMap->getWidth(), "mix width"); OgreAssert(selected_y >= 0 && selected_y < worldMap->getHeight(), "mix height"); setCameraPos(); std::cout << "worldClickPos: " << pos_x << " " << pos_y << std::endl; } ImDrawList *draw_list = ImGui::GetWindowDrawList(); draw_list->AddCircleFilled(ImVec2(top_x + pos_x, top_y + pos_y), 1.0f, IM_COL32(0, 255, 0, 255)); { std::list positions; StaticGeometryModule::getItemPositions(&positions); for (auto pos : positions) { int item_x = TerrainModule::get_img_x(pos.x); int item_y = TerrainModule::get_img_y(pos.z); draw_list->AddCircleFilled( ImVec2(top_x + item_x, top_y + item_y), 3.0f, IM_COL32(255, 255, 0, 255)); } } if (locationSelected) draw_list->AddCircleFilled( ImVec2(top_x + selected_x, top_y + selected_y), 4.0f, IM_COL32(64, 255, 64, 255)); { Ogre::Vector3 cursorPos = ECS::get() .sceneNode->_getDerivedPosition(); int cursor_x = TerrainModule::get_img_x(cursorPos.x); int cursor_y = TerrainModule::get_img_y(cursorPos.z); draw_list->AddCircleFilled( ImVec2(top_x + cursor_x, top_y + cursor_y), 4.0f, IM_COL32(255, 64, 64, 128)); } ImGui::PopStyleVar(); ImGui::Spacing(); ImGui::EndChild(); ImGui::SameLine(); ImGui::BeginChild("WorldMap...", ImVec2(64, 480), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar); ImGui::EndChild(); ImGui::Spacing(); ImGui::BeginChild("WorldMap Bottom...", ImVec2(0, 0)); if (ImGui::CollapsingHeader("Display Info")) { displayInfo(); if (ImGui::SliderFloat("Cursor Angle...", &cursorAngle, -180.0f, 180.0f)) update_cursor_angle = true; } displayItems(); ImGui::EndChild(); ImGui::Spacing(); ImGui::End(); if (update_cursor_height || update_cursor_angle) { if (update_cursor_height) { Ogre::Vector3 position = ECS::get() .sceneNode ->_getDerivedPosition(); position.y = ECS::get() .mTerrainGroup ->getHeightAtWorldPosition( position); ECS::get() .sceneNode->_setDerivedPosition( position); } if (update_cursor_angle) ECS::get() .sceneNode->_setDerivedOrientation( Ogre::Quaternion( Ogre::Degree( cursorAngle), Ogre::Vector3::UNIT_Y)); } executeCommands(); } void 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(size.x - window_width, 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( ECS::get() .get() .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(); if (ImGui::Button("From Cursor")) std::cout << name << " From Cursor" << std::endl; if (ImGui::Button("To Cursor")) std::cout << name << " To Cursor" << std::endl; 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 preview(const Ogre::RenderTargetViewportEvent &evt) { int i; Ogre::ImGuiOverlay::NewFrame(); if (ECS::get().get().enabled) { buttons_panel(); panel(); if (enableMapEditor) worldMapView(); } } }; GUIModule::GUIModule(flecs::world &ecs) { ecs.module(); ecs.import (); ecs.component() .on_add([](GUI &gui) { gui.enabled = false; gui.grab = false; gui.grabChanged = false; }) .add(flecs::Singleton); ecs.component() .on_add([](GUIData &priv) { priv.glb_names.clear(); priv.mGUIListener = nullptr; priv.mGuiOverlay = nullptr; }) .add(flecs::Singleton); ecs.set({ false, true, false, false, false, "", {}, -1 }); ecs.set({ nullptr, {}, nullptr }); ui_wait = ecs.system("SetupGUI") .kind(flecs::OnUpdate) .each([this](const RenderWindow &window, App &app, GUIData &gui) { if (!gui.mGuiOverlay) { float vpScale = window.dpi / 96 * window.window->getWidth() / 1600.0f; Ogre::OverlayManager::getSingleton() .setPixelRatio(vpScale); std::cout << "GUI configure\n"; OgreAssert(app.mGuiOverlay, "No ImGUI overlay"); gui.mGuiOverlay = app.mGuiOverlay; gui.mGUIListener = new GUIListener(); gui.mGuiOverlay->setZOrder(300); gui.mGuiOverlay->show(); gui.mGUIListener->panel_width = 300.0f; gui.mGUIListener->enableEditor = false; window.window->addListener( gui.mGUIListener); 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"); gui.glb_names.insert( gui.glb_names.end(), names.begin(), names.end()); } ECS::modified(); std::cout << "GUI configure finished\n"; } }); } EditorGUIModule::EditorGUIModule(flecs::world &ecs) { ecs.module(); ecs.import (); ecs.import (); ecs.component() .on_add([](GUI &gui) { gui.enabled = true; gui.grab = false; gui.grabChanged = false; }) .add(flecs::Singleton); ecs.component() .on_add([](EditorGUIData &priv) { priv.glb_names.clear(); priv.mGUIListener = nullptr; priv.mGuiOverlay = nullptr; }) .add(flecs::Singleton); ecs.observer("SupportEditorGUI") .event(flecs::OnSet) .without() .each([](const RenderWindow &window, const App &app, GUI &gui) { float vpScale = window.dpi / 96 * window.window->getWidth() / 1600.0f; Ogre::OverlayManager::getSingleton().setPixelRatio( vpScale); std::cout << "Editor GUI configure\n"; OgreAssert(app.mGuiOverlay, "No ImGUI overlay"); Ogre::ImGuiOverlay *guiOverlay = app.mGuiOverlay; EditorGUIListener *guiListener = new EditorGUIListener(guiOverlay); guiOverlay->setZOrder(300); guiOverlay->show(); guiListener->panel_width = 300.0f; guiListener->enableEditor = false; window.window->addListener(guiListener); ECS::get().set( { app.mGuiOverlay, {}, guiListener }); std::cout << "Editor GUI configure finished\n"; }); } }