diff --git a/src/editor/main.cpp b/src/editor/main.cpp index 1d4f37c..93cca04 100644 --- a/src/editor/main.cpp +++ b/src/editor/main.cpp @@ -296,15 +296,71 @@ public: void frameRendered(const Ogre::FrameEvent &evt) override; }; -class App : public OgreBites::ApplicationContext { - Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal; - Ogre::Camera *mCamera; - Ogre::Real mPivotPitch; +struct SceneData { Ogre::SceneManager *mScnMgr; + Ogre::Camera *mCamera; + Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal; + Ogre::Real mPivotPitch; + SceneData() + : mScnMgr(nullptr) + , mCamera(nullptr) + , mCameraNode(nullptr) + , mCameraPivot(nullptr) + , mCameraGoal(nullptr) + { + } + void setup(Ogre::Root *root, Ogre::OverlaySystem *overlaySystem) + { + Ogre::SceneManager *scnMgr = root->createSceneManager(); + mScnMgr = scnMgr; + mScnMgr->addRenderQueueListener(overlaySystem); + } + void initCamera(const Ogre::String &cameraName) + { + mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode( + cameraName + "CameraNode"); + mCameraNode->setPosition(0, 2, 3); + mCameraNode->lookAt(Ogre::Vector3(0, 1, -1), + Ogre::Node::TS_PARENT); + + // create the camera + mCamera = mScnMgr->createCamera(cameraName); + mCamera->setNearClipDistance(0.05f); + mCamera->setAutoAspectRatio(true); + mCameraNode->attachObject(mCamera); + mCameraPivot = + mScnMgr->getRootSceneNode()->createChildSceneNode( + cameraName + "FPSCameraPivot"); + mCameraGoal = mCameraPivot->createChildSceneNode( + cameraName + "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; + } + void setupRTSS() + { + Ogre::RTShader::ShaderGenerator *shadergen = + Ogre::RTShader::ShaderGenerator::getSingletonPtr(); + shadergen->addSceneManager(mScnMgr); + } + Ogre::SceneManager *getSceneManager() + { + return mScnMgr; + } +}; + +class App : public OgreBites::ApplicationContext { Ogre::Viewport *mViewport; SkyBoxRenderer *sky; bool mGrab; KeyboardListener mKbd; + SceneData mEditorNormalScene, mEditorAltScene; public: App() @@ -316,16 +372,12 @@ public: virtual ~App() { } - void setup() + void setup() override { 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()); + mEditorNormalScene.setup(root, getOverlaySystem()); + mEditorAltScene.setup(root, getOverlaySystem()); } bool isWindowGrab() { @@ -353,85 +405,41 @@ public: 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; + mEditorNormalScene.initCamera("fps_camera"); + mEditorNormalScene.initCamera("alt_camera"); + mViewport = getRenderWindow()->addViewport( + mEditorNormalScene.mCamera); } void configure() { - std::cout << "Startup" - << "\n"; + std::cout << "Startup" + << "\n"; initApp(); - std::cout << "Set up RTSS" - << "\n"; + std::cout << "Set up RTSS" + << "\n"; Ogre::Root *root = getRoot(); - Ogre::SceneManager *scnMgr = getSceneManager(); - - // register our scene with the RTSS - Ogre::RTShader::ShaderGenerator *shadergen = - Ogre::RTShader::ShaderGenerator::getSingletonPtr(); - shadergen->addSceneManager(scnMgr); + mEditorNormalScene.setupRTSS(); + mEditorAltScene.setupRTSS(); setWindowGrab(false); - std::cout << "Init camera" - << "\n"; + std::cout << "Init camera" + << "\n"; initCamera(); - std::cout << "Set up water" - << "\n"; - std::cout << "Set up cursor" - << "\n"; Ogre::ResourceGroupManager::getSingleton() .initialiseAllResourceGroups(); - // OgreBites::ApplicationContext::loadResources(); - // setupCursor(); - std::cout << "Setup input" - << "\n"; + std::cout << "Setup input" + << "\n"; setupInput(); - std::cout << "Create content" - << "\n"; + std::cout << "Create content" + << "\n"; createContent(); - std::cout << "Setup done" - << "\n"; -#if 0 - mDbgDraw->setDebugMode(mDbgDraw->getDebugMode() | - btIDebugDraw::DBG_DrawContactPoints); -#endif - } - Ogre::SceneManager *getSceneManager() - { - return mScnMgr; + std::cout << "Setup done" + << "\n"; } Ogre::Timer mTerrainUpd; // TODO: implement rough water level calculation float getWaterLevel(const Ogre::Vector3 &position) { - Ogre::Vector3::UNIT_Y; - float etime = - Ogre::ControllerManager::getSingleton().getElapsedTime(); return 0.0f; } void updateWorld(float delta) @@ -447,6 +455,26 @@ public: ECS::get().modified(); } ECS::update(delta); +#if 0 + if (switchWindow) { + int scene = ECS::get().scene; + mEditorNormalScene.mScnMgr->removeRenderQueueListener( + getOverlaySystem()); + mEditorAltScene.mScnMgr->removeRenderQueueListener( + getOverlaySystem()); + mViewport->setOverlaysEnabled(false); + if (scene == 0) + mViewport->setCamera( + mEditorNormalScene.mCamera); + else if (scene == 1) + mViewport->setCamera(mEditorAltScene.mCamera); + mViewport->setOverlaysEnabled(true); + mEditorNormalScene.mScnMgr->addRenderQueueListener( + getOverlaySystem()); + mEditorAltScene.mScnMgr->addRenderQueueListener( + getOverlaySystem()); + } +#endif } class InputListenerChainFlexible : public OgreBites::InputListener { protected: @@ -580,10 +608,11 @@ public: void setupInput() { } + bool switchWindow = false; void createContent() { int i; - sky = new SkyBoxRenderer(getSceneManager()); + sky = new SkyBoxRenderer(mEditorNormalScene.getSceneManager()); bool drawFirst = true; uint8_t renderQueue = drawFirst ? Ogre::RENDER_QUEUE_SKIES_EARLY : @@ -599,8 +628,14 @@ public: "Skybox/Dynamic", "General"); OgreAssert(m, "Sky box material not found."); m->load(); - ECS::setupEditor(mScnMgr, /*mDynWorld.get(), */ mCameraNode, - mCamera, getRenderWindow()); + ECS::setupEditor( + mEditorNormalScene.mScnMgr, + /*mDynWorld.get(), */ mEditorNormalScene.mCameraNode, + mEditorNormalScene.mCamera, getRenderWindow()); + ECS::setupEditorAlt( + mEditorAltScene.mScnMgr, + /*mDynWorld.get(), */ mEditorAltScene.mCameraNode, + mEditorAltScene.mCamera, getRenderWindow()); ECS::get().import (); ECS::get().import (); ECS::get().set( @@ -632,11 +667,20 @@ public: nullptr, { getImGuiInputListener(), &mKbd } }); ECS::get().add(); +#if 0 + ECS::get() + .observer("UpdateEditorScene") + .event(flecs::OnSet) + .each([&](ECS::EditorSceneSwitch &sw) { + switchWindow = true; + }); +#endif std::shared_ptr manualObj( - mScnMgr->createManualObject("EditorGizmo")); + mEditorNormalScene.mScnMgr->createManualObject( + "EditorGizmo")); Ogre::SceneNode *gizmoNode = - mScnMgr->getRootSceneNode()->createChildSceneNode( - "EditorGizmoNode"); + mEditorNormalScene.mScnMgr->getRootSceneNode() + ->createChildSceneNode("EditorGizmoNode"); gizmoNode->attachObject(manualObj.get()); manualObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY); ECS::get().set({ manualObj, gizmoNode }); @@ -723,13 +767,9 @@ public: ECS::get().get_mut().enabled = active; ECS::get().modified(); } - Ogre::Camera *getCamera() - { - return mCamera; - } flecs::entity getPlayer() const { - return ECS::player; + return ECS::player; } void enableDbgDraw(bool enable) { @@ -795,7 +835,7 @@ int main() { App ctx; ctx.configure(); - // ctx.enableDbgDraw(false); + // ctx.enableDbgDraw(false); ctx.getRoot()->startRendering(); ctx.setWindowGrab(false); ctx.closeApp(); diff --git a/src/gamedata/CMakeLists.txt b/src/gamedata/CMakeLists.txt index d1e426c..183da0c 100644 --- a/src/gamedata/CMakeLists.txt +++ b/src/gamedata/CMakeLists.txt @@ -4,6 +4,7 @@ find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG find_package(Bullet REQUIRED) find_package(nlohmann_json REQUIRED) find_package(OgreProcedural REQUIRED CONFIG) +add_subdirectory(items) add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp PhysicsModule.cpp EventModule.cpp CharacterManagerModule.cpp @@ -14,7 +15,7 @@ target_link_libraries(GameData PUBLIC nlohmann_json::nlohmann_json OgreMain OgreBites - OgrePaging OgreTerrain OgreOverlay OgreProcedural::OgreProcedural + OgrePaging OgreTerrain OgreOverlay OgreProcedural::OgreProcedural items PRIVATE sceneloader world-build physics editor) target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${BULLET_INCLUDE_DIR} ../luaaa) target_compile_definitions(GameData PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION) diff --git a/src/gamedata/Components.h b/src/gamedata/Components.h index d2839db..d6a7af3 100644 --- a/src/gamedata/Components.h +++ b/src/gamedata/Components.h @@ -75,5 +75,8 @@ struct GroundCheckReady {}; struct Body2Entity { /* std::unordered_map entities; */ }; +struct EditorSceneSwitch { + int scene; +}; } -#endif \ No newline at end of file +#endif diff --git a/src/gamedata/GUIModule.cpp b/src/gamedata/GUIModule.cpp index 1e0f7a4..7024b05 100644 --- a/src/gamedata/GUIModule.cpp +++ b/src/gamedata/GUIModule.cpp @@ -21,6 +21,7 @@ #include "StaticGeometryModule.h" #include "EditorGizmoModule.h" #include "PhysicsModule.h" +#include "items.h" #include "GUIModule.h" namespace ECS { @@ -485,8 +486,11 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { Ogre::Image worldMapImage; EditorGUIListener(Ogre::ImGuiOverlay *overlay) - : Ogre::RenderTargetListener() - , keepCameraAbove(true) + : Ogre::RenderTargetListener() + , enableEditor(false) + , enableMapEditor(false) + , keepCameraAbove(true) + , command(COMMAND_NONE) { _midFont = createFont("midFont", "General", "Jupiteroid-Regular.ttf", 18.0f); @@ -561,9 +565,23 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { { 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; + bool enableDebugRender = ECS::get().enableDbgDraw; + ImVec2 size = ImGui::GetMainViewport()->Size; float window_width = size.x * 0.2f; if (window_width > panel_width) @@ -580,40 +598,45 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { 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 (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); + 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); + 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; @@ -781,6 +804,11 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { 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); @@ -802,7 +830,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { orientation = ECS::get() .sceneNode->_getDerivedOrientation(); } - bool keepCameraAbove = true; + bool keepCameraAbove = true; void setCameraPos() { Ogre::Vector3 cursorPos; @@ -819,22 +847,22 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { 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; - } - } + 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); @@ -874,22 +902,22 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { 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; - } - } + 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); @@ -979,768 +1007,275 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { step_count++; } } - /* This is editor function */ - static bool findPierOffset(float &offset) - { - Ogre::Vector3 basePos = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion baseRot = - ECS::get() - .sceneNode->_getDerivedOrientation(); - Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); - float length = 0.0f; - while (length < 250.0f) { - Ogre::Vector3 currentPosition = - basePos + direction * length; - float height = - ECS::get() - .mTerrainGroup->getHeightAtWorldPosition( - currentPosition); - if (height < -4.0f) { - offset = length; - break; - } - length += 2.0f; - } - return length < 250.0f; - } - static bool findPierOffsetAndLengthAndDepth(float &offset, - float &length, float &depth) - { - if (!findPierOffset(offset)) - return false; - Ogre::Vector3 basePos = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion baseRot = - ECS::get() - .sceneNode->_getDerivedOrientation(); - Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); - length = 0.0f; - depth = 4.0f; - while (length < 60.0f) { - Ogre::Vector3 currentPosition = - basePos + direction * (offset + length); - float height = - ECS::get() - .mTerrainGroup->getHeightAtWorldPosition( - currentPosition); - if (depth < -height) - depth = -height; - if (height > -4.0f) - break; - length += 6.0f; - } - return true; - } - static void findPierHeight(float maxLength, float &height) - { - Ogre::Vector3 basePos = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion baseRot = - ECS::get() - .sceneNode->_getDerivedOrientation(); - Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); - float length = 0.0f; - height = 0.0f; - while (length < 60.0f) { - Ogre::Vector3 currentPosition = - basePos + direction * (length); - float dheight = - ECS::get() - .mTerrainGroup->getHeightAtWorldPosition( - currentPosition); - if (height < dheight) - height = dheight; - length += 1.0f; - } - } - static void findPierPath(float pathLength, - std::vector &path) - { - float minHeight = 0.2f; - int i; - Ogre::Vector3 basePos = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion baseRot = - ECS::get() - .sceneNode->_getDerivedOrientation(); - Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); - float length = 0.0f; - while (length < pathLength) { - Ogre::Vector3 currentPosition = - basePos + direction * (length); - float dheight = - ECS::get() - .mTerrainGroup->getHeightAtWorldPosition( - currentPosition); - if (dheight < minHeight) - dheight = minHeight; - Ogre::Vector3 localOffset = - Ogre::Vector3(0, 0, 1) * length; - Ogre::Vector3 localFromWorld = - ECS::get() - .sceneNode->convertWorldToLocalPosition( - { currentPosition.x, dheight, - currentPosition.z }); - path.push_back({ localOffset.x, localFromWorld.y, - localOffset.z }); - length += 2.0f; - } - if (path.size() == 0) { - path.push_back(Ogre::Vector3(0, 0, 0)); - path.push_back(Ogre::Vector3(0, 0, pathLength)); - } - std::vector tmppath = path; - path.clear(); - for (auto &pt : tmppath) { - if (path.size() == 0) - path.push_back(pt); - else { - if (path.back().z + 0.5f >= pt.z) - continue; - else - path.push_back(pt); - } - } - Ogre::Vector3 lastp = path.back(); - for (i = 1; i < path.size(); i++) { - Ogre::Vector3 &prev = path[i - 1]; - if (path[i].y > prev.y) - continue; - else if (path[i].y < prev.y) { - float d = prev.y - path[i].y; - if (d > 0.15f) - path[i].y = prev.y - 0.15f; - } - } - float dy = path.back().y - lastp.y; - if (dy > 0) - path.push_back({ lastp.x, lastp.y, - path.back().z + dy * 3.0f }); - path.push_back( - { path.back().x, path.back().y, path.back().z + 2.0f }); - } static void to_json(nlohmann::json &j, const Ogre::Vector3 &position) { j["x"] = position.x; j["y"] = position.y; j["z"] = position.z; } - void createHarbourItem() + float setLevelValue = 0.0f; + float riseLowerChange = 0.0f; + enum { + COMMAND_NONE, + COMMAND_RISELOWER, + COMMAND_RISELOWER2, + COMMAND_SMOOTH, + COMMAND_SETLEVEL + }; + int command; + void heightmapMenu() { - Ogre::Vector3 itemPosition = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion itemOrientation = - ECS::get() - .sceneNode->_getDerivedOrientation(); - float pierLength, pierDepth; - float pierOffset; - float pierHeight; - if (!findPierOffsetAndLengthAndDepth(pierOffset, pierLength, - pierDepth)) - return; - findPierHeight(pierOffset + pierLength, pierHeight); - std::vector pierPath; - findPierPath(pierOffset + 2.0f, pierPath); - flecs::entity e = StaticGeometryModule::createItem( - itemPosition, itemOrientation, "harbour"); - Ogre::String prop = StaticGeometryModule::getItemProperties(e); - nlohmann::json j = nlohmann::json::parse(prop); - j["pierOffset"] = pierOffset; - j["pierLength"] = pierLength; - j["pierDepth"] = pierDepth; - j["pierHeight"] = pierHeight; - nlohmann::json p = nlohmann::json::array(); - for (const auto &pt : pierPath) { - nlohmann::json pj; - to_json(pj, pt); - p.push_back(pj); + 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(); } - j["pierPath"] = p; - StaticGeometryModule::setItemProperties(e, j.dump()); - // setHarbourSurface(); - StaticGeometryModule::saveItems(); - // updateWorldTexture(); - // updateHeightmap(); - // TerrainModule::save_heightmap(); } - void createTempleItem() - { - Ogre::Vector3 itemPosition = - ECS::get().sceneNode->_getDerivedPosition(); - Ogre::Quaternion itemOrientation = - ECS::get() - .sceneNode->_getDerivedOrientation(); - flecs::entity e = StaticGeometryModule::createItem( - itemPosition, itemOrientation, "temple"); - Ogre::String prop = StaticGeometryModule::getItemProperties(e); - nlohmann::json j = nlohmann::json::parse(prop); - j["size"] = 40.0f; - j["form"] = "rect"; - j["pillarHeight"] = 16.0f; - j["pillarRadius"] = 0.5f; - j["pillarCount"] = 20; - StaticGeometryModule::setItemProperties(e, j.dump()); - StaticGeometryModule::saveItems(); - } - void createHarbourMenu() + void executeCommands() { - if (ImGui::MenuItem("Create")) - createHarbourItem(); + 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 createTempleMenu() - { - if (ImGui::MenuItem("Create")) - createTempleItem(); - } - bool editHarbourDistrict(nlohmann::json &jitem) - { - float plazzaRadius = 5.0f; - float plazzaHeight = 0.2f; - float plazzaElevation = 0.0f; - float centerOffset = 0.0f; - bool plazza = false; - bool changed = false; - struct LotData { - float distance; - float angle; - float width; - float depth; - float elevation; - bool valid; - Ogre::String type; - Ogre::String properties; - }; - std::vector centerBuildings; - nlohmann::json &j = jitem; - if (j.find("centerOffset") != j.end()) - centerOffset = j["centerOffset"].get(); - if (j.find("plazza") != j.end()) - plazza = j["plazza"].get(); - if (j.find("plazzaRadius") != j.end()) - plazzaRadius = j["plazzaRadius"].get(); - if (j.find("plazzaHeight") != j.end()) - plazzaHeight = j["plazzaHeight"].get(); - if (j.find("plazzaElevation") != j.end()) - plazzaElevation = j["plazzaElevation"].get(); - if (j.find("centerBuildings") != j.end()) { - for (auto &jb : j["centerBuildings"]) { - LotData data; - data.distance = 100.0f; - data.angle = 0; - data.width = 50.0f; - data.depth = 50.0f; - data.elevation = 0.0f; - data.type = "base"; - data.properties = "{}"; - data.valid = true; - if (jb.find("distance") != jb.end()) - data.distance = - jb["distance"].get(); - if (jb.find("angle") != jb.end()) - data.angle = jb["angle"].get(); - if (jb.find("width") != jb.end()) - data.width = jb["width"].get(); - if (jb.find("depth") != jb.end()) - data.depth = jb["depth"].get(); - if (jb.find("elevation") != jb.end()) - data.elevation = - jb["elevation"].get(); - if (jb.find("type") != jb.end()) - data.type = - jb["type"].get(); - if (jb.find("properties") != jb.end()) - data.properties = - jb["properties"] - .get(); - centerBuildings.push_back(data); - } - } - if (ImGui::SliderFloat("Center Offset", ¢erOffset, 0.0f, - 100.0f)) - changed = true; - if (ImGui::Checkbox("Plazza", &plazza)) - changed = true; - if (plazza) { - if (ImGui::SliderFloat("Plazza Radius", &plazzaRadius, - 5.0f, 100.0f)) - changed = true; - if (ImGui::SliderFloat("Plazza Height", &plazzaHeight, - 0.2f, 1.0f)) - changed = true; - if (ImGui::SliderFloat("Plazza Elevation", - &plazzaElevation, -5.0f, 5.0f)) - changed = true; - } - int count = 0; - for (auto &b : centerBuildings) { - ImGui::Text("Lot %d", count); - Ogre::String ms = - "##" + Ogre::StringConverter::toString(count); - if (ImGui::SliderFloat(("Lot distance" + ms).c_str(), - &b.distance, 0.0f, 100.0f)) - changed = true; - if (ImGui::SliderFloat(("Lot angle" + ms).c_str(), - &b.angle, 0.0f, 360.0f)) - changed = true; - if (ImGui::SliderFloat(("Width" + ms).c_str(), &b.width, - 10.0f, 200.0f)) - changed = true; - if (ImGui::SliderFloat(("Depth" + ms).c_str(), &b.depth, - 10.0f, 200.0f)) - changed = true; - if (ImGui::SliderFloat(("Elevation" + ms).c_str(), - &b.elevation, -10.0f, 10.0f)) - changed = true; - if (ImGui::SmallButton(("Delete" + ms).c_str())) - b.valid = false; - count++; - } - if (ImGui::SmallButton("Add building")) { - changed = true; - LotData data; - data.distance = 100.0f; - data.angle = 0; - data.width = 50.0f; - data.depth = 50.0f; - data.elevation = 0.0f; - data.type = "base"; - data.properties = "{}"; - data.valid = true; - centerBuildings.push_back(data); - } - if (changed) { - j["centerOffset"] = centerOffset; - j["plazza"] = plazza; - j["plazzaRadius"] = plazzaRadius; - j["plazzaHeight"] = plazzaHeight; - j["plazzaElevation"] = plazzaElevation; - nlohmann::json lots = nlohmann::json::array(); - for (const auto &d : centerBuildings) { - nlohmann::json jdata; - if (!d.valid) - continue; - jdata["distance"] = d.distance; - jdata["angle"] = d.angle; - jdata["width"] = d.width; - jdata["depth"] = d.depth; - jdata["elevation"] = d.elevation; - jdata["type"] = d.type; - jdata["properties"] = d.properties; - lots.push_back(jdata); - } - j["centerBuildings"] = lots; - } - return changed; - } - void - createHarbourPopup(const std::pair item) - { - bool lighthouse = false; - float lighthouseDistance = 0.0f; - float lighthouseAngle = 0.0f; - float centerOffset = 0.0f; - bool changed = false; - - Ogre::String prop = - StaticGeometryModule::getItemProperties(item.first); - nlohmann::json j = nlohmann::json::parse(prop); - nlohmann::json jcenter = nlohmann::json::object(); - if (j.find("lighthouse") != j.end()) - lighthouse = j["lighthouse"].get(); - if (j.find("lighthouseDistance") != j.end()) - lighthouseDistance = - j["lighthouseDistance"].get(); - if (j.find("lighthouseAngle") != j.end()) - lighthouseAngle = j["lighthouseAngle"].get(); - if (j.find("centerOffset") != j.end()) - centerOffset = j["centerOffset"].get(); - if (j.find("center") != j.end()) - jcenter = j["center"]; - if (ImGui::Checkbox("Lighthouse", &lighthouse)) - changed = true; - if (lighthouse) { - if (ImGui::SliderFloat("Lighthouse Distance", - &lighthouseDistance, 0.0f, - 100.0f)) - changed = true; - if (ImGui::SliderFloat("Lighthouse Angle", - &lighthouseAngle, -90.0f, 90.0f)) - changed = true; - } - if (ImGui::SliderFloat("Center Offset Global", ¢erOffset, - 0.0f, 100.0f)) - changed = true; - changed = changed || editHarbourDistrict(jcenter); - if (changed) { - j["lighthouse"] = lighthouse; - j["lighthouseDistance"] = lighthouseDistance; - j["lighthouseAngle"] = lighthouseAngle; - j["center"] = jcenter; - j["centerOffset"] = centerOffset; - StaticGeometryModule::setItemProperties(item.first, - j.dump()); - StaticGeometryModule::saveItems(); - StaticGeometryModule::destroyItemGeometry(item.first); - StaticGeometryModule::createItemGeometry(item.first); - } - ImGui::Text("%s", j.dump(4).c_str()); - } - void - createTemplePopup(const std::pair item) - { - float size = 40.0f; - float pillarRadius = 0.5f; - float pillarHeight = 16.0f; - int pillarCount = 20; - Ogre::String form; - - Ogre::String prop = - StaticGeometryModule::getItemProperties(item.first); - nlohmann::json j = nlohmann::json::parse(prop); - bool changed = false; - if (j.find("size") != j.end()) - size = j["size"].get(); - if (j.find("pillarRadius") != j.end()) - pillarRadius = j["pillarRadius"].get(); - if (j.find("pillarHeight") != j.end()) - pillarHeight = j["pillarHeight"].get(); - if (j.find("pillarCount") != j.end()) - pillarCount = j["pillarCount"].get(); - if (ImGui::SliderFloat("Temple Size", &size, 40.0f, 100.0f)) - changed = true; - if (ImGui::SliderFloat("Temple Pillar Radius", &pillarRadius, - 0.5f, 2.0f)) - changed = true; - if (ImGui::SliderFloat("Temple Pillar Height", &pillarHeight, - 16.0f, 60.0f)) - changed = true; - if (ImGui::SliderInt("Pillar Count", &pillarCount, 1, 200)) - changed = true; - if (changed) { - j["size"] = size; - j["pillarRadius"] = pillarRadius; - j["pillarHeight"] = pillarHeight; - j["pillarCount"] = pillarCount; - StaticGeometryModule::setItemProperties(item.first, - j.dump()); - StaticGeometryModule::saveItems(); - StaticGeometryModule::destroyItemGeometry(item.first); - StaticGeometryModule::createItemGeometry(item.first); - } - ImGui::Text("%s", j.dump(4).c_str()); - } - 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 showItemButtons(const std::pair &item) - { - ImGui::SameLine(); - Ogre::String upd_label = - "Update Height##" + - Ogre::StringConverter::toString(item.first.id()); - if (ImGui::SmallButton(upd_label.c_str())) { - TerrainItem &uitem = item.first.get_mut(); - uitem.position.y = - ECS::get() - .mTerrainGroup->getHeightAtWorldPosition( - uitem.position); - StaticGeometryModule::saveItems(); - } - ImGui::SameLine(); - Ogre::String edit_label = - "Edit##" + - Ogre::StringConverter::toString(item.first.id()); - Ogre::String popupLabel = - "EditPopup" + - Ogre::StringConverter::toString(item.first.id()); - if (ImGui::SmallButton(edit_label.c_str())) - ImGui::OpenPopup(popupLabel.c_str()); - ImGui::SameLine(); - Ogre::String del_label = - "delete##" + - Ogre::StringConverter::toString(item.first.id()); - if (ImGui::SmallButton(del_label.c_str())) { - item.first.destruct(); - StaticGeometryModule::saveItems(); - } - ImGui::Spacing(); - } - void showItemPopup(const std::pair &item) - { - Ogre::String popupLabel = - "EditPopup" + - Ogre::StringConverter::toString(item.first.id()); - if (ImGui::BeginPopup(popupLabel.c_str())) { - Ogre::String prop = - StaticGeometryModule::getItemProperties( - item.first); - nlohmann::json j = nlohmann::json::parse(prop); - Ogre::String itemType = j["type"].get(); - if (itemType == "harbour") - createHarbourPopup(item); - else if (itemType == "temple") - createTemplePopup(item); - ImGui::EndPopup(); - } - } - - void displayItems() - { - std::pair selected_item; - std::list > items; - StaticGeometryModule::getItemsProperties(&items); - bool item_is_selected = false; - for (const auto &item : items) { - Ogre::String label = Ogre::StringConverter::toString( - item.first.id()); - label += item.second.substr(0, 32); - if (ImGui::SmallButton(label.c_str())) { /* select */ - selected_item = item; - item_is_selected = true; - } - showItemButtons(item); - } - if (item_is_selected) - setCameraSelectedPos(selected_item.first); - for (const auto &item : 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"); @@ -1778,15 +1313,8 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { ImGui::Begin("WorldMap...", nullptr, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Create")) { - if (ImGui::BeginMenu("Harbour")) { - createHarbourMenu(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Temple")) { - createTempleMenu(); - ImGui::EndMenu(); - } - ImGui::EndMenu(); + Items::createItemsMenu(); + ImGui::EndMenu(); } if (ImGui::BeginMenu("Heightmap")) { if (ImGui::MenuItem("Update terrain")) @@ -1797,8 +1325,53 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { 0.0f, 1.0f); ImGui::SliderInt("Size", &size, 0, 32); ImGui::Separator(); - heightmapMenu(); - ImGui::EndMenu(); + 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; + } } ImGui::EndMenuBar(); } @@ -1890,42 +1463,40 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { ImGui::EndChild(); ImGui::Spacing(); ImGui::BeginChild("WorldMap Bottom...", ImVec2(0, 0)); - displayInfo(); - bool update_cursor_height = false; - bool update_cursor_angle = false; - if (ImGui::Button("Update cursor position")) - update_cursor_height = true; - if (ImGui::SliderFloat("Cursor Angle...", &cursorAngle, -180.0f, - 180.0f)) - update_cursor_angle = true; - displayItems(); + 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(); - } + 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; @@ -2031,236 +1602,6 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { } ImGui::Spacing(); ImGui::End(); -#if 0 - 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(); - } -#endif } void preview(const Ogre::RenderTargetViewportEvent &evt) { @@ -2268,10 +1609,6 @@ struct EditorGUIListener : public Ogre::RenderTargetListener { Ogre::ImGuiOverlay::NewFrame(); if (ECS::get().get().enabled) { buttons_panel(); -#if 0 - buildings_editor(); - map_editor(); -#endif panel(); if (enableMapEditor) worldMapView(); diff --git a/src/gamedata/GameData.cpp b/src/gamedata/GameData.cpp index e350853..7485e87 100644 --- a/src/gamedata/GameData.cpp +++ b/src/gamedata/GameData.cpp @@ -42,7 +42,7 @@ void setup_minimal() ecs.component().add(flecs::Singleton); } void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, - Ogre::Camera *camera, Ogre::RenderWindow *window) + Ogre::Camera *camera, Ogre::RenderWindow *window) { std::cout << "Setup GameData\n"; setup_minimal(); @@ -112,58 +112,58 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, // ecs.set({}); std::cout << "Setup GameData done\n"; - ecs.system("SpawnPlayer").kind(flecs::OnUpdate).interval(0.5f).run([&](flecs::iter &it) { - flecs::entity player = - ECS::get().getPlayer(); - if (!player.is_valid()) { - /* Create player */ - Ogre::Vector3 position; - JPH::BodyID id; - long x, y; - Ogre::TerrainGroup *tg = - ECS::get().mTerrainGroup; - if (tg->isDerivedDataUpdateInProgress()) - return; - tg->convertWorldPositionToTerrainSlot( - Ogre::Vector3(0, 0, 4), &x, &y); - Ogre::Terrain *terrain = tg->getTerrain(x, y); - if (terrain && terrain->isLoaded()) { - if (PhysicsModule::raycastQuery( - Ogre::Vector3(0, 500, 4), - Ogre::Vector3(0, -500, 4), position, - id)) { - if (position.y < -10.0f && - position.y > -50.0f) { - player = - ecs.get_mut< - CharacterManagerModule>() - .createPlayer( - { position.x, - position.y, - position.z }, - Ogre::Quaternion( - Ogre::Radian( - Ogre::Math:: - PI), - Ogre::Vector3:: - UNIT_Y)); - std::cout << position - << std::endl; - // OgreAssert(false, "spawn"); - } - } - } - } - }); + ecs.system("SpawnPlayer").kind(flecs::OnUpdate).interval(0.5f).run([&](flecs::iter &it) { + flecs::entity player = + ECS::get().getPlayer(); + if (!player.is_valid()) { + /* Create player */ + Ogre::Vector3 position; + JPH::BodyID id; + long x, y; + Ogre::TerrainGroup *tg = + ECS::get().mTerrainGroup; + if (tg->isDerivedDataUpdateInProgress()) + return; + tg->convertWorldPositionToTerrainSlot( + Ogre::Vector3(0, 0, 4), &x, &y); + Ogre::Terrain *terrain = tg->getTerrain(x, y); + if (terrain && terrain->isLoaded()) { + if (PhysicsModule::raycastQuery( + Ogre::Vector3(0, 500, 4), + Ogre::Vector3(0, -500, 4), position, + id)) { + if (position.y < -10.0f && + position.y > -50.0f) { + player = + ecs.get_mut< + CharacterManagerModule>() + .createPlayer( + { position.x, + position.y, + position.z }, + Ogre::Quaternion( + Ogre::Radian( + Ogre::Math:: + PI), + Ogre::Vector3:: + UNIT_Y)); + std::cout << position + << std::endl; + // OgreAssert(false, "spawn"); + } + } + } + } + }); } void setupInteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, - Ogre::Camera *camera, Ogre::RenderWindow *window) + Ogre::Camera *camera, Ogre::RenderWindow *window) { } void setupInventoryScene(Ogre::SceneManager *scnMgr, - Ogre::SceneNode *cameraNode, Ogre::Camera *camera, - Ogre::RenderWindow *window) + Ogre::SceneNode *cameraNode, Ogre::Camera *camera, + Ogre::RenderWindow *window) { } @@ -173,6 +173,7 @@ void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, std::cout << "Setup Editor\n"; setup_minimal(); ecs.component().add(flecs::Singleton); + ecs.component().add(flecs::Singleton); ecs.import (); ecs.import (); ecs.import (); @@ -218,6 +219,9 @@ void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, ecs.set({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(), (int)window->getHeight(), false }); ecs.set({ cameraNode, camera, false }); +#if 0 + ecs.set({ 0 }); +#endif ecs.add(); ecs.add(); ecs.add(); @@ -252,11 +256,11 @@ flecs::world get() bool Vector3::zeroLength() const { float l = x * x + y * y + z * z; - return (l < 1e-06 * 1e-06); + return (l < 1e-06 * 1e-06); } void setupEditorAlt(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, - Ogre::Camera *camera, Ogre::RenderWindow *window) + Ogre::Camera *camera, Ogre::RenderWindow *window) { } diff --git a/src/gamedata/StaticGeometryModule.cpp b/src/gamedata/StaticGeometryModule.cpp index 6d3ee0e..d1276fb 100644 --- a/src/gamedata/StaticGeometryModule.cpp +++ b/src/gamedata/StaticGeometryModule.cpp @@ -12,6 +12,7 @@ #include "TerrainModule.h" #include "physics.h" #include "PhysicsModule.h" +#include "items.h" #include "StaticGeometryModule.h" namespace ECS @@ -24,83 +25,83 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs) ecs.module(); ecs.component(); ecs.component(); - ecs.component().on_remove([](flecs::entity e, - TerrainItemNode &item) { - if (item.itemNode) { - item.itemNode->destroyAllChildrenAndObjects(); - item.itemNode->getCreator()->destroySceneNode( - item.itemNode); - item.itemNode = nullptr; - } - if (item.geo) { - ECS::get().mScnMgr->destroyStaticGeometry( - item.geo); - item.geo = nullptr; - } - }); + ecs.component().on_remove([](flecs::entity e, + TerrainItemNode &item) { + if (item.itemNode) { + item.itemNode->destroyAllChildrenAndObjects(); + item.itemNode->getCreator()->destroySceneNode( + item.itemNode); + item.itemNode = nullptr; + } + if (item.geo) { + ECS::get().mScnMgr->destroyStaticGeometry( + item.geo); + item.geo = nullptr; + } + }); + ecs.component(); ecs.import (); - ecs.observer("LoadTerrainItems") + ecs.observer("LoadTerrainItems") .event(flecs::OnSet) - .each([&](const Terrain &terrain) { - if (terrain.mTerrainGroup && !itemsLoaded) { - loadItems(); - itemsLoaded = true; - } + .each([&](const Terrain &terrain) { + if (terrain.mTerrainGroup && !itemsLoaded) { + loadItems(); + itemsLoaded = true; + } }); if (!Ogre::MeshLodGenerator::getSingletonPtr()) new Ogre::MeshLodGenerator(); - ecs.system("AddGeometryQueue").kind(flecs::OnUpdate).run([&](flecs::iter &it) { - std::list items; - if (!ECS::get().mTerrainGroup) - return; - if (!itemsLoaded) { - loadItems(); - itemsLoaded = true; - return; - } - std::list > output; - while (!addQueue.empty()) { - std::pair item = addQueue.front(); - std::pair slot = { item.first, - item.second }; - flecs::entity parent = - ECS::get() - .query_builder() - .build() - .find([&slot](const TerrainSlotParent - &parent) { - return parent.slot == slot; - }); - if (parent.is_valid()) { - ECS::get() - .query_builder() - .with(flecs::ChildOf, parent) - .without() - .write() - .build() - .each([&](flecs::entity e, - const TerrainItem &item) { - std::cout << "item: " << e.id() - << std::endl; - items.push_back(e); - }); - for (auto e : items) { - createItemGeometry(e); - } - addQueue.pop_front(); - } else { - output.push_back(item); - addQueue.pop_front(); - } - } - OgreAssert(addQueue.empty(), "queue is not empty"); - if (!output.empty()) - addQueue = output; - }); + ecs.system("AddGeometryQueue").kind(flecs::OnUpdate).run([&](flecs::iter &it) { + std::list items; + if (!ECS::get().mTerrainGroup) + return; + if (!itemsLoaded) { + loadItems(); + itemsLoaded = true; + return; + } + std::list > output; + while (!addQueue.empty()) { + std::pair item = addQueue.front(); + std::pair slot = { item.first, + item.second }; + flecs::entity parent = + ECS::get() + .query_builder() + .build() + .find([&slot](const TerrainSlotParent + &parent) { + return parent.slot == slot; + }); + if (parent.is_valid()) { + items.clear(); + ECS::get() + .query_builder() + .with(flecs::ChildOf, parent) + .without() + .write() + .build() + .each([&](flecs::entity e, + const TerrainItem &item) { + items.push_back(e); + }); + for (auto e : items) { + createItemGeometry(e); + } + addQueue.pop_front(); + } else { + output.push_back(item); + addQueue.pop_front(); + } + } + OgreAssert(addQueue.empty(), "queue is not empty"); + if (!output.empty()) + addQueue = output; + }); } void StaticGeometryModule::addGeometryForSlot(long x, long y) { - addQueue.push_back({ x, y }); + addQueue.push_back({ x, y }); } void StaticGeometryModule::removeGeometryForSlot(long x, long y) { @@ -158,32 +159,6 @@ const Ogre::String &StaticGeometryModule::getItemProperties(flecs::entity id) OgreAssert(id.is_valid(), "bad id"); return id.get().properties; } -static void to_json(nlohmann::json &j, const Ogre::Vector3 &position) -{ - j["x"] = position.x; - j["y"] = position.y; - j["z"] = position.z; -} -static void to_json(nlohmann::json &j, const Ogre::Quaternion &orientation) -{ - j["w"] = orientation.w; - j["x"] = orientation.x; - j["y"] = orientation.y; - j["z"] = orientation.z; -} -static void from_json(const nlohmann::json &j, Ogre::Vector3 &position) -{ - position.x = j["x"].get(); - position.y = j["y"].get(); - position.z = j["z"].get(); -} -static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation) -{ - orientation.w = j["w"].get(); - orientation.x = j["x"].get(); - orientation.y = j["y"].get(); - orientation.z = j["z"].get(); -} void StaticGeometryModule::saveItems() { Ogre::String path = "resources/buildings/items.list"; @@ -209,6 +184,22 @@ void StaticGeometryModule::saveItems() to_json(jitem["position"], item.position); to_json(jitem["orientation"], item.orientation); to_json(jitem["properties"], item.properties); + jitem["objects"] = nlohmann::json::array(); + ECS::get() + .query_builder() + .with(flecs::ChildOf, e) + .build() + .each([&](flecs::entity obje, + const TerrainItem &objItem) { + nlohmann::json jobjitem; + to_json(jobjitem["position"], + objItem.position); + to_json(jobjitem["orientation"], + objItem.orientation); + to_json(jobjitem["properties"], + objItem.properties); + jitem["objects"].push_back(jobjitem); + }); jitemlist.push_back(jitem); }); fout << jitemlist.dump(); @@ -236,7 +227,7 @@ void StaticGeometryModule::loadItems() from_json(v["position"], position); from_json(v["orientation"], orientation); properties = v["properties"].get(); - std::cout << v.dump(4) << std::endl; + std::cout << v.dump(4) << std::endl; long x, y; ECS::get() .mTerrainGroup->convertWorldPositionToTerrainSlot( @@ -253,15 +244,34 @@ void StaticGeometryModule::loadItems() if (!slot.is_valid()) slot = ECS::get().entity().set( { pos }); - OgreAssert(slot.is_valid(), "Failed to create slot"); - flecs::entity item = - ECS::get().entity().child_of(slot).set( - { position, orientation, properties }); + OgreAssert(slot.is_valid(), "Failed to create slot"); + flecs::entity item = + ECS::get().entity().child_of(slot).set( + { position, orientation, properties }); + if (v.find("objects") != v.end()) { + for (auto &obj : v["objects"]) { + Ogre::Vector3 objposition; + Ogre::Quaternion objorientation; + Ogre::String objproperties; + from_json(obj["position"], objposition); + from_json(obj["orientation"], objorientation); + objproperties = + obj["properties"].get(); + flecs::entity itemObj = + ECS::get() + .entity() + .child_of(item) + .set( + { objposition, + objorientation, + objproperties }); + } + } std::cout << "createItem: " << x << " " << y << " " << item.id() << std::endl; std::cout << "position: " << item.id() << " " << position << std::endl; - } + } } void StaticGeometryModule::getItemPositionPerSlot( long x, long y, std::list *positions) @@ -307,207 +317,13 @@ void StaticGeometryModule::getItemsProperties( } void StaticGeometryModule::createItemGeometry(flecs::entity e) { - OgreAssert(!e.has(), "Geometry already created"); - Ogre::String props = e.get().properties; - nlohmann::json jp = nlohmann::json::parse(props); - Ogre::SceneNode *itemNode = ECS::get() - .mScnMgr->getRootSceneNode() - ->createChildSceneNode(); - itemNode->_setDerivedPosition(e.get().position); - itemNode->_setDerivedOrientation(e.get().orientation); - if (jp.find("staticMesh") != jp.end()) { - Ogre::String meshName = jp["staticMesh"].get(); - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) { - Ogre::Entity *ent = - ECS::get().mScnMgr->createEntity( - mesh); - itemNode->attachObject(ent); - } - } else if (jp.find("type") != jp.end()) { - Ogre::String itemType = jp["type"].get(); - std::cout << "type: " << itemType << std::endl; - std::cout << "props: " << props << std::endl; - if (itemType == "harbour") { - Ogre::StaticGeometry *geo = - ECS::get() - .mScnMgr->createStaticGeometry( - "harbour_" + - Ogre::StringConverter::toString( - e.id())); - geo->setRegionDimensions(Ogre::Vector3(140, 140, 140)); - Ogre::Vector3 geoposition = - itemNode->_getDerivedPosition(); - geoposition.y = 0.0f; - geo->setOrigin(geoposition); - createHarbour(e, itemNode, geo); - e.set({ itemNode, geo }); - } else if (itemType == "temple") { - Ogre::StaticGeometry *geo = - ECS::get() - .mScnMgr->createStaticGeometry( - "harbour_" + - Ogre::StringConverter::toString( - e.id())); - geo->setRegionDimensions(Ogre::Vector3(140, 140, 140)); - Ogre::Vector3 geoposition = - itemNode->_getDerivedPosition(); - geoposition.y = 0.0f; - geo->setOrigin(geoposition); - createTemple(e, itemNode, geo); - e.set({ itemNode, geo }); - } - } else { - std::cout << "can't build item" << std::endl; - std::cout << "props: " << props << std::endl; - OgreAssert(false, "can't create item"); - } + Geometry::createItemGeometry(e); } void StaticGeometryModule::destroyItemGeometry(flecs::entity e) { - OgreAssert(e.has(), "No geometry created"); -#if 0 - ECS::get().mScnMgr->destroyStaticGeometry() - e.get().geo->destroy(); - e.get_mut().geo = nullptr; - e.modified(); -#endif - e.remove(); + Geometry::destroyItemGeometry(e); } -void StaticGeometryModule::setupLods(Ogre::LodConfig &config) -{ - // config.advanced.useCompression = false; - // config.advanced.useVertexNormals = true; - config.advanced.preventPunchingHoles = true; - config.advanced.preventBreakingLines = true; - config.createGeneratedLodLevel(10, 0.15f); - config.createGeneratedLodLevel(30, 0.25f); - config.createGeneratedLodLevel(60, 0.36f); - config.createGeneratedLodLevel(150, 0.65f); - config.advanced.useBackgroundQueue = false; - Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config); -} - -void StaticGeometryModule::createPlazza(flecs::entity e, - const nlohmann::json &district, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - Ogre::MaterialPtr harbourMaterial; - harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id())); - Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); - Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); - const nlohmann::json &jp = district; - Procedural::TriangleBuffer tb; - float centerOffset = 0.0f; - float plazzaRadius = 5.0f; - float plazzaHeight = 0.2f; - float plazzaElevation = 0.0f; - if (jp.find("centerOffset") != jp.end()) - centerOffset = jp["centerOffset"].get(); - if (jp.find("plazzaRadius") != jp.end()) - plazzaRadius = jp["plazzaRadius"].get(); - if (jp.find("plazzaHeight") != jp.end()) - plazzaHeight = jp["plazzaHeight"].get(); - if (jp.find("plazzaElevation") != jp.end()) - plazzaElevation = jp["plazzaElevation"].get(); - if (plazzaHeight < 0.1f) - plazzaHeight = 0.1f; - if (plazzaRadius < 5.0f) - plazzaRadius = 5.0f; - Ogre::Vector3 worldPlazzaCenter = worldPosition; -#if 0 - Procedural::CylinderGenerator() - .setHeight(plazzaHeight) - .setRadius(plazzaRadius) - .setEnableNormals(true) - .setPosition(Ogre::Vector3( - 0.0f, plazzaHeight / 2.0f + plazzaElevation, 0.0f)) - .addToTriangleBuffer(tb); -#endif - float mh = 4.0f; - Procedural::Shape *plazzaShape = new Procedural::Shape(); - plazzaShape->addPoint(0, -plazzaHeight - mh - mh); - plazzaShape->addPoint(plazzaRadius * 0.5f + mh, - -plazzaHeight - mh - mh); - plazzaShape->addPoint(plazzaRadius + mh, -plazzaHeight - mh); - plazzaShape->addPoint(plazzaRadius, -plazzaHeight); - plazzaShape->addPoint(plazzaRadius, 0.0f); - plazzaShape->addPoint(plazzaRadius - 0.1f, 0.1f); - plazzaShape->addPoint(plazzaRadius - mh + 0.1f, plazzaHeight); - plazzaShape->addPoint(plazzaRadius - mh, plazzaHeight + 0.1f); - plazzaShape->addPoint(plazzaRadius * 0.5f + mh, plazzaHeight); - plazzaShape->addPoint(0, plazzaHeight); - Procedural::Lathe() - .setShapeToExtrude(plazzaShape) - .setEnableNormals(true) - .setPosition(Ogre::Vector3( - 0.0f, plazzaHeight / 2.0f + plazzaElevation, 0.0f)) - .setNumSeg(24) - .addToTriangleBuffer(tb); - for (auto &v : tb.getVertices()) { - v.mUV *= 0.08f; - v.mUV.x += 0.41f; - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } - Ogre::String meshName = - "plazzaMesh" + Ogre::StringConverter::toString(e.id()); - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) - Ogre::MeshManager::getSingleton().remove(mesh); - mesh = tb.transformToMesh(meshName); - Ogre::LodConfig config(mesh); - setupLods(config); - Ogre::Entity *pathEnt = - ECS::get().mScnMgr->createEntity(mesh); - pathEnt->setMaterial(harbourMaterial); - geo->addEntity(pathEnt, worldPlazzaCenter, worldOrientation, - Ogre::Vector3(1, 1, 1)); -} -struct harbourMaker { - Ogre::Entity *planks, *pillar, *beam; - Ogre::String makeName(const Ogre::String &base, flecs::entity e) - { - return base + Ogre::StringConverter::toString(e.id()); - } - harbourMaker(flecs::entity e) - { - Ogre::String planksName = makeName("Plank", e); - Ogre::String beamName = makeName("Beam", e); - Ogre::String pillarName = makeName("Pillar", e); - std::pair sets[] = { - { planksName, &planks }, - { beamName, &beam }, - { pillarName, &pillar } - }; - std::map meshes = { - { planksName, "pier-plank.glb" }, - { beamName, "pier-beam.glb" }, - { pillarName, "pier-pillar.glb" }, - }; - for (auto &p : sets) { - if (ECS::get().mScnMgr->hasEntity(p.first)) - *p.second = - ECS::get() - .mScnMgr->getEntity(p.first); - else { - *p.second = ECS::get() - .mScnMgr->createEntity( - p.first, - meshes.at(p.first)); - Ogre::MeshPtr mesh = (*p.second)->getMesh(); - Ogre::LodConfig config(mesh); - StaticGeometryModule::setupLods(config); - } - } - } -}; struct TiledMeshes { struct Tile { Ogre::String materialName; @@ -913,646 +729,5 @@ out:; { } }; -void StaticGeometryModule::createBridge(flecs::entity e, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - int i; - Procedural::TriangleBuffer tb; - Ogre::MaterialPtr harbourMaterial; - harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id())); - float stepWidth = 12.0f; - float stepHeight = 0.15f; - float stepDepth = 0.25f; - float stairsHeight = 0.0f; - float stairsOffset = 0.0f; - std::vector pierPath; - Ogre::String props = e.get().properties; - nlohmann::json jp = nlohmann::json::parse(props); - if (jp.find("stairsHeight") != jp.end()) - stairsHeight = jp["stairsHeight"].get(); - if (jp.find("stairsOffset") != jp.end()) - stairsOffset = jp["stairsOffset"].get(); - if (jp.find("stepHeight") != jp.end()) - stepHeight = jp["stepHeight"].get(); - if (jp.find("stepDepth") != jp.end()) - stepDepth = jp["stepDepth"].get(); - if (jp.find("pierPath") != jp.end()) { - pierPath.reserve(jp["pierPath"].size()); - for (auto &jpt : jp["pierPath"]) { - Ogre::Vector3 pt; - from_json(jpt, pt); - pierPath.push_back(pt); - } - } -#if 1 - Procedural::Shape *pierShape = new Procedural::Shape(); - pierShape->addPoint(8.f, -0.7f); - pierShape->addPoint(6.f, 0.7f); - pierShape->addPoint(6.05f, 0.65f); - pierShape->addPoint(0.f, 0.6f); - pierShape->addPoint(-6.05f, 0.65f); - pierShape->addPoint(-6.0f, 0.7f); - pierShape->addPoint(-8.f, -0.7f); - pierShape->close(); - - Procedural::CubicHermiteSpline3 *pierCurve; - Procedural::Path pierCurvePath; - if (jp.find("pierPath") != jp.end()) { - pierPath.reserve(jp["pierPath"].size()); - pierCurve = new Procedural::CubicHermiteSpline3(); - // pierCurve = new Procedural::RoundedCornerSpline3(); -#if 0 - { - int i; - for (i = 0; i < 5; i++) { - Ogre::Vector3 pt; - from_json(jp["pierPath"][i], pt); - pierPath.push_back(pt); - pierCurve->addPoint( - pt, pt - Ogre::Vector3(0, 0, -1), - pt + Ogre::Vector3(0, 0, 1)); - } - Ogre::Vector3 pt2; - from_json(jp["pierPath"].back(), pt2); - pierPath.push_back(pt2); - pierCurve->addPoint(pt2); - for (const auto &m : pierPath) { - std::cout << m << std::endl; - } - } -#endif -#if 1 - for (auto &jpt : jp["pierPath"]) { - Ogre::Vector3 pt; - from_json(jpt, pt); - pierPath.push_back(pt); - pierCurve->addPoint(pt, Ogre::Vector3(0, 0, 1)); - // pierCurve->addPoint(pt); - } -#endif - OgreAssert(pierPath.size() > 0, "empty path"); - // pierCurve->setNumSeg(8); - pierCurvePath = pierCurve->realizePath(); - // V - Procedural::Track shapeTextureTrack = - Procedural::Track(Procedural::Track::AM_POINT) - .addKeyFrame(0, 0.0f) - .addKeyFrame(6, 0.1f); - // U - Procedural::Track pathTextureTrack = - Procedural::Track(Procedural::Track::AM_POINT) - .addKeyFrame(0, 0.45f) - .addKeyFrame(6, 0.9f); - Procedural::Extruder extruder; - extruder.setShapeTextureTrack(&shapeTextureTrack) - .setPathTextureTrack(&pathTextureTrack) - .setShapeToExtrude(pierShape) - .setExtrusionPath(&pierCurvePath) - .setEnableNormals(true) - .setUTile(1.0f) - .setVTile(1.0f) - .addToTriangleBuffer(tb); - for (auto &v : tb.getVertices()) { - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.41f, 0.9f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } -#if 0 - for (const auto &v : tb.getVertices()) { - std::cout << "UV: " << v.mUV << std::endl; - } - OgreAssert(false, "uvs"); -#endif -#if 0 - Ogre::LodConfig config(extrudedMesh); - setupLods(config); - Ogre::Entity *pathEnt = - ECS::get().mScnMgr->createEntity( - extrudedMesh); - pathEnt->setMaterial(harbourMaterial); - float xofft = 0.0f; - Ogre::Vector3 worldPosition = - sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * 0.0f; - Ogre::Quaternion worldOrientation = - sceneNode->_getDerivedOrientation(); - Ogre::Vector3 xoffset = - worldOrientation * (Ogre::Vector3::UNIT_X * xofft); - geo->addEntity(pathEnt, worldPosition + xoffset, - worldOrientation, Ogre::Vector3(1, 1, 1)); -#endif - } -#else - for (i = 0; i < pierPath.size(); i++) { - if (i == 0) - continue; - Ogre::Vector3 lvec = pierPath[i] - pierPath[i - 1]; - Ogre::Vector3 xvec = Ogre::Vector3::UNIT_Y.crossProduct(lvec); - Ogre::Vector3 n = lvec.crossProduct(xvec).normalisedCopy(); - Ogre::Vector3 pos = (pierPath[i] + pierPath[i - 1]) * 0.5f; - Procedural::PlaneGenerator() - .setNormal(n) - .setNumSegX(2) - .setNumSegY(2) - .setSizeX(1) - .setSizeY(1) - .setPosition(pos) - .addToTriangleBuffer(tb); - } -#endif - Ogre::String meshName = - "pierPathMesh" + Ogre::StringConverter::toString(e.id()); - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) - Ogre::MeshManager::getSingleton().remove(mesh); - mesh = tb.transformToMesh(meshName); - Ogre::LodConfig config(mesh); - setupLods(config); - Ogre::Entity *pathEnt = - ECS::get().mScnMgr->createEntity(mesh); - pathEnt->setMaterial(harbourMaterial); - float xofft = 0.0f; - Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * 0.0f; - Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); - Ogre::Vector3 xoffset = - worldOrientation * (Ogre::Vector3::UNIT_X * xofft); - geo->addEntity(pathEnt, worldPosition + xoffset, worldOrientation, - Ogre::Vector3(1, 1, 1)); - ECS::get().mScnMgr->destroyEntity(pathEnt); -} -void StaticGeometryModule::createPier(flecs::entity e, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - Ogre::MaterialPtr harbourMaterial; - harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id())); - harbourMaker hm(e); - Ogre::Vector3 position = sceneNode->_getDerivedPosition(); - Ogre::String props = e.get().properties; - nlohmann::json jp = nlohmann::json::parse(props); - float pierHeight = 0.0f, pierLength = 6.0f, pierDepth = 6.0f; - if (jp.find("pierLength") != jp.end()) - pierLength = jp["pierLength"].get(); - if (jp.find("pierDepth") != jp.end()) - pierDepth = jp["pierDepth"].get(); - if (jp.find("pierHeight") != jp.end()) - pierHeight = jp["pierHeight"].get(); - Procedural::TriangleBuffer tb; - float plankLength = 2.0f; - float plankWidth = 4.01f; - float plankHeight = 0.3f; - const float beamLength = 6.0f; - const float beamWidth = 5.5f; - float beamHeight = 0.3f; - if (pierLength < 12.0f) - pierLength = 12.0f; - auto processGrid = [&sceneNode, &geo](float stepLength, float length, - float zoffset, float yofft, - float xofft, Ogre::Entity *ent) { - float step = 0.0f; - while (step < length) { - Ogre::Vector3 worldPosition = - sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * - (step + zoffset); - Ogre::Quaternion worldOrientation = - sceneNode->_getDerivedOrientation(); - Ogre::Vector3 xoffset = worldOrientation * - (Ogre::Vector3::UNIT_X * xofft); - Ogre::Vector3 yoffset = worldOrientation * - (Ogre::Vector3::UNIT_Y * yofft); - geo->addEntity(ent, worldPosition + xoffset + yoffset, - worldOrientation, - Ogre::Vector3(1, 1, 1)); - step += stepLength; - } - }; - float xofftPlanks; - for (xofftPlanks = -plankWidth; xofftPlanks <= plankWidth; - xofftPlanks += plankWidth) - processGrid(plankLength, pierLength, plankLength / 2.0f, - plankHeight / 2.0f + beamHeight / 2.0f, xofftPlanks, - hm.planks); - { - Procedural::TriangleBuffer tbPillars, tbBollards; - float step = 0.0f; - while (step < pierLength) { - // pillars - Procedural::BoxGenerator() - .setSizeX(0.5f) - .setSizeY(pierDepth) - .setSizeZ(0.5f) - .setEnableNormals(true) - .setPosition(Ogre::Vector3( - -5.0f, -pierDepth / 2.0f + 0.5f, step)) - .addToTriangleBuffer(tbPillars); - Procedural::BoxGenerator() - .setSizeX(0.5f) - .setSizeY(pierDepth) - .setSizeZ(0.5f) - .setEnableNormals(true) - .setPosition(Ogre::Vector3( - 5.0f, -pierDepth / 2.0f + 0.5f, step)) - .addToTriangleBuffer(tbPillars); - step += 6.0f; - } - step = pierLength - 0.5f; - while (step >= 0.0f) { - // bollards - Procedural::CylinderGenerator() - .setHeight(0.8f) - .setRadius(0.3f) - .setPosition(Ogre::Vector3( - -5.3f, 0.4f + 0.5f + 0.1f, step)) - .addToTriangleBuffer(tbBollards); - Procedural::CylinderGenerator() - .setHeight(0.8f) - .setRadius(0.3f) - .setPosition(Ogre::Vector3( - 5.3f, 0.4f + 0.5f + 0.1f, step)) - .addToTriangleBuffer(tbBollards); - step -= 12.0f; - } - // beams - Procedural::BoxGenerator() - .setSizeX(0.5f) - .setSizeY(beamHeight) - .setSizeZ(pierLength) - .setEnableNormals(true) - .setPosition(Ogre::Vector3(-5.0f, - 0.2 + beamHeight / 2.0f, - pierLength / 2.0f)) - .addToTriangleBuffer(tbPillars); - Procedural::BoxGenerator() - .setSizeX(0.5f) - .setSizeY(beamHeight) - .setSizeZ(pierLength) - .setEnableNormals(true) - .setPosition(Ogre::Vector3(5.0f, - 0.2 + beamHeight / 2.0f, - pierLength / 2.0f)) - .addToTriangleBuffer(tbPillars); - for (auto &v : tbPillars.getVertices()) { - v.mUV *= 0.08f; - v.mUV += Ogre::Vector2(0.01f, 0.01f); - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.0f, 0.1f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } - for (auto &v : tbBollards.getVertices()) { - v.mUV *= 0.08f; - v.mUV.x += 0.21f; - v.mUV.y += 0.01f; - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.2f, 0.3f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } - tb.append(tbPillars); - tb.append(tbBollards); - } - Ogre::String meshName = - "pier" + Ogre::StringConverter::toString(e.id()); - { - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) - Ogre::MeshManager::getSingleton().remove(mesh); - - mesh = tb.transformToMesh(meshName); - Ogre::LodConfig config(mesh); - // config.advanced.useCompression = false; - // config.advanced.useVertexNormals = true; - setupLods(config); - Ogre::Entity *ent = - ECS::get().mScnMgr->createEntity(mesh); - ent->setMaterial(harbourMaterial); - float xofft = 0.0f; - Ogre::Vector3 worldPosition = - sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * 0.0f; - Ogre::Quaternion worldOrientation = - sceneNode->_getDerivedOrientation(); - Ogre::Vector3 xoffset = - worldOrientation * (Ogre::Vector3::UNIT_X * xofft); - geo->addEntity(ent, worldPosition + xoffset, worldOrientation, - Ogre::Vector3(1, 1, 1)); - } - std::cout << meshName << std::endl; -} - -void StaticGeometryModule::createHarbour(flecs::entity e, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - std::cout << "createHarbour " << e.id() << std::endl; - Ogre::MaterialPtr harbourMaterial; - harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id())); - if (!harbourMaterial) { - Procedural::TextureBuffer colorAtlas(1024); - Procedural::RectangleTexture drawAtlas(&colorAtlas); - Ogre::ColourValue normalYellow(0.8f, 0.6f, 0, 1); - Ogre::ColourValue roadBrown(0.4f, 0.3f, 0.3f, 1); - Ogre::ColourValue bollardGrey(0.2f, 0.2f, 0.2f, 1); - drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) - .setColour(normalYellow) - .process(); - drawAtlas.setRectangle(Ogre::RealRect(0.2f, 0.0f, 0.3f, 1.0f)) - .setColour(bollardGrey) - .process(); - drawAtlas.setRectangle(Ogre::RealRect(0.4f, 0.0f, 1.0f, 1.0f)) - .setColour(roadBrown) - .process(); - Ogre::TexturePtr pierTexture = colorAtlas.createTexture( - "proceduralTextureHarbour" + - Ogre::StringConverter::toString(e.id())); - colorAtlas.saveImage("tmp.png"); - harbourMaterial = - Ogre::MaterialManager::getSingletonPtr()->create( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id()), - Ogre::ResourceGroupManager:: - DEFAULT_RESOURCE_GROUP_NAME); - harbourMaterial->getTechnique(0)->getPass(0)->setShininess(0); - harbourMaterial->getTechnique(0)->getPass(0)->setDiffuse( - Ogre::ColourValue::White); - harbourMaterial->getTechnique(0)->getPass(0)->setSpecular( - Ogre::ColourValue(1.0f, 1.0f, 0.9f)); - harbourMaterial->getTechnique(0) - ->getPass(0) - ->createTextureUnitState( - "proceduralTextureHarbour" + - Ogre::StringConverter::toString(e.id())); - if (Ogre::RTShader::ShaderGenerator::initialize()) { - harbourMaterial->prepare(); - Ogre::RTShader::ShaderGenerator *mShaderGenerator = - Ogre::RTShader::ShaderGenerator:: - getSingletonPtr(); - mShaderGenerator->createShaderBasedTechnique( - *harbourMaterial, - Ogre::MaterialManager::DEFAULT_SCHEME_NAME, - Ogre::RTShader::ShaderGenerator:: - DEFAULT_SCHEME_NAME); - Ogre::RTShader::RenderState *pMainRenderState = - mShaderGenerator->getRenderState( - Ogre::RTShader::ShaderGenerator:: - DEFAULT_SCHEME_NAME, - *harbourMaterial); - } - } - { - Ogre::String props = e.get().properties; - nlohmann::json jp = nlohmann::json::parse(props); - float pierOffset = 0.0f; - float centerOffset = 0.0f; - float plazzaRadius = 5.0f; - bool plazza = false; - nlohmann::json jcenter = nlohmann::json::object(); - if (jp.find("center") != jp.end()) - jcenter = jp["center"]; - if (jcenter.find("plazzaRadius") != jcenter.end()) - plazzaRadius = jcenter["plazzaRadius"]; - if (jp.find("pierOffset") != jp.end()) - pierOffset = jp["pierOffset"].get(); - if (jp.find("plazza") != jp.end()) - plazza = jp["plazza"].get(); - if (jp.find("centerOffset") != jp.end()) - centerOffset = jp["centerOffset"].get(); - Ogre::Vector3 worldPosition = - sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * (pierOffset); - float xofft = 0.0f; - float stairLengthZ = worldPosition.y; - float stairsOffset = 0.0f; - stairsOffset = stairLengthZ; - jp["stairsHeight"] = worldPosition.y; - jp["stairsOffset"] = stairsOffset; - e.get_mut().properties = jp.dump(); - e.modified(); - worldPosition.y = 0.0f; - Ogre::Quaternion worldOrientation = - sceneNode->_getDerivedOrientation(); - Ogre::Vector3 xoffset = - worldOrientation * (Ogre::Vector3::UNIT_X * xofft); - Ogre::Vector3 zoffset = - worldOrientation * - (Ogre::Vector3::UNIT_Z * (stairsOffset - 1)); - Ogre::SceneNode *elevatorNode = - sceneNode->createChildSceneNode(); - Ogre::SceneNode *pierNode = sceneNode->createChildSceneNode(); - pierNode->_setDerivedPosition(worldPosition + zoffset + - xoffset); - Ogre::Vector3 worldPlazzaCenter = - sceneNode->_getDerivedPosition() + - sceneNode->_getDerivedOrientation() * - Ogre::Vector3::UNIT_Z * - (-centerOffset - plazzaRadius + 2.0f); - Ogre::SceneNode *centerNode = sceneNode->createChildSceneNode(); - centerNode->_setDerivedPosition(worldPlazzaCenter); - createBridge(e, elevatorNode, geo); - createPier(e, pierNode, geo); - createPlazza(e, jcenter, centerNode, geo); - createBuildings(e, jcenter, centerNode, geo); - } - geo->build(); -} - -void StaticGeometryModule::createBuildings(flecs::entity e, - const nlohmann::json &district, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - Ogre::MaterialPtr harbourMaterial; - harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialHarbour" + - Ogre::StringConverter::toString(e.id())); - nlohmann::json jbuildings = nlohmann::json::array(); - if (district.find("centerBuildings") != district.end()) - jbuildings = district["centerBuildings"]; - Ogre::Vector3 centerPosition = sceneNode->_getDerivedPosition(); - Ogre::Quaternion centerOrientation = - sceneNode->_getDerivedOrientation(); - int count = 0; - float baseHeight = 4.0f; - for (const auto &jb : jbuildings) { - Procedural::TriangleBuffer tb; - float angle = 0.0f; - float depth = 50.0f; - float width = 100.0f; - float distance = 100.0f; - float elevation = 0.0f; - std::cout << jb.dump() << std::endl; - if (jb.find("angle") != jb.end()) - angle = jb["angle"].get(); - if (jb.find("depth") != jb.end()) - depth = jb["depth"].get(); - if (jb.find("width") != jb.end()) - width = jb["width"].get(); - if (jb.find("distance") != jb.end()) - distance = jb["distance"].get(); - if (jb.find("elevation") != jb.end()) - elevation = jb["elevation"].get(); - - OgreAssert(width > 1 && depth > 1 && baseHeight > 1, - "Bad stuff happen"); - - Ogre::Quaternion rotation = Ogre::Quaternion( - Ogre::Degree(angle), Ogre::Vector3::UNIT_Y); - Ogre::Vector3 offset = centerOrientation * rotation * - (Ogre::Vector3::UNIT_Z * distance); - Procedural::BoxGenerator() - .setSizeX(width) - .setSizeY(baseHeight) - .setSizeZ(depth) - .setEnableNormals(true) - .setPosition(Ogre::Vector3( - 0.0f, -baseHeight / 2.0f + elevation, 0.0f)) - .addToTriangleBuffer(tb); - OgreAssert(tb.getVertices().size() > 8, "bad box"); - for (auto &v : tb.getVertices()) { - float c = 1.0 + 1.0 / (v.mPosition.y + baseHeight + - elevation); - v.mPosition.x *= c; - v.mPosition.z *= c; - v.mUV *= 0.08f; - v.mUV.x += 0.41f; - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } - Ogre::String meshName = - "lotbase" + Ogre::StringConverter::toString(count) + - "_" + Ogre::StringConverter::toString(e.id()); - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) - Ogre::MeshManager::getSingleton().remove(mesh); - mesh = tb.transformToMesh(meshName); - Ogre::LodConfig config(mesh); - setupLods(config); - Ogre::Entity *ent = - ECS::get().mScnMgr->createEntity( - "Ent" + meshName, mesh); - ent->setMaterial(harbourMaterial); - geo->addEntity(ent, centerPosition + offset, rotation, - Ogre::Vector3::UNIT_SCALE); - ECS::get().mScnMgr->destroyEntity(ent); - count++; - } -} - -void StaticGeometryModule::createTemple(flecs::entity e, - Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo) -{ - Ogre::String props = e.get().properties; - nlohmann::json jp = nlohmann::json::parse(props); - float size; - if (jp.find("size") != jp.end()) - size = jp["size"].get(); - Procedural::TriangleBuffer tb; - float elevation = 0.0f; - Ogre::MaterialPtr templeMaterial; - templeMaterial = Ogre::MaterialManager::getSingleton().getByName( - "proceduralMaterialTemple" + - Ogre::StringConverter::toString(e.id())); - if (!templeMaterial) { - Procedural::TextureBuffer colorAtlas(1024); - Procedural::RectangleTexture drawAtlas(&colorAtlas); - Ogre::ColourValue normalGreen(0.6f, 0.8f, 0.5f, 1); - drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) - .setColour(normalGreen) - .process(); - Ogre::TexturePtr pierTexture = colorAtlas.createTexture( - "proceduralTextureTemple" + - Ogre::StringConverter::toString(e.id())); - colorAtlas.saveImage("tmp2.png"); - templeMaterial = Ogre::MaterialManager::getSingletonPtr()->create( - "proceduralMaterialTemple" + - Ogre::StringConverter::toString(e.id()), - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - templeMaterial->getTechnique(0)->getPass(0)->setShininess(0); - templeMaterial->getTechnique(0)->getPass(0)->setDiffuse( - Ogre::ColourValue::White); - templeMaterial->getTechnique(0)->getPass(0)->setSpecular( - Ogre::ColourValue(1.0f, 1.0f, 0.9f)); - templeMaterial->getTechnique(0) - ->getPass(0) - ->createTextureUnitState( - "proceduralTextureTemple" + - Ogre::StringConverter::toString(e.id())); - if (Ogre::RTShader::ShaderGenerator::initialize()) { - templeMaterial->prepare(); - Ogre::RTShader::ShaderGenerator *mShaderGenerator = - Ogre::RTShader::ShaderGenerator:: - getSingletonPtr(); - mShaderGenerator->createShaderBasedTechnique( - *templeMaterial, - Ogre::MaterialManager::DEFAULT_SCHEME_NAME, - Ogre::RTShader::ShaderGenerator:: - DEFAULT_SCHEME_NAME); - Ogre::RTShader::RenderState *pMainRenderState = - mShaderGenerator->getRenderState( - Ogre::RTShader::ShaderGenerator:: - DEFAULT_SCHEME_NAME, - *templeMaterial); - } - } - Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); - Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); - Procedural::BoxGenerator() - .setSizeX(size) - .setSizeY(20) - .setSizeZ(size) - .setEnableNormals(true) - .setPosition(Ogre::Vector3(0.0f, -20 / 2.0f + elevation, 0.0f)) - .addToTriangleBuffer(tb); - OgreAssert(tb.getVertices().size() > 8, "bad box"); - for (auto &v : tb.getVertices()) { -#if 0 - float c = 1.0 + 1.0 / (v.mPosition.y + baseHeight + - elevation); - v.mPosition.x *= c; - v.mPosition.z *= c; -#endif - v.mUV *= 0.08f; - v.mUV.x += 0.01f; - v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.0f, 0.4f); - v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); - } - Ogre::String meshName = - "Temple" + Ogre::StringConverter::toString(e.id()); - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().getByName(meshName); - if (mesh) - Ogre::MeshManager::getSingleton().remove(mesh); - mesh = tb.transformToMesh(meshName); - Ogre::LodConfig config(mesh); - setupLods(config); - Ogre::Entity *ent = ECS::get().mScnMgr->createEntity( - "Ent" + meshName, mesh); - ent->setMaterial(templeMaterial); - geo->addEntity(ent, worldPosition, worldOrientation, - Ogre::Vector3::UNIT_SCALE); - ECS::get().mScnMgr->destroyEntity(ent); - geo->build(); - JPH::ShapeRefC shape = - JoltPhysicsWrapper::getSingleton().createMeshShape(mesh); - JPH::BodyID id = JoltPhysicsWrapper::getSingleton().createBody( - shape.GetPtr(), 0, sceneNode, JPH::EMotionType::Static, - Layers::NON_MOVING); - e.set(id); - JoltPhysicsWrapper::getSingleton().addBody(id, - JPH::EActivation::Activate); -} } diff --git a/src/gamedata/StaticGeometryModule.h b/src/gamedata/StaticGeometryModule.h index dffbdea..03c568d 100644 --- a/src/gamedata/StaticGeometryModule.h +++ b/src/gamedata/StaticGeometryModule.h @@ -19,7 +19,11 @@ struct TerrainItem { }; struct TerrainItemNode { Ogre::SceneNode *itemNode; - Ogre::StaticGeometry *geo; + Ogre::StaticGeometry *geo; +}; +struct TerrainItemMeshNode { + Ogre::SceneNode *itemNode; + Ogre::StaticGeometry *geo; }; struct StaticGeometryModule { @@ -43,16 +47,7 @@ struct StaticGeometryModule { static void getItemsProperties( std::list > *items); static void createItemGeometry(flecs::entity e); - static void destroyItemGeometry(flecs::entity e); - static void setupLods(Ogre::LodConfig &config); - static void createPlazza(flecs::entity e, const nlohmann::json &district, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); - static void createBridge(flecs::entity e, Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo); - static void createPier(flecs::entity e, Ogre::SceneNode *sceneNode, - Ogre::StaticGeometry *geo); - static void createHarbour(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); - static void createBuildings(flecs::entity e, const nlohmann::json &district, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); - static void createTemple(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); + static void destroyItemGeometry(flecs::entity e); }; } #endif diff --git a/src/gamedata/TerrainModule.cpp b/src/gamedata/TerrainModule.cpp index 34501a3..8f57779 100644 --- a/src/gamedata/TerrainModule.cpp +++ b/src/gamedata/TerrainModule.cpp @@ -278,7 +278,7 @@ public: float worldSize = terrain->getWorldSize(); float scaled = worldSize / (size - 1); Ogre::Vector3 bodyPosition = terrain->getPosition(); - // bodyPosition.y += (maxH + minH) / 2.0f; + // bodyPosition.y += (maxH + minH) / 2.0f; bodyPosition.x += worldSize / 2.0f; bodyPosition.z += worldSize / 2.0f; Ogre::Vector3 offset = @@ -338,21 +338,22 @@ public: } void update() { - std::lock_guard guard(mtx); - static bool created = false; + std::lock_guard guard(mtx); + static bool created = false; while (!collider_queue.empty()) { - Ogre::TerrainGroup *group = + Ogre::TerrainGroup *group = collider_queue.front().group; - if (group->isDerivedDataUpdateInProgress()) - break; - long x = collider_queue.front().x; + if (group->isDerivedDataUpdateInProgress()) + break; + long x = collider_queue.front().x; long y = collider_queue.front().y; - std::cout << x << " " << y << " " - << collider_queue.size() << std::endl; + std::cout << x << " " << y << " " + << collider_queue.size() << std::endl; Ogre::Terrain *terrain = group->getTerrain(x, y); Ogre::Vector3 worldPos; group->convertTerrainSlotToWorldPosition(x, y, &worldPos); +#if 0 std::cout << "terrain: " << terrain; if (terrain) std::cout @@ -360,7 +361,8 @@ public: << terrain->isLoaded() << " " << terrain->isDerivedDataUpdateInProgress() << std::endl; - if (terrain && terrain->getHeightData() && +#endif + if (terrain && terrain->getHeightData() && terrain->isLoaded() && !terrain->isDerivedDataUpdateInProgress()) { Ogre::LogManager::getSingleton().logError( @@ -368,8 +370,8 @@ public: Ogre::StringConverter::toString(x) + " " + Ogre::StringConverter::toString(y)); - // float minH = terrain->getMinHeight(); - // float maxH = terrain->getMaxHeight(); + // float minH = terrain->getMinHeight(); + // float maxH = terrain->getMaxHeight(); int size = terrain->getSize(); float worldSize = terrain->getWorldSize(); { @@ -440,22 +442,22 @@ public: #endif /* Spawn items */ StaticGeometryModule::addGeometryForSlot(x, y); - collider_queue.pop_front(); + collider_queue.pop_front(); } else { - /* Terrain data not ready maybe move to next terrain */ - gen_collider m = collider_queue.front(); + /* Terrain data not ready maybe move to next terrain */ + gen_collider m = collider_queue.front(); collider_queue.pop_front(); - collider_queue.push_back(m); - break; // allow system to move on + collider_queue.push_back(m); + break; // allow system to move on } - } - if (collider_queue.empty() && - !ECS::get().mTerrainReady) { - ECS::get_mut().mTerrainReady = true; - ECS::modified(); - } - } + } + if (collider_queue.empty() && + !ECS::get().mTerrainReady) { + ECS::get_mut().mTerrainReady = true; + ECS::modified(); + } + } }; class DummyPageProvider : public Ogre::PageProvider { public: diff --git a/src/gamedata/WaterModule.cpp b/src/gamedata/WaterModule.cpp index d0eb3bf..a0bf13a 100644 --- a/src/gamedata/WaterModule.cpp +++ b/src/gamedata/WaterModule.cpp @@ -468,6 +468,31 @@ WaterModule::WaterModule(flecs::world &ecs) std::cout << "Water setup done\n"; ECS::get().add(); }) + .on_remove([](flecs::entity e, WaterSurface &water) { + const Ogre::String renderTargetName = + "ReflectionRefractionTexture"; + ECS::get() + .mScnMgr->getRenderQueue() + ->setRenderableListener(nullptr); + water.mReflectionTexture->removeAllViewports(); + ECS::get().mScnMgr->destroyCamera( + water.mRefractionCamera); + ECS::get().mScnMgr->destroyCamera( + water.mRefractionDepthCamera); + ECS::get().mScnMgr->destroyCamera( + water.mReflectionCamera); + ECS::get().mScnMgr->destroyCamera( + water.mReflectionDepthCamera); + Ogre::TextureManager::getSingleton().remove( + renderTargetName); + water.mWaterNode->destroyAllChildrenAndObjects(); + ECS::get().mScnMgr->destroySceneNode( + water.mWaterNode); + Ogre::MaterialManager::getSingleton().remove( + "Water/Depth"); + Ogre::MaterialManager::getSingleton().remove( + "Water/Above"); + }) .add(flecs::Singleton); #if 0 ecs.component().add(flecs::Singleton); diff --git a/src/gamedata/items/CMakeLists.txt b/src/gamedata/items/CMakeLists.txt new file mode 100644 index 0000000..740dc0b --- /dev/null +++ b/src/gamedata/items/CMakeLists.txt @@ -0,0 +1,16 @@ +project(items) +find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG) +find_package(Bullet REQUIRED) +find_package(nlohmann_json REQUIRED) +find_package(OgreProcedural REQUIRED CONFIG) +add_library(items STATIC items.cpp harbour.cpp temple.cpp town.cpp) +target_include_directories(items PUBLIC .) +target_link_libraries(items PRIVATE + flecs::flecs_static + nlohmann_json::nlohmann_json + GameData + OgreMain + OgreBites + editor + physics +) \ No newline at end of file diff --git a/src/gamedata/items/harbour.cpp b/src/gamedata/items/harbour.cpp new file mode 100644 index 0000000..aa76bc4 --- /dev/null +++ b/src/gamedata/items/harbour.cpp @@ -0,0 +1,983 @@ +#include +#include +#include +#include +#include +#include +#include +#include "Components.h" +#include "GameData.h" +#include "EditorGizmoModule.h" +#include "TerrainModule.h" +#include "StaticGeometryModule.h" +#include "items.h" +#include "harbour.h" +namespace ECS +{ +namespace Items +{ +/* This is editor function */ +static bool findPierOffset(float &offset) +{ + Ogre::Vector3 basePos = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion baseRot = + ECS::get().sceneNode->_getDerivedOrientation(); + Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); + float length = 0.0f; + while (length < 250.0f) { + Ogre::Vector3 currentPosition = basePos + direction * length; + float height = ECS::get() + .mTerrainGroup->getHeightAtWorldPosition( + currentPosition); + if (height < -4.0f) { + offset = length; + break; + } + length += 2.0f; + } + return length < 250.0f; +} +static bool findPierOffsetAndLengthAndDepth(float &offset, float &length, + float &depth) +{ + if (!findPierOffset(offset)) + return false; + Ogre::Vector3 basePos = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion baseRot = + ECS::get().sceneNode->_getDerivedOrientation(); + Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); + length = 0.0f; + depth = 4.0f; + while (length < 60.0f) { + Ogre::Vector3 currentPosition = + basePos + direction * (offset + length); + float height = ECS::get() + .mTerrainGroup->getHeightAtWorldPosition( + currentPosition); + if (depth < -height) + depth = -height; + if (height > -4.0f) + break; + length += 6.0f; + } + return true; +} +static void findPierHeight(float maxLength, float &height) +{ + Ogre::Vector3 basePos = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion baseRot = + ECS::get().sceneNode->_getDerivedOrientation(); + Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); + float length = 0.0f; + height = 0.0f; + while (length < 60.0f) { + Ogre::Vector3 currentPosition = basePos + direction * (length); + float dheight = + ECS::get() + .mTerrainGroup->getHeightAtWorldPosition( + currentPosition); + if (height < dheight) + height = dheight; + length += 1.0f; + } +} +static void findPierPath(float pathLength, std::vector &path) +{ + float minHeight = 0.2f; + int i; + Ogre::Vector3 basePos = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion baseRot = + ECS::get().sceneNode->_getDerivedOrientation(); + Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1); + float length = 0.0f; + while (length < pathLength) { + Ogre::Vector3 currentPosition = basePos + direction * (length); + float dheight = + ECS::get() + .mTerrainGroup->getHeightAtWorldPosition( + currentPosition); + if (dheight < minHeight) + dheight = minHeight; + Ogre::Vector3 localOffset = Ogre::Vector3(0, 0, 1) * length; + Ogre::Vector3 localFromWorld = + ECS::get() + .sceneNode->convertWorldToLocalPosition( + { currentPosition.x, dheight, + currentPosition.z }); + path.push_back( + { localOffset.x, localFromWorld.y, localOffset.z }); + length += 2.0f; + } + if (path.size() == 0) { + path.push_back(Ogre::Vector3(0, 0, 0)); + path.push_back(Ogre::Vector3(0, 0, pathLength)); + } + std::vector tmppath = path; + path.clear(); + for (auto &pt : tmppath) { + if (path.size() == 0) + path.push_back(pt); + else { + if (path.back().z + 0.5f >= pt.z) + continue; + else + path.push_back(pt); + } + } + Ogre::Vector3 lastp = path.back(); + for (i = 1; i < path.size(); i++) { + Ogre::Vector3 &prev = path[i - 1]; + if (path[i].y > prev.y) + continue; + else if (path[i].y < prev.y) { + float d = prev.y - path[i].y; + if (d > 0.15f) + path[i].y = prev.y - 0.15f; + } + } + float dy = path.back().y - lastp.y; + if (dy > 0) + path.push_back({ lastp.x, lastp.y, path.back().z + dy * 3.0f }); + path.push_back({ path.back().x, path.back().y, path.back().z + 2.0f }); +} +bool editHarbourDistrict(nlohmann::json &jitem) +{ + float plazzaRadius = 5.0f; + float plazzaHeight = 0.2f; + float plazzaElevation = 0.0f; + float centerOffset = 0.0f; + bool plazza = false; + bool changed = false; + struct LotData { + float distance; + float angle; + float width; + float depth; + float elevation; + bool valid; + Ogre::String type; + Ogre::String properties; + }; + std::vector centerBuildings; + nlohmann::json &j = jitem; + if (j.find("centerOffset") != j.end()) + centerOffset = j["centerOffset"].get(); + if (j.find("plazza") != j.end()) + plazza = j["plazza"].get(); + if (j.find("plazzaRadius") != j.end()) + plazzaRadius = j["plazzaRadius"].get(); + if (j.find("plazzaHeight") != j.end()) + plazzaHeight = j["plazzaHeight"].get(); + if (j.find("plazzaElevation") != j.end()) + plazzaElevation = j["plazzaElevation"].get(); + if (j.find("centerBuildings") != j.end()) { + for (auto &jb : j["centerBuildings"]) { + LotData data; + data.distance = 100.0f; + data.angle = 0; + data.width = 50.0f; + data.depth = 50.0f; + data.elevation = 0.0f; + data.type = "base"; + data.properties = "{}"; + data.valid = true; + if (jb.find("distance") != jb.end()) + data.distance = jb["distance"].get(); + if (jb.find("angle") != jb.end()) + data.angle = jb["angle"].get(); + if (jb.find("width") != jb.end()) + data.width = jb["width"].get(); + if (jb.find("depth") != jb.end()) + data.depth = jb["depth"].get(); + if (jb.find("elevation") != jb.end()) + data.elevation = jb["elevation"].get(); + if (jb.find("type") != jb.end()) + data.type = jb["type"].get(); + if (jb.find("properties") != jb.end()) + data.properties = + jb["properties"].get(); + centerBuildings.push_back(data); + } + } + if (ImGui::SliderFloat("Center Offset", ¢erOffset, 0.0f, 100.0f)) + changed = true; + if (ImGui::Checkbox("Plazza", &plazza)) + changed = true; + if (plazza) { + if (ImGui::SliderFloat("Plazza Radius", &plazzaRadius, 5.0f, + 100.0f)) + changed = true; + if (ImGui::SliderFloat("Plazza Height", &plazzaHeight, 0.2f, + 1.0f)) + changed = true; + if (ImGui::SliderFloat("Plazza Elevation", &plazzaElevation, + -5.0f, 5.0f)) + changed = true; + } + int count = 0; + for (auto &b : centerBuildings) { + ImGui::Text("Lot %d", count); + Ogre::String ms = "##" + Ogre::StringConverter::toString(count); + if (ImGui::SliderFloat(("Lot distance" + ms).c_str(), + &b.distance, 0.0f, 100.0f)) + changed = true; + if (ImGui::SliderFloat(("Lot angle" + ms).c_str(), &b.angle, + 0.0f, 360.0f)) + changed = true; + if (ImGui::SliderFloat(("Width" + ms).c_str(), &b.width, 10.0f, + 200.0f)) + changed = true; + if (ImGui::SliderFloat(("Depth" + ms).c_str(), &b.depth, 10.0f, + 200.0f)) + changed = true; + if (ImGui::SliderFloat(("Elevation" + ms).c_str(), &b.elevation, + -10.0f, 10.0f)) + changed = true; + if (ImGui::SmallButton(("Delete" + ms).c_str())) + b.valid = false; + count++; + } + if (ImGui::SmallButton("Add building")) { + changed = true; + LotData data; + data.distance = 100.0f; + data.angle = 0; + data.width = 50.0f; + data.depth = 50.0f; + data.elevation = 0.0f; + data.type = "base"; + data.properties = "{}"; + data.valid = true; + centerBuildings.push_back(data); + } + if (changed) { + j["centerOffset"] = centerOffset; + j["plazza"] = plazza; + j["plazzaRadius"] = plazzaRadius; + j["plazzaHeight"] = plazzaHeight; + j["plazzaElevation"] = plazzaElevation; + nlohmann::json lots = nlohmann::json::array(); + for (const auto &d : centerBuildings) { + nlohmann::json jdata; + if (!d.valid) + continue; + jdata["distance"] = d.distance; + jdata["angle"] = d.angle; + jdata["width"] = d.width; + jdata["depth"] = d.depth; + jdata["elevation"] = d.elevation; + jdata["type"] = d.type; + jdata["properties"] = d.properties; + lots.push_back(jdata); + } + j["centerBuildings"] = lots; + } + return changed; +} +void createHarbourPopup(const std::pair item) +{ + bool lighthouse = false; + float lighthouseDistance = 0.0f; + float lighthouseAngle = 0.0f; + float centerOffset = 0.0f; + bool changed = false; + + Ogre::String prop = StaticGeometryModule::getItemProperties(item.first); + nlohmann::json j = nlohmann::json::parse(prop); + nlohmann::json jcenter = nlohmann::json::object(); + if (j.find("lighthouse") != j.end()) + lighthouse = j["lighthouse"].get(); + if (j.find("lighthouseDistance") != j.end()) + lighthouseDistance = j["lighthouseDistance"].get(); + if (j.find("lighthouseAngle") != j.end()) + lighthouseAngle = j["lighthouseAngle"].get(); + if (j.find("centerOffset") != j.end()) + centerOffset = j["centerOffset"].get(); + if (j.find("center") != j.end()) + jcenter = j["center"]; + if (ImGui::Checkbox("Lighthouse", &lighthouse)) + changed = true; + if (lighthouse) { + if (ImGui::SliderFloat("Lighthouse Distance", + &lighthouseDistance, 0.0f, 100.0f)) + changed = true; + if (ImGui::SliderFloat("Lighthouse Angle", &lighthouseAngle, + -90.0f, 90.0f)) + changed = true; + } + if (ImGui::SliderFloat("Center Offset Global", ¢erOffset, 0.0f, + 100.0f)) + changed = true; + changed = changed || editHarbourDistrict(jcenter); + if (changed) { + j["lighthouse"] = lighthouse; + j["lighthouseDistance"] = lighthouseDistance; + j["lighthouseAngle"] = lighthouseAngle; + j["center"] = jcenter; + j["centerOffset"] = centerOffset; + StaticGeometryModule::setItemProperties(item.first, j.dump()); + StaticGeometryModule::saveItems(); + StaticGeometryModule::destroyItemGeometry(item.first); + StaticGeometryModule::createItemGeometry(item.first); + } + ImGui::Text("%s", j.dump(4).c_str()); +} +void createHarbourItem() +{ + Ogre::Vector3 itemPosition = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion itemOrientation = + ECS::get().sceneNode->_getDerivedOrientation(); + float pierLength, pierDepth; + float pierOffset; + float pierHeight; + if (!findPierOffsetAndLengthAndDepth(pierOffset, pierLength, pierDepth)) + return; + findPierHeight(pierOffset + pierLength, pierHeight); + std::vector pierPath; + findPierPath(pierOffset + 2.0f, pierPath); + flecs::entity e = StaticGeometryModule::createItem( + itemPosition, itemOrientation, "harbour"); + Ogre::String prop = StaticGeometryModule::getItemProperties(e); + nlohmann::json j = nlohmann::json::parse(prop); + j["pierOffset"] = pierOffset; + j["pierLength"] = pierLength; + j["pierDepth"] = pierDepth; + j["pierHeight"] = pierHeight; + nlohmann::json p = nlohmann::json::array(); + for (const auto &pt : pierPath) { + nlohmann::json pj; + to_json(pj, pt); + p.push_back(pj); + } + j["pierPath"] = p; + StaticGeometryModule::setItemProperties(e, j.dump()); + // setHarbourSurface(); + StaticGeometryModule::saveItems(); + // updateWorldTexture(); + // updateHeightmap(); + // TerrainModule::save_heightmap(); +} +void createHarbourMenu() +{ + if (ImGui::MenuItem("Create")) + createHarbourItem(); +} +} +namespace Geometry +{ +void createBridge(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ + int i; + Procedural::TriangleBuffer tb; + Ogre::MaterialPtr harbourMaterial; + harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id())); + float stepWidth = 12.0f; + float stepHeight = 0.15f; + float stepDepth = 0.25f; + float stairsHeight = 0.0f; + float stairsOffset = 0.0f; + std::vector pierPath; + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + if (jp.find("stairsHeight") != jp.end()) + stairsHeight = jp["stairsHeight"].get(); + if (jp.find("stairsOffset") != jp.end()) + stairsOffset = jp["stairsOffset"].get(); + if (jp.find("stepHeight") != jp.end()) + stepHeight = jp["stepHeight"].get(); + if (jp.find("stepDepth") != jp.end()) + stepDepth = jp["stepDepth"].get(); + if (jp.find("pierPath") != jp.end()) { + pierPath.reserve(jp["pierPath"].size()); + for (auto &jpt : jp["pierPath"]) { + Ogre::Vector3 pt; + from_json(jpt, pt); + pierPath.push_back(pt); + } + } +#if 1 + Procedural::Shape *pierShape = new Procedural::Shape(); + pierShape->addPoint(8.f, -0.7f); + pierShape->addPoint(6.f, 0.7f); + pierShape->addPoint(6.05f, 0.65f); + pierShape->addPoint(0.f, 0.6f); + pierShape->addPoint(-6.05f, 0.65f); + pierShape->addPoint(-6.0f, 0.7f); + pierShape->addPoint(-8.f, -0.7f); + pierShape->close(); + + Procedural::CubicHermiteSpline3 *pierCurve; + Procedural::Path pierCurvePath; + if (jp.find("pierPath") != jp.end()) { + pierPath.reserve(jp["pierPath"].size()); + pierCurve = new Procedural::CubicHermiteSpline3(); + // pierCurve = new Procedural::RoundedCornerSpline3(); +#if 0 + { + int i; + for (i = 0; i < 5; i++) { + Ogre::Vector3 pt; + from_json(jp["pierPath"][i], pt); + pierPath.push_back(pt); + pierCurve->addPoint( + pt, pt - Ogre::Vector3(0, 0, -1), + pt + Ogre::Vector3(0, 0, 1)); + } + Ogre::Vector3 pt2; + from_json(jp["pierPath"].back(), pt2); + pierPath.push_back(pt2); + pierCurve->addPoint(pt2); + for (const auto &m : pierPath) { + std::cout << m << std::endl; + } + } +#endif +#if 1 + for (auto &jpt : jp["pierPath"]) { + Ogre::Vector3 pt; + from_json(jpt, pt); + pierPath.push_back(pt); + pierCurve->addPoint(pt, Ogre::Vector3(0, 0, 1)); + // pierCurve->addPoint(pt); + } +#endif + OgreAssert(pierPath.size() > 0, "empty path"); + // pierCurve->setNumSeg(8); + pierCurvePath = pierCurve->realizePath(); + // V + Procedural::Track shapeTextureTrack = + Procedural::Track(Procedural::Track::AM_POINT) + .addKeyFrame(0, 0.0f) + .addKeyFrame(6, 0.1f); + // U + Procedural::Track pathTextureTrack = + Procedural::Track(Procedural::Track::AM_POINT) + .addKeyFrame(0, 0.45f) + .addKeyFrame(6, 0.9f); + Procedural::Extruder extruder; + extruder.setShapeTextureTrack(&shapeTextureTrack) + .setPathTextureTrack(&pathTextureTrack) + .setShapeToExtrude(pierShape) + .setExtrusionPath(&pierCurvePath) + .setEnableNormals(true) + .setUTile(1.0f) + .setVTile(1.0f) + .addToTriangleBuffer(tb); + for (auto &v : tb.getVertices()) { + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.41f, 0.9f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } +#if 0 + for (const auto &v : tb.getVertices()) { + std::cout << "UV: " << v.mUV << std::endl; + } + OgreAssert(false, "uvs"); +#endif +#if 0 + Ogre::LodConfig config(extrudedMesh); + setupLods(config); + Ogre::Entity *pathEnt = + ECS::get().mScnMgr->createEntity( + extrudedMesh); + pathEnt->setMaterial(harbourMaterial); + float xofft = 0.0f; + Ogre::Vector3 worldPosition = + sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * 0.0f; + Ogre::Quaternion worldOrientation = + sceneNode->_getDerivedOrientation(); + Ogre::Vector3 xoffset = + worldOrientation * (Ogre::Vector3::UNIT_X * xofft); + geo->addEntity(pathEnt, worldPosition + xoffset, + worldOrientation, Ogre::Vector3(1, 1, 1)); +#endif + } +#else + for (i = 0; i < pierPath.size(); i++) { + if (i == 0) + continue; + Ogre::Vector3 lvec = pierPath[i] - pierPath[i - 1]; + Ogre::Vector3 xvec = Ogre::Vector3::UNIT_Y.crossProduct(lvec); + Ogre::Vector3 n = lvec.crossProduct(xvec).normalisedCopy(); + Ogre::Vector3 pos = (pierPath[i] + pierPath[i - 1]) * 0.5f; + Procedural::PlaneGenerator() + .setNormal(n) + .setNumSegX(2) + .setNumSegY(2) + .setSizeX(1) + .setSizeY(1) + .setPosition(pos) + .addToTriangleBuffer(tb); + } +#endif + Ogre::String meshName = + "pierPathMesh" + Ogre::StringConverter::toString(e.id()); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *pathEnt = + ECS::get().mScnMgr->createEntity(mesh); + pathEnt->setMaterial(harbourMaterial); + float xofft = 0.0f; + Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * 0.0f; + Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); + Ogre::Vector3 xoffset = + worldOrientation * (Ogre::Vector3::UNIT_X * xofft); + geo->addEntity(pathEnt, worldPosition + xoffset, worldOrientation, + Ogre::Vector3(1, 1, 1)); + ECS::get().mScnMgr->destroyEntity(pathEnt); +} +void createPier(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr harbourMaterial; + harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id())); + harbourMaker hm(e); + Ogre::Vector3 position = sceneNode->_getDerivedPosition(); + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + float pierHeight = 0.0f, pierLength = 6.0f, pierDepth = 6.0f; + if (jp.find("pierLength") != jp.end()) + pierLength = jp["pierLength"].get(); + if (jp.find("pierDepth") != jp.end()) + pierDepth = jp["pierDepth"].get(); + if (jp.find("pierHeight") != jp.end()) + pierHeight = jp["pierHeight"].get(); + Procedural::TriangleBuffer tb; + float plankLength = 2.0f; + float plankWidth = 4.01f; + float plankHeight = 0.3f; + const float beamLength = 6.0f; + const float beamWidth = 5.5f; + float beamHeight = 0.3f; + if (pierLength < 12.0f) + pierLength = 12.0f; + auto processGrid = [&sceneNode, &geo](float stepLength, float length, + float zoffset, float yofft, + float xofft, Ogre::Entity *ent) { + float step = 0.0f; + while (step < length) { + Ogre::Vector3 worldPosition = + sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * + (step + zoffset); + Ogre::Quaternion worldOrientation = + sceneNode->_getDerivedOrientation(); + Ogre::Vector3 xoffset = worldOrientation * + (Ogre::Vector3::UNIT_X * xofft); + Ogre::Vector3 yoffset = worldOrientation * + (Ogre::Vector3::UNIT_Y * yofft); + geo->addEntity(ent, worldPosition + xoffset + yoffset, + worldOrientation, + Ogre::Vector3(1, 1, 1)); + step += stepLength; + } + }; + float xofftPlanks; + for (xofftPlanks = -plankWidth; xofftPlanks <= plankWidth; + xofftPlanks += plankWidth) + processGrid(plankLength, pierLength, plankLength / 2.0f, + plankHeight / 2.0f + beamHeight / 2.0f, xofftPlanks, + hm.planks); + { + Procedural::TriangleBuffer tbPillars, tbBollards; + float step = 0.0f; + while (step < pierLength) { + // pillars + Procedural::BoxGenerator() + .setSizeX(0.5f) + .setSizeY(pierDepth) + .setSizeZ(0.5f) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + -5.0f, -pierDepth / 2.0f + 0.5f, step)) + .addToTriangleBuffer(tbPillars); + Procedural::BoxGenerator() + .setSizeX(0.5f) + .setSizeY(pierDepth) + .setSizeZ(0.5f) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + 5.0f, -pierDepth / 2.0f + 0.5f, step)) + .addToTriangleBuffer(tbPillars); + step += 6.0f; + } + step = pierLength - 0.5f; + while (step >= 0.0f) { + // bollards + Procedural::CylinderGenerator() + .setHeight(0.8f) + .setRadius(0.3f) + .setPosition(Ogre::Vector3( + -5.3f, 0.4f + 0.5f + 0.1f, step)) + .addToTriangleBuffer(tbBollards); + Procedural::CylinderGenerator() + .setHeight(0.8f) + .setRadius(0.3f) + .setPosition(Ogre::Vector3( + 5.3f, 0.4f + 0.5f + 0.1f, step)) + .addToTriangleBuffer(tbBollards); + step -= 12.0f; + } + // beams + Procedural::BoxGenerator() + .setSizeX(0.5f) + .setSizeY(beamHeight) + .setSizeZ(pierLength) + .setEnableNormals(true) + .setPosition(Ogre::Vector3(-5.0f, + 0.2 + beamHeight / 2.0f, + pierLength / 2.0f)) + .addToTriangleBuffer(tbPillars); + Procedural::BoxGenerator() + .setSizeX(0.5f) + .setSizeY(beamHeight) + .setSizeZ(pierLength) + .setEnableNormals(true) + .setPosition(Ogre::Vector3(5.0f, + 0.2 + beamHeight / 2.0f, + pierLength / 2.0f)) + .addToTriangleBuffer(tbPillars); + for (auto &v : tbPillars.getVertices()) { + v.mUV *= 0.08f; + v.mUV += Ogre::Vector2(0.01f, 0.01f); + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.0f, 0.1f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + for (auto &v : tbBollards.getVertices()) { + v.mUV *= 0.08f; + v.mUV.x += 0.21f; + v.mUV.y += 0.01f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.2f, 0.3f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + tb.append(tbPillars); + tb.append(tbBollards); + } + Ogre::String meshName = + "pier" + Ogre::StringConverter::toString(e.id()); + { + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + // config.advanced.useCompression = false; + // config.advanced.useVertexNormals = true; + setupLods(config); + Ogre::Entity *ent = + ECS::get().mScnMgr->createEntity(mesh); + ent->setMaterial(harbourMaterial); + float xofft = 0.0f; + Ogre::Vector3 worldPosition = + sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * 0.0f; + Ogre::Quaternion worldOrientation = + sceneNode->_getDerivedOrientation(); + Ogre::Vector3 xoffset = + worldOrientation * (Ogre::Vector3::UNIT_X * xofft); + geo->addEntity(ent, worldPosition + xoffset, worldOrientation, + Ogre::Vector3(1, 1, 1)); + } + std::cout << meshName << std::endl; +} +void createPlazza(flecs::entity e, const nlohmann::json &district, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr harbourMaterial; + harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id())); + Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); + const nlohmann::json &jp = district; + Procedural::TriangleBuffer tb; + float centerOffset = 0.0f; + float plazzaRadius = 5.0f; + float plazzaHeight = 0.2f; + float plazzaElevation = 0.0f; + if (jp.find("centerOffset") != jp.end()) + centerOffset = jp["centerOffset"].get(); + if (jp.find("plazzaRadius") != jp.end()) + plazzaRadius = jp["plazzaRadius"].get(); + if (jp.find("plazzaHeight") != jp.end()) + plazzaHeight = jp["plazzaHeight"].get(); + if (jp.find("plazzaElevation") != jp.end()) + plazzaElevation = jp["plazzaElevation"].get(); + if (plazzaHeight < 0.1f) + plazzaHeight = 0.1f; + if (plazzaRadius < 5.0f) + plazzaRadius = 5.0f; + Ogre::Vector3 worldPlazzaCenter = worldPosition; +#if 0 + Procedural::CylinderGenerator() + .setHeight(plazzaHeight) + .setRadius(plazzaRadius) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + 0.0f, plazzaHeight / 2.0f + plazzaElevation, 0.0f)) + .addToTriangleBuffer(tb); +#endif + float mh = 4.0f; + Procedural::Shape *plazzaShape = new Procedural::Shape(); + plazzaShape->addPoint(0, -plazzaHeight - mh - mh); + plazzaShape->addPoint(plazzaRadius * 0.5f + mh, + -plazzaHeight - mh - mh); + plazzaShape->addPoint(plazzaRadius + mh, -plazzaHeight - mh); + plazzaShape->addPoint(plazzaRadius, -plazzaHeight); + plazzaShape->addPoint(plazzaRadius, 0.0f); + plazzaShape->addPoint(plazzaRadius - 0.1f, 0.1f); + plazzaShape->addPoint(plazzaRadius - mh + 0.1f, plazzaHeight); + plazzaShape->addPoint(plazzaRadius - mh, plazzaHeight + 0.1f); + plazzaShape->addPoint(plazzaRadius * 0.5f + mh, plazzaHeight); + plazzaShape->addPoint(0, plazzaHeight); + Procedural::Lathe() + .setShapeToExtrude(plazzaShape) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + 0.0f, plazzaHeight / 2.0f + plazzaElevation, 0.0f)) + .setNumSeg(24) + .addToTriangleBuffer(tb); + for (auto &v : tb.getVertices()) { + v.mUV *= 0.08f; + v.mUV.x += 0.41f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + Ogre::String meshName = + "plazzaMesh" + Ogre::StringConverter::toString(e.id()); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *pathEnt = + ECS::get().mScnMgr->createEntity(mesh); + pathEnt->setMaterial(harbourMaterial); + geo->addEntity(pathEnt, worldPlazzaCenter, worldOrientation, + Ogre::Vector3(1, 1, 1)); +} + +void createBuildings(flecs::entity e, const nlohmann::json &district, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr harbourMaterial; + harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id())); + nlohmann::json jbuildings = nlohmann::json::array(); + if (district.find("centerBuildings") != district.end()) + jbuildings = district["centerBuildings"]; + Ogre::Vector3 centerPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion centerOrientation = + sceneNode->_getDerivedOrientation(); + int count = 0; + float baseHeight = 4.0f; + for (const auto &jb : jbuildings) { + Procedural::TriangleBuffer tb; + float angle = 0.0f; + float depth = 50.0f; + float width = 100.0f; + float distance = 100.0f; + float elevation = 0.0f; + std::cout << jb.dump() << std::endl; + if (jb.find("angle") != jb.end()) + angle = jb["angle"].get(); + if (jb.find("depth") != jb.end()) + depth = jb["depth"].get(); + if (jb.find("width") != jb.end()) + width = jb["width"].get(); + if (jb.find("distance") != jb.end()) + distance = jb["distance"].get(); + if (jb.find("elevation") != jb.end()) + elevation = jb["elevation"].get(); + + OgreAssert(width > 1 && depth > 1 && baseHeight > 1, + "Bad stuff happen"); + + Ogre::Quaternion rotation = Ogre::Quaternion( + Ogre::Degree(angle), Ogre::Vector3::UNIT_Y); + Ogre::Vector3 offset = centerOrientation * rotation * + (Ogre::Vector3::UNIT_Z * distance); + Procedural::BoxGenerator() + .setSizeX(width) + .setSizeY(baseHeight) + .setSizeZ(depth) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + 0.0f, -baseHeight / 2.0f + elevation, 0.0f)) + .addToTriangleBuffer(tb); + OgreAssert(tb.getVertices().size() > 8, "bad box"); + for (auto &v : tb.getVertices()) { + float c = 1.0 + 1.0 / (v.mPosition.y + baseHeight + + elevation); + v.mPosition.x *= c; + v.mPosition.z *= c; + v.mUV *= 0.08f; + v.mUV.x += 0.41f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + Ogre::String meshName = + "lotbase" + Ogre::StringConverter::toString(count) + + "_" + Ogre::StringConverter::toString(e.id()); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *ent = + ECS::get().mScnMgr->createEntity( + "Ent" + meshName, mesh); + ent->setMaterial(harbourMaterial); + geo->addEntity(ent, centerPosition + offset, rotation, + Ogre::Vector3::UNIT_SCALE); + ECS::get().mScnMgr->destroyEntity(ent); + count++; + } +} + +void createHarbour(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ + std::cout << "createHarbour " << e.id() << std::endl; + Ogre::MaterialPtr harbourMaterial; + harbourMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id())); + if (!harbourMaterial) { + Procedural::TextureBuffer colorAtlas(1024); + Procedural::RectangleTexture drawAtlas(&colorAtlas); + Ogre::ColourValue normalYellow(0.8f, 0.6f, 0, 1); + Ogre::ColourValue roadBrown(0.4f, 0.3f, 0.3f, 1); + Ogre::ColourValue bollardGrey(0.2f, 0.2f, 0.2f, 1); + drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) + .setColour(normalYellow) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.2f, 0.0f, 0.3f, 1.0f)) + .setColour(bollardGrey) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.4f, 0.0f, 1.0f, 1.0f)) + .setColour(roadBrown) + .process(); + Ogre::TexturePtr pierTexture = colorAtlas.createTexture( + "proceduralTextureHarbour" + + Ogre::StringConverter::toString(e.id())); + colorAtlas.saveImage("tmp.png"); + harbourMaterial = + Ogre::MaterialManager::getSingletonPtr()->create( + "proceduralMaterialHarbour" + + Ogre::StringConverter::toString(e.id()), + Ogre::ResourceGroupManager:: + DEFAULT_RESOURCE_GROUP_NAME); + harbourMaterial->getTechnique(0)->getPass(0)->setShininess(0); + harbourMaterial->getTechnique(0)->getPass(0)->setDiffuse( + Ogre::ColourValue::White); + harbourMaterial->getTechnique(0)->getPass(0)->setSpecular( + Ogre::ColourValue(1.0f, 1.0f, 0.9f)); + harbourMaterial->getTechnique(0) + ->getPass(0) + ->createTextureUnitState( + "proceduralTextureHarbour" + + Ogre::StringConverter::toString(e.id())); + if (Ogre::RTShader::ShaderGenerator::initialize()) { + harbourMaterial->prepare(); + Ogre::RTShader::ShaderGenerator *mShaderGenerator = + Ogre::RTShader::ShaderGenerator:: + getSingletonPtr(); + mShaderGenerator->createShaderBasedTechnique( + *harbourMaterial, + Ogre::MaterialManager::DEFAULT_SCHEME_NAME, + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME); + Ogre::RTShader::RenderState *pMainRenderState = + mShaderGenerator->getRenderState( + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME, + *harbourMaterial); + } + } + { + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + float pierOffset = 0.0f; + float centerOffset = 0.0f; + float plazzaRadius = 5.0f; + bool plazza = false; + nlohmann::json jcenter = nlohmann::json::object(); + if (jp.find("center") != jp.end()) + jcenter = jp["center"]; + if (jcenter.find("plazzaRadius") != jcenter.end()) + plazzaRadius = jcenter["plazzaRadius"]; + if (jp.find("pierOffset") != jp.end()) + pierOffset = jp["pierOffset"].get(); + if (jp.find("plazza") != jp.end()) + plazza = jp["plazza"].get(); + if (jp.find("centerOffset") != jp.end()) + centerOffset = jp["centerOffset"].get(); + Ogre::Vector3 worldPosition = + sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * (pierOffset); + float xofft = 0.0f; + float stairLengthZ = worldPosition.y; + float stairsOffset = 0.0f; + stairsOffset = stairLengthZ; + jp["stairsHeight"] = worldPosition.y; + jp["stairsOffset"] = stairsOffset; + e.get_mut().properties = jp.dump(); + e.modified(); + worldPosition.y = 0.0f; + Ogre::Quaternion worldOrientation = + sceneNode->_getDerivedOrientation(); + Ogre::Vector3 xoffset = + worldOrientation * (Ogre::Vector3::UNIT_X * xofft); + Ogre::Vector3 zoffset = + worldOrientation * + (Ogre::Vector3::UNIT_Z * (stairsOffset - 1)); + Ogre::SceneNode *elevatorNode = + sceneNode->createChildSceneNode(); + Ogre::SceneNode *pierNode = sceneNode->createChildSceneNode(); + pierNode->_setDerivedPosition(worldPosition + zoffset + + xoffset); + Ogre::Vector3 worldPlazzaCenter = + sceneNode->_getDerivedPosition() + + sceneNode->_getDerivedOrientation() * + Ogre::Vector3::UNIT_Z * + (-centerOffset - plazzaRadius + 2.0f); + Ogre::SceneNode *centerNode = sceneNode->createChildSceneNode(); + centerNode->_setDerivedPosition(worldPlazzaCenter); + createBridge(e, elevatorNode, geo); + createPier(e, pierNode, geo); + createPlazza(e, jcenter, centerNode, geo); + createBuildings(e, jcenter, centerNode, geo); + } + geo->build(); +} +} +} \ No newline at end of file diff --git a/src/gamedata/items/harbour.h b/src/gamedata/items/harbour.h new file mode 100644 index 0000000..52b855b --- /dev/null +++ b/src/gamedata/items/harbour.h @@ -0,0 +1,25 @@ +#ifndef __HARBOUR_H__ +#define __HARBOUR_H__ +#include +namespace ECS +{ +namespace Items +{ +void createHarbourPopup(const std::pair item); +void createHarbourMenu(); +} +namespace Geometry +{ +void createHarbour(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +void createBridge(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +void createPier(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +void createPlazza(flecs::entity e, const nlohmann::json &district, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); +void createBuildings(flecs::entity e, const nlohmann::json &district, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); +} +} +#endif \ No newline at end of file diff --git a/src/gamedata/items/items.cpp b/src/gamedata/items/items.cpp new file mode 100644 index 0000000..7b9d777 --- /dev/null +++ b/src/gamedata/items/items.cpp @@ -0,0 +1,223 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "Components.h" +#include "GameData.h" +#include "StaticGeometryModule.h" +#include "EditorGizmoModule.h" +#include "TerrainModule.h" +#include "physics.h" +#include "PhysicsModule.h" +#include "harbour.h" +#include "temple.h" +#include "town.h" +#include "items.h" +namespace ECS +{ +namespace Items +{ +void showItemPopup(const std::pair &item) +{ + Ogre::String popupLabel = + "EditPopup" + Ogre::StringConverter::toString(item.first.id()); + if (ImGui::BeginPopup(popupLabel.c_str())) { + Ogre::String prop = + StaticGeometryModule::getItemProperties(item.first); + nlohmann::json j = nlohmann::json::parse(prop); + Ogre::String itemType = j["type"].get(); + if (itemType == "harbour") + createHarbourPopup(item); + else if (itemType == "temple") + createTemplePopup(item); + else if (itemType == "town") + createTownPopup(item); + ImGui::EndPopup(); + } +} +void showItemButtons(const std::pair &item) +{ + ImGui::SameLine(); + Ogre::String upd_label = + "Update Height##" + + Ogre::StringConverter::toString(item.first.id()); + if (ImGui::SmallButton(upd_label.c_str())) { + TerrainItem &uitem = item.first.get_mut(); + uitem.position.y = + ECS::get() + .mTerrainGroup->getHeightAtWorldPosition( + uitem.position); + StaticGeometryModule::saveItems(); + } + ImGui::SameLine(); + Ogre::String edit_label = + "Edit##" + Ogre::StringConverter::toString(item.first.id()); + Ogre::String popupLabel = + "EditPopup" + Ogre::StringConverter::toString(item.first.id()); + if (ImGui::SmallButton(edit_label.c_str())) + ImGui::OpenPopup(popupLabel.c_str()); + ImGui::SameLine(); + Ogre::String del_label = + "delete##" + Ogre::StringConverter::toString(item.first.id()); + if (ImGui::SmallButton(del_label.c_str())) { + item.first.destruct(); + StaticGeometryModule::saveItems(); + } + ImGui::Spacing(); +} +void createItemsMenu() +{ + if (ImGui::BeginMenu("Harbour")) { + Items::createHarbourMenu(); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Temple")) { + Items::createTempleMenu(); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Town")) { + Items::createTownMenu(); + ImGui::EndMenu(); + } +} +} +namespace Geometry +{ +void setupLods(Ogre::LodConfig &config) +{ + // config.advanced.useCompression = false; + // config.advanced.useVertexNormals = true; + config.advanced.preventPunchingHoles = true; + config.advanced.preventBreakingLines = true; + config.createGeneratedLodLevel(10, 0.15f); + config.createGeneratedLodLevel(30, 0.25f); + config.createGeneratedLodLevel(60, 0.36f); + config.createGeneratedLodLevel(150, 0.65f); + config.advanced.useBackgroundQueue = false; + Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config); +} + +Ogre::StaticGeometry *createStaticGeometry(flecs::entity e) +{ + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + if (jp.find("type") != jp.end()) { + Ogre::String itemType = jp["type"].get(); + Ogre::String geoName = itemType + "_" + + Ogre::StringConverter::toString(e.id()); + OgreAssert((ECS::get().mScnMgr->hasStaticGeometry( + geoName)) == false, + "" + geoName + " already exists for some reason"); + Ogre::StaticGeometry *geo = + ECS::get().mScnMgr->createStaticGeometry( + geoName); + return geo; + } + return nullptr; +} +void createItemGeometry(flecs::entity e) +{ + OgreAssert(!e.has(), "Geometry already created"); + std::cout << "creating geometry for item: " << e.id() << std::endl; + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + Ogre::SceneNode *itemNode = ECS::get() + .mScnMgr->getRootSceneNode() + ->createChildSceneNode(); + itemNode->_setDerivedPosition(e.get().position); + itemNode->_setDerivedOrientation(e.get().orientation); + if (jp.find("staticMesh") != jp.end()) { + Ogre::String meshName = jp["staticMesh"].get(); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) { + Ogre::Entity *ent = + ECS::get().mScnMgr->createEntity( + mesh); + itemNode->attachObject(ent); + } + } else if (jp.find("type") != jp.end()) { + Ogre::String itemType = jp["type"].get(); + std::cout << "type: " << itemType << std::endl; + std::cout << "props: " << props << std::endl; + Ogre::StaticGeometry *geo = createStaticGeometry(e); + if (geo) { + geo->setRegionDimensions(Ogre::Vector3(140, 140, 140)); + Ogre::Vector3 geoposition = + itemNode->_getDerivedPosition(); + geoposition.y = 0.0f; + geo->setOrigin(geoposition); + } + if (itemType == "harbour") { + OgreAssert(geo, "Can't create static geometry"); + Geometry::createHarbour(e, itemNode, geo); + e.set({ itemNode, geo }); + } else if (itemType == "temple") { + OgreAssert(geo, "Can't create static geometry"); + createTemple(e, itemNode, geo); + e.set({ itemNode, geo }); + } else if (itemType == "town") { + OgreAssert(geo, "Can't create static geometry"); + createTown(e, itemNode, geo); + e.set({ itemNode, geo }); + std::cout << " town created: " << e.id() << std::endl; + } else { + OgreAssert(geo, "Can't create static geometry"); + e.set({ itemNode, geo }); + OgreAssert(false, "Unknown item type: " + itemType); + } + } else { + std::cout << "can't build item" << std::endl; + std::cout << "props: " << props << std::endl; + OgreAssert(false, "can't create item"); + } +} + +void destroyItemGeometry(flecs::entity e) +{ + OgreAssert(e.has(), "No geometry created"); +#if 0 + ECS::get().mScnMgr->destroyStaticGeometry() + e.get().geo->destroy(); + e.get_mut().geo = nullptr; + e.modified(); +#endif + e.remove(); +} +flecs::entity createMeshGeometry(const Ogre::String &meshName, + flecs::entity parente, + Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ + Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load( + meshName, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + OgreAssert(mesh, "mesh " + meshName + " not found"); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *ent = ECS::get().mScnMgr->createEntity( + "Ent" + meshName, mesh); + geo->addEntity(ent, sceneNode->_getDerivedPosition(), + sceneNode->_getDerivedOrientation()); + ECS::get().mScnMgr->destroyEntity(ent); + JPH::ShapeRefC shape = + JoltPhysicsWrapper::getSingleton().createMeshShape(mesh); + JPH::BodyID id = JoltPhysicsWrapper::getSingleton().createBody( + shape.GetPtr(), 0, sceneNode, JPH::EMotionType::Static, + Layers::NON_MOVING); + flecs::entity e = ECS::get() + .entity() + .child_of(parente) + .set(id) + .set({ sceneNode, geo }); + JoltPhysicsWrapper::getSingleton().addBody(id, + JPH::EActivation::Activate); + return e; +} + +} +} \ No newline at end of file diff --git a/src/gamedata/items/items.h b/src/gamedata/items/items.h new file mode 100644 index 0000000..44e6d1d --- /dev/null +++ b/src/gamedata/items/items.h @@ -0,0 +1,89 @@ +#ifndef __ITEMS_H__ +#define __ITEMS_H__ +#include +#include +namespace ECS +{ +namespace Items +{ +void showItemPopup(const std::pair &item); +void showItemButtons(const std::pair &item); +void createItemsMenu(); +} +namespace Geometry +{ +void setupLods(Ogre::LodConfig &config); +struct harbourMaker { + Ogre::Entity *planks, *pillar, *beam; + Ogre::String makeName(const Ogre::String &base, flecs::entity e) + { + return base + Ogre::StringConverter::toString(e.id()); + } + harbourMaker(flecs::entity e) + { + Ogre::String planksName = makeName("Plank", e); + Ogre::String beamName = makeName("Beam", e); + Ogre::String pillarName = makeName("Pillar", e); + std::pair sets[] = { + { planksName, &planks }, + { beamName, &beam }, + { pillarName, &pillar } + }; + std::map meshes = { + { planksName, "pier-plank.glb" }, + { beamName, "pier-beam.glb" }, + { pillarName, "pier-pillar.glb" }, + }; + for (auto &p : sets) { + if (ECS::get().mScnMgr->hasEntity(p.first)) + *p.second = + ECS::get() + .mScnMgr->getEntity(p.first); + else { + *p.second = ECS::get() + .mScnMgr->createEntity( + p.first, + meshes.at(p.first)); + Ogre::MeshPtr mesh = (*p.second)->getMesh(); + Ogre::LodConfig config(mesh); + setupLods(config); + } + } + } +}; +void createItemGeometry(flecs::entity e); +void destroyItemGeometry(flecs::entity e); +flecs::entity createMeshGeometry(const Ogre::String &meshName, + flecs::entity parente, + Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); + +} +static void to_json(nlohmann::json &j, const Ogre::Vector3 &position) +{ + j["x"] = position.x; + j["y"] = position.y; + j["z"] = position.z; +} +static void to_json(nlohmann::json &j, const Ogre::Quaternion &orientation) +{ + j["w"] = orientation.w; + j["x"] = orientation.x; + j["y"] = orientation.y; + j["z"] = orientation.z; +} +static void from_json(const nlohmann::json &j, Ogre::Vector3 &position) +{ + position.x = j["x"].get(); + position.y = j["y"].get(); + position.z = j["z"].get(); +} +static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation) +{ + orientation.w = j["w"].get(); + orientation.x = j["x"].get(); + orientation.y = j["y"].get(); + orientation.z = j["z"].get(); +} +} +#endif \ No newline at end of file diff --git a/src/gamedata/items/temple.cpp b/src/gamedata/items/temple.cpp new file mode 100644 index 0000000..4490f73 --- /dev/null +++ b/src/gamedata/items/temple.cpp @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include +#include +#include +#include "Components.h" +#include "GameData.h" +#include "EditorGizmoModule.h" +#include "TerrainModule.h" +#include "StaticGeometryModule.h" +#include "physics.h" +#include "PhysicsModule.h" +#include "items.h" +#include "temple.h" +namespace ECS +{ +namespace Items +{ +void createTempleItem() +{ + Ogre::Vector3 itemPosition = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion itemOrientation = + ECS::get().sceneNode->_getDerivedOrientation(); + flecs::entity e = StaticGeometryModule::createItem( + itemPosition, itemOrientation, "temple"); + Ogre::String prop = StaticGeometryModule::getItemProperties(e); + nlohmann::json j = nlohmann::json::parse(prop); + j["size"] = 40.0f; + j["form"] = "rect"; + j["pillarHeight"] = 16.0f; + j["pillarRadius"] = 0.5f; + j["pillarCount"] = 20; + StaticGeometryModule::setItemProperties(e, j.dump()); + StaticGeometryModule::saveItems(); +} +void createTempleMenu() +{ + if (ImGui::MenuItem("Create")) + createTempleItem(); +} +void createTemplePopup(const std::pair item) +{ + float size = 40.0f; + float pillarRadius = 0.5f; + float pillarHeight = 16.0f; + int pillarCount = 20; + Ogre::String form; + + Ogre::String prop = StaticGeometryModule::getItemProperties(item.first); + nlohmann::json j = nlohmann::json::parse(prop); + bool changed = false; + if (j.find("size") != j.end()) + size = j["size"].get(); + if (j.find("pillarRadius") != j.end()) + pillarRadius = j["pillarRadius"].get(); + if (j.find("pillarHeight") != j.end()) + pillarHeight = j["pillarHeight"].get(); + if (j.find("pillarCount") != j.end()) + pillarCount = j["pillarCount"].get(); + if (ImGui::SliderFloat("Temple Size", &size, 40.0f, 100.0f)) + changed = true; + if (ImGui::SliderFloat("Temple Pillar Radius", &pillarRadius, 0.5f, + 2.0f)) + changed = true; + if (ImGui::SliderFloat("Temple Pillar Height", &pillarHeight, 16.0f, + 60.0f)) + changed = true; + if (ImGui::SliderInt("Pillar Count", &pillarCount, 1, 200)) + changed = true; + if (changed) { + j["size"] = size; + j["pillarRadius"] = pillarRadius; + j["pillarHeight"] = pillarHeight; + j["pillarCount"] = pillarCount; + StaticGeometryModule::setItemProperties(item.first, j.dump()); + StaticGeometryModule::saveItems(); + StaticGeometryModule::destroyItemGeometry(item.first); + StaticGeometryModule::createItemGeometry(item.first); + } + ImGui::Text("%s", j.dump(4).c_str()); +} +} +namespace Geometry +{ +void createTemple(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + float size = 20.0f; + int pillarCount = 4; + float pillarRadius = 0.5f, pillarHeight = 10.0f; + if (jp.find("size") != jp.end()) + size = jp["size"].get(); + if (jp.find("pillarCount") != jp.end()) + pillarCount = jp["pillarCount"].get(); + if (jp.find("pillarHeight") != jp.end()) + pillarHeight = jp["pillarHeight"].get(); + if (jp.find("pillarCount") != jp.end()) + size = jp["size"].get(); + Procedural::TriangleBuffer tb, colliderTb; + float elevation = 0.0f; + Ogre::MaterialPtr templeMaterial; + templeMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialTemple" + + Ogre::StringConverter::toString(e.id())); + if (!templeMaterial) { + Procedural::TextureBuffer colorAtlas(1024); + Procedural::RectangleTexture drawAtlas(&colorAtlas); + Ogre::ColourValue normalGreen(0.6f, 0.8f, 0.5f, 1); + drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) + .setColour(normalGreen) + .process(); + Ogre::TexturePtr pierTexture = colorAtlas.createTexture( + "proceduralTextureTemple" + + Ogre::StringConverter::toString(e.id())); + colorAtlas.saveImage("tmp2.png"); + templeMaterial = Ogre::MaterialManager::getSingletonPtr()->create( + "proceduralMaterialTemple" + + Ogre::StringConverter::toString(e.id()), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + templeMaterial->getTechnique(0)->getPass(0)->setShininess(0); + templeMaterial->getTechnique(0)->getPass(0)->setDiffuse( + Ogre::ColourValue::White); + templeMaterial->getTechnique(0)->getPass(0)->setSpecular( + Ogre::ColourValue(1.0f, 1.0f, 0.9f)); + templeMaterial->getTechnique(0) + ->getPass(0) + ->createTextureUnitState( + "proceduralTextureTemple" + + Ogre::StringConverter::toString(e.id())); + if (Ogre::RTShader::ShaderGenerator::initialize()) { + templeMaterial->prepare(); + Ogre::RTShader::ShaderGenerator *mShaderGenerator = + Ogre::RTShader::ShaderGenerator:: + getSingletonPtr(); + mShaderGenerator->createShaderBasedTechnique( + *templeMaterial, + Ogre::MaterialManager::DEFAULT_SCHEME_NAME, + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME); + Ogre::RTShader::RenderState *pMainRenderState = + mShaderGenerator->getRenderState( + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME, + *templeMaterial); + } + } + Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); + Procedural::BoxGenerator() + .setSizeX(size) + .setSizeY(20) + .setSizeZ(size) + .setEnableNormals(true) + .setPosition( + Ogre::Vector3(0.0f, -20.0f / 2.0f + elevation, 0.0f)) + .addToTriangleBuffer(tb); + float pillarStep = 0.0f; + float pillarStepSize = size * 4.0f / (float)pillarCount; + int pcount = pillarCount; + while (pillarStep < size - pillarRadius * 2.0f && pcount > 0) { + float s = pillarStep - size / 2.0f + pillarStepSize / 2.0f; + Procedural::CylinderGenerator() + .setHeight(pillarHeight) + .setRadius(pillarRadius) + .setNumSegBase(8) + .setPosition(s, 0.0f, -size / 2.0f + pillarRadius) + .addToTriangleBuffer(tb); + Procedural::CylinderGenerator() + .setHeight(pillarHeight) + .setRadius(pillarRadius) + .setNumSegBase(8) + .setPosition(s, 0.0f, size / 2.0f - pillarRadius) + .addToTriangleBuffer(tb); + Procedural::CylinderGenerator() + .setHeight(pillarHeight) + .setRadius(pillarRadius) + .setNumSegBase(8) + .setPosition(-size / 2.0f + pillarRadius, 0.0f, s) + .addToTriangleBuffer(tb); + Procedural::CylinderGenerator() + .setHeight(pillarHeight) + .setRadius(pillarRadius) + .setNumSegBase(8) + .setPosition(size / 2.0f - pillarRadius, 0.0f, s) + .addToTriangleBuffer(tb); + pillarStep += pillarStepSize; + pcount--; + pcount--; + pcount--; + pcount--; + } + OgreAssert(tb.getVertices().size() > 8, "bad box"); + for (auto &v : tb.getVertices()) { +#if 0 + float c = 1.0 + 1.0 / (v.mPosition.y + baseHeight + + elevation); + v.mPosition.x *= c; + v.mPosition.z *= c; +#endif + v.mUV *= 0.08f; + v.mUV.x += 0.01f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.0f, 0.4f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + Ogre::String meshName = + "Temple" + Ogre::StringConverter::toString(e.id()); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + Geometry::setupLods(config); + Ogre::Entity *ent = ECS::get().mScnMgr->createEntity( + "Ent" + meshName, mesh); + ent->setMaterial(templeMaterial); + geo->addEntity(ent, worldPosition, worldOrientation, + Ogre::Vector3::UNIT_SCALE); + ECS::get().mScnMgr->destroyEntity(ent); + // TODO set altar position + createMeshGeometry("altar.glb", e, sceneNode->createChildSceneNode(), + geo); + geo->build(); + JPH::ShapeRefC shape = + JoltPhysicsWrapper::getSingleton().createMeshShape(mesh); + JPH::BodyID id = JoltPhysicsWrapper::getSingleton().createBody( + shape.GetPtr(), 0, sceneNode, JPH::EMotionType::Static, + Layers::NON_MOVING); + e.set(id); + JoltPhysicsWrapper::getSingleton().addBody(id, + JPH::EActivation::Activate); +} + +} +} diff --git a/src/gamedata/items/temple.h b/src/gamedata/items/temple.h new file mode 100644 index 0000000..b0bff42 --- /dev/null +++ b/src/gamedata/items/temple.h @@ -0,0 +1,20 @@ +#ifndef __TEMPLE_H__ +#define __TEMPLE_H__ +#include +#include +namespace ECS +{ +namespace Items +{ +void createTempleItem(); +void createTempleMenu(); +void createTemplePopup(const std::pair item); +} +namespace Geometry +{ +void createTemple(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +} +} + +#endif \ No newline at end of file diff --git a/src/gamedata/items/town.cpp b/src/gamedata/items/town.cpp new file mode 100644 index 0000000..b563aea --- /dev/null +++ b/src/gamedata/items/town.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include "Components.h" +#include "GameData.h" +#include "EditorGizmoModule.h" +#include "TerrainModule.h" +#include "StaticGeometryModule.h" +#include "physics.h" +#include "PhysicsModule.h" +#include "items.h" +#include "town.h" +namespace ECS +{ +namespace Items +{ +void createTownItem() +{ + Ogre::Vector3 itemPosition = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion itemOrientation = + ECS::get().sceneNode->_getDerivedOrientation(); + flecs::entity e = StaticGeometryModule::createItem( + itemPosition, itemOrientation, "town"); + Ogre::String prop = StaticGeometryModule::getItemProperties(e); + nlohmann::json j = nlohmann::json::parse(prop); + j["districts"] = nlohmann::json::array(); + StaticGeometryModule::setItemProperties(e, j.dump()); + // setHarbourSurface(); + StaticGeometryModule::saveItems(); + // updateWorldTexture(); + // updateHeightmap(); + // TerrainModule::save_heightmap(); +} +void createTownMenu() +{ + if (ImGui::MenuItem("Create")) + createTownItem(); +} +void createTownPopup(const std::pair item) +{ + Ogre::String prop = StaticGeometryModule::getItemProperties(item.first); + nlohmann::json j = nlohmann::json::parse(prop); + bool changed = false; + if (ImGui::SmallButton("Add district")) { + nlohmann::json d; + d["radius"] = 50.0f; + d["lots"] = nlohmann::json::array(); + j["districts"].push_back(d); + changed = true; + } + if (changed) { + StaticGeometryModule::setItemProperties(item.first, j.dump()); + StaticGeometryModule::saveItems(); + StaticGeometryModule::destroyItemGeometry(item.first); + StaticGeometryModule::createItemGeometry(item.first); + } +} +} +namespace Geometry +{ +void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) +{ +} +} +} \ No newline at end of file diff --git a/src/gamedata/items/town.h b/src/gamedata/items/town.h new file mode 100644 index 0000000..af70d76 --- /dev/null +++ b/src/gamedata/items/town.h @@ -0,0 +1,19 @@ +#ifndef __TOWN_H__ +#define __TOWN_H__ +#include +#include +namespace ECS +{ +namespace Items +{ +void createTownItem(); +void createTownMenu(); +void createTownPopup(const std::pair item); +} +namespace Geometry +{ +void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +} +} +#endif \ No newline at end of file