Files
ogre-prototype/src/gamedata/GUIModule.cpp
2026-01-09 22:29:26 +03:00

1800 lines
52 KiB
C++

#include <iostream>
#include <OgreOverlaySystem.h>
#include <OgreOverlayManager.h>
#include <OgreImGuiOverlay.h>
#include <OgreImGuiInputListener.h>
#include <OgreRenderTargetListener.h>
#include <OgreSceneNode.h>
#include <OgreApplicationContext.h>
#include <OgreImGuiInputListener.h>
#include <OgreFontManager.h>
#include <OgreTerrainGroup.h>
#include <OgrePagedWorld.h>
#include <OgreTerrainPaging.h>
#include <OgreTerrainPagedWorldSection.h>
#include <nlohmann/json.hpp>
#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<Ogre::String> glb_names;
GUIListener *mGUIListener;
};
struct EditorGUIData {
Ogre::ImGuiOverlay *mGuiOverlay;
std::vector<Ogre::String> 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<GUIData>().mGuiOverlay->addFont(
"smallFont", "General");
OgreAssert(smallFont, "Could not load font");
midFont = ECS::get<GUIData>().mGuiOverlay->addFont("midFont",
"General");
OgreAssert(midFont, "Could not load font");
bigFont = ECS::get<GUIData>().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<GUI>().enabled)
// ECS::get().get<App>().app->setWindowGrab(true);
if (ImGui::Button("Quit"))
Ogre::Root::getSingleton().queueEndRendering();
if (ImGui::Button("Return"))
ECS::get().get<GUI>().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<EngineData>().mScnMgr->createEntity(
name);
Ogre::SceneNode *pnode =
ECS::get()
.get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(
"ent:" + name +
Ogre::StringConverter::toString(
key),
ECS::get()
.get<Camera>()
.mCameraPivot->getPosition(),
ECS::get()
.get<Camera>()
.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<GUI>().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<GUIData>().glb_names.size();
i++) {
Ogre::String id_button =
"Create entity: " +
ECS::get().get<GUIData>().glb_names[i] +
"##ent:" +
ECS::get().get<GUIData>().glb_names[i];
if (ImGui::Button(id_button.c_str())) {
create_entity_node(
ECS::get().get<GUIData>().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<EngineData>().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<GUI>().enabled)
// ECS::get().get<App>().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<GUI>().enabled) {
if (ECS::get().get<GUI>().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<GUI>()
.narrationText.c_str());
if (ECS::get().get<GUI>().choices.size() == 0) {
ImGui::SetCursorScreenPos(p);
if (ImGui::InvisibleButton(
"Background",
ImGui::GetWindowSize()))
ECS::get<LuaBase>().mLua->call_handler(
"narration_progress");
} else {
int i;
for (i = 0; i < ECS::get()
.get<GUI>()
.choices.size();
i++) {
if (ImGui::Button(
ECS::get()
.get<GUI>()
.choices[i]
.c_str())) {
ECS::get()
.get_mut<GUI>()
.narration_answer =
i + 1;
std::cout << "answer: "
<< i + 1
<< std::endl;
ECS::modified<GUI>();
ECS::get<LuaBase>()
.mLua
->call_handler(
"narration_answered");
}
}
}
ImGui::Spacing();
ImGui::PopFont();
ImGui::End();
} else if (ECS::get().get<GUI>().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<GUI>().enabled)
// ECS::get().get<App>().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<GUI>().finish();
if (new_game) {
ECS::get<LuaBase>().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<Ogre::SceneNode *> tree_input_queue,
tree_output_queue;
std::vector<Ogre::SceneNode *> tree_list;
tree_input_queue.push_back(
ECS::get()
.get<EngineData>()
.mScnMgr->getRootSceneNode());
tree_input_queue.push_back(nullptr);
std::set<Ogre::SceneNode *> 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<int> 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<EditorSceneSwitch>({ 1 });
switchWindow = false;
}
#endif
}
#if 0
bool switchWindow = false;
#endif
void buttons_panel()
{
bool enableDebugRender = ECS::get<EngineData>().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<GUI>().enabled)
// ECS::get().get<App>().app->setWindowGrab(true);
if (ImGui::Button("Quit"))
Ogre::Root::getSingleton().queueEndRendering();
if (ImGui::Button("Return"))
ECS::get().get<GUI>().finish();
if (ImGui::Checkbox("Enable physics debug",
&enableDebugRender)) {
ECS::get_mut<EngineData>().enableDbgDraw =
enableDebugRender;
ECS::modified<EngineData>();
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<EngineData>().mScnMgr->createEntity(
name);
Ogre::SceneNode *pnode =
ECS::get()
.get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(
"ent:" + name +
Ogre::StringConverter::toString(
key),
ECS::get()
.get<Camera>()
.mCameraPivot->getPosition(),
ECS::get()
.get<Camera>()
.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<GUI>().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<EditorGUIData>().glb_names.size();
i++) {
Ogre::String id_button =
"Create entity: " +
ECS::get().get<EditorGUIData>().glb_names[i] +
"##ent:" +
ECS::get().get<EditorGUIData>().glb_names[i];
if (ImGui::Button(id_button.c_str())) {
create_entity_node(ECS::get()
.get<EditorGUIData>()
.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<Camera>().mCameraPivot->_getDerivedPosition();
TerrainModule::update_heightmap(worldMapImage);
long x, y;
ECS::get<Terrain>()
.mTerrainGroup->convertWorldPositionToTerrainSlot(
worldPos, &x, &y);
for (auto &slot :
ECS::get<Terrain>().mTerrainGroup->getTerrainSlots()) {
Ogre::uint32 page =
ECS::get<Terrain>().mTerrainGroup->packIndex(
slot.second->x, slot.second->y);
Ogre::Terrain *terrain =
ECS::get<Terrain>().mTerrainGroup->getTerrain(
x, y);
if (terrain)
terrain->waitForDerivedProcesses();
ECS::get<Terrain>()
.mTerrainPagedWorldSection->unloadPage(page,
false);
}
ECS::get<Terrain>().mTerrainGroup->update(false);
}
void setCursorPos(Ogre::Vector3 &cursorPosition,
Ogre::Quaternion &orientation)
{
Ogre::Vector3 worldPos =
ECS::get<EditorGizmo>().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<Terrain>().mTerrainGroup, worldPos);
ECS::get<EditorGizmo>().sceneNode->_setDerivedPosition(
worldPos);
cursorPosition = worldPos;
orientation = ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
}
bool keepCameraAbove = true;
void setCameraPos()
{
Ogre::Vector3 cursorPos;
Ogre::Quaternion cursorOrientation;
setCursorPos(cursorPos, cursorOrientation);
Ogre::Vector3 cameraPos =
ECS::get<Camera>().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<Terrain>().mTerrainGroup, cameraPos) +
10.0f;
if (keepCameraAbove) {
if (cameraPos.y < 0.0f)
cameraPos.y = 10.0f;
} else {
Ogre::TerrainGroup *tg =
ECS::get<Terrain>().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<Camera>().mCameraPivot->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraPivot->_setDerivedOrientation(
cursorOrientation);
cameraPos =
ECS::get<Camera>().mCameraGoal->_getDerivedPosition();
ECS::get<Camera>().mCameraNode->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraNode->_setDerivedOrientation(
ECS::get<Camera>()
.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<EditorGizmo>().sceneNode->_setDerivedPosition(
position);
ECS::get<EditorGizmo>().sceneNode->_setDerivedOrientation(
orientation);
}
void setCameraSelectedPos(flecs::entity e)
{
Ogre::Vector3 cursorPos;
Ogre::Quaternion cursorOrientation;
setCursorSelectedPos(e, cursorPos, cursorOrientation);
Ogre::Vector3 cameraPos =
ECS::get<Camera>().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<Terrain>().mTerrainGroup, cameraPos) +
10.0f;
if (keepCameraAbove) {
if (cameraPos.y < 0.0f)
cameraPos.y = 10.0f;
} else {
Ogre::TerrainGroup *tg =
ECS::get<Terrain>().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<Camera>().mCameraPivot->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraPivot->_setDerivedOrientation(
cursorOrientation);
cameraPos =
ECS::get<Camera>().mCameraGoal->_getDerivedPosition();
ECS::get<Camera>().mCameraNode->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraNode->_setDerivedOrientation(
ECS::get<Camera>()
.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<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
float baseOffset = 200.0f;
Ogre::Vector3 stepOffset =
baseRot * Ogre::Vector3::NEGATIVE_UNIT_Z * baseOffset;
std::vector<float> 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<Ogre::String, float> 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<flecs::entity, Ogre::String> selected_item;
std::list<std::pair<flecs::entity, Ogre::String> > 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<Ogre::String>();
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<EditorGizmo>()
.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<EditorGizmo>().sceneNode) {
Ogre::Vector3 worldPos =
ECS::get<EditorGizmo>()
.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<Terrain>()
.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<Terrain>()
.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<EditorGizmo>()
.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<EditorGizmo>()
.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<Ogre::String>
glb_names;
const std::vector<Ogre::String> &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<Ogre::String> 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<Ogre::Vector3> 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<EditorGizmo>()
.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<EditorGizmo>()
.sceneNode
->_getDerivedPosition();
position.y = ECS::get<Terrain>()
.mTerrainGroup
->getHeightAtWorldPosition(
position);
ECS::get<EditorGizmo>()
.sceneNode->_setDerivedPosition(
position);
}
if (update_cursor_angle)
ECS::get<EditorGizmo>()
.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<Ogre::SceneNode *> tree_input_queue,
tree_output_queue;
std::vector<Ogre::SceneNode *> tree_list;
tree_input_queue.push_back(
ECS::get()
.get<EngineData>()
.mScnMgr->getRootSceneNode());
tree_input_queue.push_back(nullptr);
std::set<Ogre::SceneNode *> 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<int> 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<GUI>().enabled) {
buttons_panel();
panel();
if (enableMapEditor)
worldMapView();
}
}
};
GUIModule::GUIModule(flecs::world &ecs)
{
ecs.module<GUIModule>();
ecs.import <AppModule>();
ecs.component<GUI>()
.on_add([](GUI &gui) {
gui.enabled = false;
gui.grab = false;
gui.grabChanged = false;
})
.add(flecs::Singleton);
ecs.component<GUIData>()
.on_add([](GUIData &priv) {
priv.glb_names.clear();
priv.mGUIListener = nullptr;
priv.mGuiOverlay = nullptr;
})
.add(flecs::Singleton);
ecs.set<GUI>({ false, true, false, false, false, "", {}, -1 });
ecs.set<GUIData>({ nullptr, {}, nullptr });
ui_wait =
ecs.system<const RenderWindow, App, GUIData>("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<Ogre::String> &groups =
Ogre::ResourceGroupManager::
getSingleton()
.getResourceGroups();
for (i = 0; i < groups.size(); i++) {
std::vector<Ogre::String> names =
*Ogre::ResourceGroupManager::getSingleton()
.findResourceNames(
groups[i],
"*.glb");
gui.glb_names.insert(
gui.glb_names.end(),
names.begin(),
names.end());
}
ECS::modified<ECS::GUI>();
std::cout << "GUI configure finished\n";
}
});
}
EditorGUIModule::EditorGUIModule(flecs::world &ecs)
{
ecs.module<EditorGUIModule>();
ecs.import <AppModule>();
ecs.import <StaticGeometryModule>();
ecs.component<GUI>()
.on_add([](GUI &gui) {
gui.enabled = true;
gui.grab = false;
gui.grabChanged = false;
})
.add(flecs::Singleton);
ecs.component<EditorGUIData>()
.on_add([](EditorGUIData &priv) {
priv.glb_names.clear();
priv.mGUIListener = nullptr;
priv.mGuiOverlay = nullptr;
})
.add(flecs::Singleton);
ecs.observer<const RenderWindow, const App, GUI>("SupportEditorGUI")
.event(flecs::OnSet)
.without<EditorGUIData>()
.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<EditorGUIData>(
{ app.mGuiOverlay, {}, guiListener });
std::cout << "Editor GUI configure finished\n";
});
}
}