From 190318e5c4d8cd80751e0eafc2480991ecad078d Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Tue, 16 Sep 2025 20:38:29 +0300 Subject: [PATCH] Updates --- CMakeLists.txt | 26 +- Game.cpp | 5 +- assets/blender/buildings/altar.blend | 3 + assets/fonts/Kenney Bold.ttf | 3 + lua-scripts/data.lua | 36 ++- resources.cfg | 1 + src/gamedata/CMakeLists.txt | 4 +- src/gamedata/CharacterModule.cpp | 159 +++++++++--- src/gamedata/CharacterModule.h | 8 +- src/gamedata/GUIModule.cpp | 375 +++++++++++++++++++-------- src/gamedata/GUIModule.h | 5 + src/gamedata/GameData.cpp | 26 ++ src/gamedata/GameData.h | 1 + src/gamedata/LuaData.cpp | 133 ++++++++++ src/gamedata/LuaData.h | 29 +++ src/gamedata/TerrainModule.cpp | 325 ++++++++++++++++------- src/gamedata/TerrainModule.h | 10 + src/gamedata/WorldMapModule.cpp | 6 + src/gamedata/WorldMapModule.h | 11 + src/lua/CMakeLists.txt | 2 +- 20 files changed, 925 insertions(+), 243 deletions(-) create mode 100644 assets/blender/buildings/altar.blend create mode 100644 assets/fonts/Kenney Bold.ttf create mode 100644 src/gamedata/LuaData.cpp create mode 100644 src/gamedata/LuaData.h create mode 100644 src/gamedata/WorldMapModule.cpp create mode 100644 src/gamedata/WorldMapModule.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e46d288..d754fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,19 @@ if(OGRE_STATIC) target_link_options(Procedural PRIVATE -static-libstdc++ -static-libgcc) endif() add_dependencies(Procedural stage_files import_buildings) +file(GLOB FONTS_SRC ${CMAKE_SOURCE_DIR}/assets/fonts/*.ttf) +set(FONT_OUTPUT_FILES) +foreach(FONT_FILE ${FONTS_SRC}) + get_filename_component(FILE_NAME ${FONT_FILE} NAME_WE) + set(FONT_OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/fonts/${FILE_NAME}.ttf) + add_custom_command( + OUTPUT ${FONT_OUTPUT_FILE} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/resources/fonts + COMMAND ${CMAKE_COMMAND} -E copy ${FONT_FILE} ${FONT_OUTPUT_FILE} + DEPENDS ${FONT_FILE}) + list(APPEND FONT_OUTPUT_FILES ${FONT_OUTPUT_FILE}) +endforeach() +add_custom_target(fonts ALL DEPENDS ${FONT_OUTPUT_FILES}) file(GLOB BUILDINGS_SRC ${CMAKE_SOURCE_DIR}/assets/blender/buildings/*.blend) set(BUILDING_OUTPUT_FILES) foreach(BUILDING_FILE ${BUILDINGS_SRC}) @@ -273,7 +286,6 @@ endforeach() file(GLOB VRM_FILES RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/assets/vroid/*.vrm) file(GLOB MIXAMO_FILES RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/assets/blender/mixamo/**/*.fbx) -file(GLOB EDITED_BLENDS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/assets/blender/edited-*.blend) set(VRM_SOURCE) foreach(VRM_FILE ${VRM_FILES} ${MIXAMO_FILES}) set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${VRM_FILE}") @@ -303,6 +315,7 @@ set(EDITED_BLENDS_LIST female ) set(EDITED_BLEND_TARGETS) +set(CHARACTER_GLBS) foreach(EDITED_BLEND ${EDITED_BLENDS_LIST}) add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend @@ -314,24 +327,21 @@ add_custom_command( COMMAND ${BLENDER} -b -Y ${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/copy_animations.py -- - ${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-male.blend + ${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-${EDITED_BLEND}.blend ${EDITED_BLEND} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) list(APPEND EDITED_BLEND_TARGETS ${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend) +list(APPEND CHARACTER_GLBS ${CMAKE_BINARY_DIR}/characters/${EDITED_BLEND}/normal-${EDITED_BLEND}.glb) endforeach() -add_custom_target(edited-blends DEPENDS ${EDITED_BLEND_TARGETS}) +add_custom_target(edited-blends ALL DEPENDS ${EDITED_BLEND_TARGETS}) -set(CHARACTER_GLBS - ${CMAKE_BINARY_DIR}/characters/male/normal-male.glb - ${CMAKE_BINARY_DIR}/characters/female/normal-female.glb - ) add_custom_command( OUTPUT ${CHARACTER_GLBS} COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES} COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py COMMAND ${CMAKE_COMMAND} -E touch ${CHARACTER_GLBS} - DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${VRM_IMPORTED_BLENDS} + DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${VRM_IMPORTED_BLENDS} ${EDITED_BLEND_TARGETS} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) #add_custom_command( # OUTPUT ${CMAKE_SOURCE_DIR}/characters/female/vroid-normal-female.scene diff --git a/Game.cpp b/Game.cpp index 013cb3d..e470414 100644 --- a/Game.cpp +++ b/Game.cpp @@ -210,6 +210,7 @@ public: bool updated = false; if (isGuiEnabled()) return false; + std::cout << "GUI not enabled\n"; if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) { OgreAssert(ECS::get().has(), ""); setGuiEnabled(true); @@ -616,7 +617,6 @@ public: OGRE_NEW OgreBites::InputListenerChain( app.listeners); addInputListener(app.mInput); - std::cout << "Update listeners\n"; }); #if 0 ECS::get() @@ -758,7 +758,8 @@ void KeyboardListener::frameRendered(const Ogre::FrameEvent &evt) fps_timer.reset(); } update(evt.timeSinceLastFrame); - if (!isGuiEnabled()) { + if (!isGuiEnabled() || + (isGuiEnabled() && ECS::get().narrationBox)) { mApp->updateWorld(evt.timeSinceLastFrame); if (mInitDelay >= 0.0f) mInitDelay -= evt.timeSinceLastFrame; diff --git a/assets/blender/buildings/altar.blend b/assets/blender/buildings/altar.blend new file mode 100644 index 0000000..5f63900 --- /dev/null +++ b/assets/blender/buildings/altar.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:654a3a0dbbc23614a966123a66c62ad62d84faf35298fb3726adab9b61b6b848 +size 289327 diff --git a/assets/fonts/Kenney Bold.ttf b/assets/fonts/Kenney Bold.ttf new file mode 100644 index 0000000..ed946ec --- /dev/null +++ b/assets/fonts/Kenney Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d46b7795da2c3e214c573e5f92f0c49966d21317faa6862fab746f7fff19f0b6 +size 10436 diff --git a/lua-scripts/data.lua b/lua-scripts/data.lua index 25e364b..de7500e 100644 --- a/lua-scripts/data.lua +++ b/lua-scripts/data.lua @@ -36,4 +36,38 @@ function foo() end v = Vector3(0, 1, 2) end -foo() +narration = { + position = 1, + narration_start = { + "The party was hot, girls were sexy the wine, beer and whisky were in \ +enormous numbers. It was anniversary since you set sail with your friends. \ +The sea was calm and everything promised you another great night.", +"The whole year with your friends on your ship over vast seas of the world in decay was almost over.\ +It was so good year full of adventure, romance, indecency and luxury.", +"Your trusted friends decided that you have too much, they have too much of you and you owe them a lot.", +"They found you drunk in your room and moved to the deck and used ropes to \ +restrain you and attach a bucket of stones or something else heavy to your body.", +"After a few hours passed two strong people pulled you to the side and \ +dropped you into the sea. Last thing you heard before you hit the water was happy laugher..." + }, + progress = function(this) + if #this.narration_start < this.position then + return "" + end + local ret = this.narration_start[this.position] + this.position = this.position + 1 + return ret + end, +} +setup_handler(function(event) + print(event) + if event == "startup" then + main_menu() + elseif event == "narration_progress" then + narrate(narration:progress()) + + elseif event == "new_game" then + narrate(narration:progress()) + end +end) + diff --git a/resources.cfg b/resources.cfg index d83fbfb..d6240fc 100644 --- a/resources.cfg +++ b/resources.cfg @@ -22,6 +22,7 @@ FileSystem=skybox FileSystem=resources/buildings FileSystem=resources/vehicles FileSystem=resources/debug +FileSystem=resources/fonts # PBR media must come before the scripts that reference it #FileSystem=./Media/PBR #FileSystem=./Media/PBR/filament diff --git a/src/gamedata/CMakeLists.txt b/src/gamedata/CMakeLists.txt index 605182c..dd1e81c 100644 --- a/src/gamedata/CMakeLists.txt +++ b/src/gamedata/CMakeLists.txt @@ -1,5 +1,5 @@ project(gamedata) find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG) -add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp) -target_link_libraries(GameData PUBLIC OgreMain OgreBites OgreBullet OgrePaging OgreTerrain OgreOverlay flecs::flecs_static) +add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp) +target_link_libraries(GameData PUBLIC OgreMain OgreBites OgreBullet OgrePaging OgreTerrain OgreOverlay flecs::flecs_static lua) target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/src/gamedata/CharacterModule.cpp b/src/gamedata/CharacterModule.cpp index b476581..a181152 100644 --- a/src/gamedata/CharacterModule.cpp +++ b/src/gamedata/CharacterModule.cpp @@ -97,7 +97,8 @@ CharacterModule::CharacterModule(flecs::world &ecs) Ogre::ANIMBLEND_CUMULATIVE); Ogre::String animNames[AnimationControl::NUM_ANIMS] = { - "idle", "walking", "running" + "idle", "walking", "running", + "treading_water", "swimming" }; for (i = 0; i < AnimationControl::NUM_ANIMS; i++) { @@ -165,11 +166,11 @@ CharacterModule::CharacterModule(flecs::world &ecs) if (anim.currentAnim != anim.nextAnim) setAnimation(anim); }); - ecs.system( - "HandleAnimations1") + ecs.system("HandleAnimations1") .kind(flecs::OnUpdate) - .each([this](EngineData &eng, CharacterBase &ch, - AnimationControl &anim) { + .each([this](const EngineData &eng, const Input &input, + CharacterBase &ch, AnimationControl &anim) { float delta = eng.delta; Ogre::Real animSpeed = 1; if (anim.currentAnim != AnimationControl::ANIM_NONE) { @@ -177,6 +178,11 @@ CharacterModule::CharacterModule(flecs::world &ecs) AnimationControl::ANIM_WALK) anim.mAnims[anim.currentAnim]->addTime( delta * 1.0f); + else if (anim.currentAnim == + AnimationControl::ANIM_SWIMMING && + input.fast) + anim.mAnims[anim.currentAnim]->addTime( + delta * 20.0f); else anim.mAnims[anim.currentAnim]->addTime( delta * animSpeed); @@ -186,6 +192,24 @@ CharacterModule::CharacterModule(flecs::world &ecs) return; ch.mBoneMotion = ch.mRootBone->getPosition(); }); + ecs.system() + .kind(flecs::OnUpdate) + .with() + .with() + .with() + .each([this](flecs::entity e, CharacterBase &ch) { + float full_subm = 2.0f; + Ogre::Vector3 pos = ch.mBodyNode->getPosition(); + float current_subm = -Ogre::Math::Clamp( + pos.y + Ogre::Math::Sin(ch.mTimer * 0.13f + + 130.0f) * + 0.07f, + -full_subm, 0.0f); + if (current_subm > 0.9f) + ch.is_submerged = true; + else if (current_subm < 0.8f) + ch.is_submerged = false; + }); ecs.system( "HandleGravity") .kind(flecs::OnUpdate) @@ -222,6 +246,24 @@ CharacterModule::CharacterModule(flecs::world &ecs) } gr.gvelocity *= 0.99; }); + ecs.system("HandleSwimming") + .kind(flecs::OnUpdate) + .with() + .with() + .each([this](flecs::entity e, const EngineData &eng, + const AnimationControl &anim, + const CharacterBase &ch, CharacterVelocity &gr) { + if (anim.currentAnim == + AnimationControl::ANIM_SWIMMING) { + float h = Ogre::Math::Clamp( + 0.2f - ch.mBodyNode->getPosition().y, + 0.0f, 2000.0f); + if (h > 0.2 && h < 2.0f) + gr.gvelocity.y += 1.2 * (h + 1.0f) * h * + eng.delta; + } + }); ecs.system( "HandleRootMotionVelocity") .kind(flecs::OnUpdate) @@ -287,34 +329,72 @@ CharacterModule::CharacterModule(flecs::world &ecs) } } }); - ecs.system("HandlePlayerAnimations") + ecs.system( + "HandlePlayerAnimations") .kind(flecs::OnUpdate) .with() .with() - .each([](const Input &input, AnimationControl &anim) { + .each([](flecs::entity e, const Input &input, + const CharacterBase &ch, AnimationControl &anim) { if (!anim.configured) return; bool controls_idle = input.motion.zeroLength(); - bool anim_is_idle = anim.currentAnim == - AnimationControl::ANIM_IDLE; + bool anim_is_idle = + anim.currentAnim == + AnimationControl::ANIM_IDLE || + anim.currentAnim == + AnimationControl::ANIM_TREADING_WATER; bool anim_is_walking = anim.currentAnim == AnimationControl::ANIM_WALK; bool anim_is_running = anim.currentAnim == AnimationControl::ANIM_RUN; + bool anim_is_swimming = anim.currentAnim == + AnimationControl::ANIM_SWIMMING; bool anim_is_motion = anim_is_walking || - anim_is_running; + anim_is_running || + anim_is_swimming; + if (controls_idle) { + if (anim.currentAnim == + AnimationControl::ANIM_IDLE && + ch.is_submerged) + anim.nextAnim = AnimationControl:: + ANIM_TREADING_WATER; + else if (anim.currentAnim == + AnimationControl:: + ANIM_TREADING_WATER && + !ch.is_submerged) + anim.nextAnim = + AnimationControl::ANIM_IDLE; + } if (!controls_idle && anim_is_idle) { anim.reset = true; - if (input.fast) - anim.nextAnim = - AnimationControl::ANIM_RUN; - else - anim.nextAnim = - AnimationControl::ANIM_WALK; + if (ch.is_submerged) { + if (input.fast) + anim.nextAnim = + AnimationControl:: + ANIM_SWIMMING; + else + anim.nextAnim = + AnimationControl:: + ANIM_SWIMMING; + } else { + if (input.fast) + anim.nextAnim = + AnimationControl::ANIM_RUN; + else + anim.nextAnim = + AnimationControl:: + ANIM_WALK; + } } else anim.reset = false; if (controls_idle && anim_is_motion) - anim.nextAnim = AnimationControl::ANIM_IDLE; + if (ch.is_submerged) + anim.nextAnim = AnimationControl:: + ANIM_TREADING_WATER; + else + anim.nextAnim = + AnimationControl::ANIM_IDLE; else if (!controls_idle && anim_is_motion) { if (input.fast && anim_is_walking) anim.nextAnim = @@ -322,20 +402,42 @@ CharacterModule::CharacterModule(flecs::world &ecs) else if (!input.fast && anim_is_running) anim.nextAnim = AnimationControl::ANIM_WALK; + if ((anim_is_walking || anim_is_running) && + ch.is_submerged) { + if (input.fast) + anim.nextAnim = + AnimationControl:: + ANIM_SWIMMING; + else + anim.nextAnim = + AnimationControl:: + ANIM_SWIMMING; + } else if ((anim_is_swimming) && + !ch.is_submerged) { + if (input.fast) + anim.nextAnim = + AnimationControl::ANIM_RUN; + else + anim.nextAnim = + AnimationControl:: + ANIM_WALK; + } } }); - ecs.system( - "UpdateCharacterBase") + ecs.system("UpdateCharacterBase") .kind(flecs::OnUpdate) .with() - .each([](const EngineData &eng, CharacterBase &ch, - CharacterBody &body) { + .each([](const EngineData &eng, CharacterLocation &loc, + CharacterBase &ch, CharacterBody &body) { if (!ch.mBodyNode) { body.mController = nullptr; ch.mBodyEnt = eng.mScnMgr->createEntity( "normal-male.glb"); ch.mBodyNode = eng.mScnMgr->getRootSceneNode() ->createChildSceneNode(); + ch.mBodyNode->setOrientation(loc.orientation); + ch.mBodyNode->setPosition(loc.position); ch.mBodyNode->attachObject(ch.mBodyEnt); ch.mSkeleton = ch.mBodyEnt->getSkeleton(); body.mGhostObject = @@ -385,6 +487,11 @@ CharacterModule::CharacterModule(flecs::world &ecs) "No root bone"); ch.mRootBone = ch.mSkeleton->getBone("Root"); OgreAssert(ch.mRootBone, "No root bone"); + } else { + loc.orientation = + ch.mBodyNode->_getDerivedOrientation(); + loc.position = + ch.mBodyNode->_getDerivedPosition(); } }); ecs.system( @@ -592,16 +699,6 @@ CharacterModule::CharacterModule(flecs::world &ecs) << "\n"; }); #endif - /* Create player */ - player = ecs.entity("player"); - player.set({ AnimationControl::ANIM_NONE, - AnimationControl::ANIM_NONE, false, - false }); - player.set( - { "normal-male.glb", 0.0f, nullptr, nullptr, nullptr }); - player.set({ nullptr, nullptr, nullptr, false, false }); - player.add(); - player.add(); } void CharacterModule::setAnimation(AnimationControl &anim) diff --git a/src/gamedata/CharacterModule.h b/src/gamedata/CharacterModule.h index 62c0960..5bd948c 100644 --- a/src/gamedata/CharacterModule.h +++ b/src/gamedata/CharacterModule.h @@ -16,6 +16,11 @@ struct CharacterBase { Ogre::Node *mRootBone; Ogre::Vector3 mBoneMotion; Ogre::Vector3 mGoalDirection; // actual intended direction in world-space + bool is_submerged; +}; +struct CharacterLocation { + Ogre::Quaternion orientation; + Ogre::Vector3 position; }; struct CharacterBody { btPairCachingGhostObject *mGhostObject; @@ -33,6 +38,8 @@ struct AnimationControl { ANIM_IDLE = 0, ANIM_WALK, ANIM_RUN, + ANIM_TREADING_WATER, + ANIM_SWIMMING, NUM_ANIMS, ANIM_NONE = NUM_ANIMS }; @@ -48,7 +55,6 @@ struct AnimationControl { Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS]; }; struct CharacterModule { - flecs::entity player; CharacterModule(flecs::world &ecs); void setAnimation(AnimationControl &anim); void fadeAnimations(AnimationControl &anim, Ogre::Real deltaTime); diff --git a/src/gamedata/GUIModule.cpp b/src/gamedata/GUIModule.cpp index fb89a91..d3bdab9 100644 --- a/src/gamedata/GUIModule.cpp +++ b/src/gamedata/GUIModule.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include "GameData.h" #include "Components.h" +#include "LuaData.h" #include "GUIModule.h" namespace ECS { @@ -20,6 +22,50 @@ struct GUIData { }; struct GUIListener : public Ogre::RenderTargetListener { float panel_width; + bool enableEditor; + bool enableMapEditor; + ImFont *smallFont, *midFont, *bigFont; + Ogre::FontPtr _smallFont, _midFont, _bigFont; + GUIListener() + : Ogre::RenderTargetListener() + { + _midFont = createFont("midFont", "General", + "Jupiteroid-Regular.ttf", 18.0f); + _smallFont = createFont("smallFont", "General", + "Jupiteroid-Regular.ttf", 13.0f); + _bigFont = createFont("bigFont", "General", "Kenney Bold.ttf", + 32.0f); + smallFont = ECS::get().mGuiOverlay->addFont( + "smallFont", "General"); + OgreAssert(smallFont, "Could not load font"); + midFont = ECS::get().mGuiOverlay->addFont("midFont", + "General"); + OgreAssert(midFont, "Could not load font"); + bigFont = ECS::get().mGuiOverlay->addFont("bigFont", + "General"); + OgreAssert(bigFont, "Could not load font"); +#if 0 + Ogre::FontPtr _midFont = createFont("midFont", "General", + "Kenney Bold.ttf", 28.0f); +#endif +#if 0 + ImGui::GetIO().Fonts->Build(); +#endif + } + Ogre::FontPtr createFont(const Ogre::String &name, + const Ogre::String &group, + const Ogre::String &ttfname, float fontSize) + { + Ogre::FontPtr ret = + Ogre::FontManager::getSingleton().create(name, group); + ret->setType(Ogre::FontType::FT_TRUETYPE); + ret->setSource(ttfname); + ret->setTrueTypeSize(fontSize); + ret->setTrueTypeResolution(75); + ret->addCodePointRange(Ogre::Font::CodePointRange(30, 128)); + ret->load(); + return ret; + } void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override { @@ -36,14 +82,24 @@ struct GUIListener : public Ogre::RenderTargetListener { ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(window_width, window_height), ImGuiCond_Always); - ImGui::Begin("Dumb and Stupid"); + ImGui::Begin("Control"); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); - if (ImGui::Button("Shitty Quit button")) + if (ImGui::Button("Quit")) Ogre::Root::getSingleton().queueEndRendering(); - if (ImGui::Button("Chick-chick")) + if (ImGui::Button("Return")) ECS::get().get().finish(); - ImGui::Text("We do stoopid..."); + if (ImGui::Button("Enable/Disable item editor")) { + enableEditor ^= true; + if (enableEditor) + enableMapEditor = false; + } + if (ImGui::Button("Enable/Disable map editor")) { + enableMapEditor ^= true; + if (enableMapEditor) + enableEditor = false; + } + ImGui::Text("Text message..."); ImGui::End(); } void create_entity_node(const Ogre::String &name, int key) @@ -140,6 +196,9 @@ struct GUIListener : public Ogre::RenderTargetListener { ImGui::Text("Name: %s", pname.c_str()); } } + void map_editor() + { + } void preview(const Ogre::RenderTargetViewportEvent &evt) { int i; @@ -161,118 +220,214 @@ struct GUIListener : public Ogre::RenderTargetListener { ImGuiWindowFlags_NoInputs); // if (ECS::get().get().enabled) // ECS::get().get().app->setWindowGrab(true); - ImGui::Text( + ImGui::PushFont(bigFont); + ImGui::TextWrapped( + "%s", "This game does not autosave. Please use save function to keep your state"); + ImGui::PopFont(); ImGui::End(); - } - if (ECS::get().get().enabled) { - buttons_panel(); - buildings_editor(); - ImVec2 size = ImGui::GetMainViewport()->Size; - float window_width = size.x * 0.2f; - if (window_width > panel_width) - window_width = panel_width; - float window_height = size.y * 0.5f - 20; - ImGui::SetNextWindowPos(ImVec2(size.x - window_width, - size.y * 0.5f + 20), - ImGuiCond_Always); - ImGui::SetNextWindowSize(ImVec2(window_width, - window_height), - ImGuiCond_Always); - // ImGui::Begin("Dumb and Stupid", &mKbd.gui_active); - ImGui::Begin("Panel..."); - std::deque tree_input_queue, - tree_output_queue; - std::vector tree_list; - tree_input_queue.push_back( - 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])); + } else if (ECS::get().get().enabled) { + if (ECS::get().get().narrationBox) { + ImVec2 size = ImGui::GetMainViewport()->Size; + ImGui::SetNextWindowPos(ImVec2(0, + size.y * 0.75f), + ImGuiCond_Always); + ImGui::SetNextWindowSize(ImVec2(size.x, + size.y * 0.25f), + ImGuiCond_Always); + ImGui::Begin("Narration...", NULL, + ImGuiWindowFlags_NoTitleBar); + ImGui::PushFont(midFont); + ImVec2 p = ImGui::GetCursorScreenPos(); + ImGui::TextWrapped( + "%s", ECS::get() + .get() + .narrationText.c_str()); + ImGui::SetCursorScreenPos(p); + if (ImGui::InvisibleButton( + "Background", + ImGui::GetWindowSize())) + ECS::get().mLua->call_handler( + "narration_progress"); + 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( - nullptr); - } - } else - tree_output_queue.push_back( - item); + 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(); } - 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; + 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); + 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 (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--; } - if (tree_list[count]) - depth++; - else - depth--; + ImGui::Spacing(); + ImGui::End(); } - ImGui::Spacing(); - ImGui::End(); } } }; @@ -293,7 +448,7 @@ GUIModule::GUIModule(flecs::world &ecs) priv.mGuiOverlay = nullptr; }) .add(flecs::Singleton); - ecs.set({ false, true, false }); + ecs.set({ false, true, false, false, false }); ecs.set({ nullptr, {}, nullptr }); ui_wait = ecs.system("SetupGUI") @@ -311,9 +466,11 @@ GUIModule::GUIModule(flecs::world &ecs) OgreAssert(app.mGuiOverlay, "No ImGUI overlay"); gui.mGuiOverlay = app.mGuiOverlay; + gui.mGUIListener = new GUIListener(); gui.mGuiOverlay->setZOrder(300); gui.mGuiOverlay->show(); - gui.mGUIListener = new GUIListener(); + gui.mGUIListener->panel_width = 300.0f; + gui.mGUIListener->enableEditor = false; window.window->addListener( gui.mGUIListener); int i; diff --git a/src/gamedata/GUIModule.h b/src/gamedata/GUIModule.h index fdd5a78..14b0fd9 100644 --- a/src/gamedata/GUIModule.h +++ b/src/gamedata/GUIModule.h @@ -10,6 +10,9 @@ struct GUI { bool enabled; bool grab; bool grabChanged; + bool narrationBox; + bool mainMenu; + Ogre::String narrationText; static void setWindowGrab(bool g = true) { ECS::GUI &gui = ECS::get().get_mut(); @@ -23,6 +26,8 @@ struct GUI { { ECS::GUI &gui = ECS::get().get_mut(); gui.enabled = false; + gui.mainMenu = false; + gui.narrationBox = false; ECS::get().modified(); setWindowGrab(true); } diff --git a/src/gamedata/GameData.cpp b/src/gamedata/GameData.cpp index 0055670..8f52f6d 100644 --- a/src/gamedata/GameData.cpp +++ b/src/gamedata/GameData.cpp @@ -7,10 +7,13 @@ #include "TerrainModule.h" #include "SunModule.h" #include "GUIModule.h" +#include "LuaData.h" +#include "WorldMapModule.h" namespace ECS { static flecs::world ecs; +flecs::entity player; void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, Ogre::SceneNode *cameraNode, Ogre::Camera *camera, Ogre::RenderWindow *window) @@ -37,6 +40,9 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, ecs.import (); ecs.import (); ecs.import (); + ecs.import (); + ecs.import (); + ecs.import (); ecs.system("UpdateDelta") .kind(flecs::OnUpdate) .each([](EngineData &eng) { @@ -84,6 +90,26 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, false, { 0, 0, 0 } }); std::cout << "Setup GameData done\n"; + + /* Create player */ + player = ecs.entity("player"); + Ogre::Vector3 playerPos(0, 0, 4); + player.set({ { 0, 0, 0, 1 }, playerPos }); + player.set({ AnimationControl::ANIM_NONE, + AnimationControl::ANIM_NONE, false, + false }); + player.set({ "normal-male.glb", + 0.0f, + nullptr, + nullptr, + nullptr, + nullptr, + { 0, 0, 0 }, + { 0, 0, 0 }, + false }); + player.set({ nullptr, nullptr, nullptr, false, false }); + player.add(); + player.add(); } void update(float delta) { diff --git a/src/gamedata/GameData.h b/src/gamedata/GameData.h index 31d0a3b..4f42e11 100644 --- a/src/gamedata/GameData.h +++ b/src/gamedata/GameData.h @@ -4,6 +4,7 @@ #include namespace ECS { +extern flecs::entity player; void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, Ogre::SceneNode *cameraNode, Ogre::Camera *camera, Ogre::RenderWindow *window); diff --git a/src/gamedata/LuaData.cpp b/src/gamedata/LuaData.cpp new file mode 100644 index 0000000..72fd8ca --- /dev/null +++ b/src/gamedata/LuaData.cpp @@ -0,0 +1,133 @@ +#include "GameData.h" +#include "Components.h" +#include "GUIModule.h" +#include "LuaData.h" +namespace ECS +{ + +int LuaData::setup_handler() +{ + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_pushvalue(L, 1); + int ref = luaL_ref(L, LUA_REGISTRYINDEX); + setup_handlers.push_back(ref); + return 0; +} +int LuaData::call_handler(const Ogre::String &event) +{ + int i; + for (i = 0; i < setup_handlers.size(); i++) { + lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]); + lua_pushstring(L, event.c_str()); + lua_pcall(L, 1, 0, 0); + } + return 0; +} +LuaData::LuaData() + : L(luaL_newstate()) +{ + luaopen_base(L); + luaopen_package(L); + lua_pushcfunction(L, [](lua_State *L) -> int { + OgreAssert(false, "Crash function called"); + return 0; + }); + lua_setglobal(L, "crash"); + lua_pushcfunction(L, [](lua_State *L) -> int { + luaL_checktype(L, 1, LUA_TFUNCTION); + ECS::get().mLua->setup_handler(); + return 0; + }); + lua_setglobal(L, "setup_handler"); + lua_pushcfunction(L, [](lua_State *L) -> int { + luaL_checktype(L, 1, LUA_TSTRING); + size_t len; + Ogre::String message(luaL_tolstring(L, 1, &len)); + if (message.length() == 0 && ECS::get_mut().narrationBox) { + ECS::get_mut().enabled = false; + ECS::get_mut().grab = true; + ECS::get_mut().grabChanged = true; + ECS::get_mut().narrationText = message; + ECS::get_mut().narrationBox = false; + ECS::modified(); + } else { + std::replace(message.begin(), message.end(), '\n', ' '); + std::replace(message.begin(), message.end(), '\r', ' '); + + std::cout << "narrator message: " << message + << std::endl; + ECS::get_mut().enabled = true; + ECS::get_mut().grab = false; + ECS::get_mut().grabChanged = true; + ECS::get_mut().narrationText = message; + ECS::get_mut().narrationBox = true; + ECS::modified(); + } + + return 0; + }); + lua_setglobal(L, "narrate"); + lua_pushcfunction(L, [](lua_State *L) -> int { + // ECS::get_mut().mainMenu = true; + ECS::get_mut().enabled = true; + ECS::get_mut().mainMenu = true; + ECS::get_mut().grab = false; + ECS::get_mut().grabChanged = true; + ECS::modified(); + return 0; + }); + lua_setglobal(L, "main_menu"); +} + +LuaData::~LuaData() +{ + lua_close(L); +} + +void LuaData::lateSetup() +{ + Ogre::DataStreamList streams = + Ogre::ResourceGroupManager::getSingleton().openResources( + "*.lua", "LuaScripts"); + while (!streams.empty()) { + Ogre::DataStreamPtr s = streams.front(); + std::cout << "stream: " << s->getAsString() << "\n"; + streams.pop_front(); + if (luaL_dostring(L, s->getAsString().c_str()) != LUA_OK) { + std::cout << "error: " << lua_tostring(L, -1) << "\n"; + OgreAssert(false, "Script failure"); + } + } + const char *lua_code = "\n\ + function stuff()\n\ + return 4\n\ + end\n\ + x = stuff()\n\ + "; + luaL_dostring(L, lua_code); + lua_getglobal(L, "x"); + int x = lua_tonumber(L, 1); + std::cout << "lua: " << x << "\n"; +} + +LuaModule::LuaModule(flecs::world &ecs) +{ + ecs.component().add(flecs::Singleton); + ecs.set({ OGRE_NEW LuaData, false, false }); + ecs.system("LuaUpdate") + .kind(flecs::OnUpdate) + .each([](const EngineData &eng, LuaBase &lua) { + if (!lua.setup_called) { + lua.mLua->lateSetup(); + lua.mLua->call_handler("setup"); + lua.setup_called = true; + } + if (!lua.startup_called) { + if (eng.startupDelay <= 0.0f) { + lua.mLua->call_handler("startup"); + lua.startup_called = true; + } + } + }); +} +} \ No newline at end of file diff --git a/src/gamedata/LuaData.h b/src/gamedata/LuaData.h new file mode 100644 index 0000000..135a381 --- /dev/null +++ b/src/gamedata/LuaData.h @@ -0,0 +1,29 @@ +#ifndef LUA_DATA_H +#define LUA_DATA_H +#include "lua.hpp" +#include +#include +#include +#include +namespace ECS +{ +struct LuaData { + lua_State *L; + std::vector setup_handlers; + int setup_handler(); + int call_handler(const Ogre::String &event); + + LuaData(); + virtual ~LuaData(); + void lateSetup(); +}; +struct LuaBase { + LuaData *mLua; + bool setup_called; + bool startup_called; +}; +struct LuaModule { + LuaModule(flecs::world &ecs); +}; +} +#endif diff --git a/src/gamedata/TerrainModule.cpp b/src/gamedata/TerrainModule.cpp index 0ec1fcb..dab6de2 100644 --- a/src/gamedata/TerrainModule.cpp +++ b/src/gamedata/TerrainModule.cpp @@ -31,77 +31,30 @@ namespace ECS { -class FlatTerrainDefiner - : public Ogre::TerrainPagedWorldSection::TerrainDefiner, - public Ogre::FrameListener { - Ogre::SceneManager *mScnMgr; - Ogre::Bullet::DynamicsWorld *mWorld; - struct gen_collider { - Ogre::TerrainGroup *group; - long x; - long y; - }; - std::deque collider_queue; - Ogre::Image img, img_noise, img_brushes; - -public: - FlatTerrainDefiner(Ogre::SceneManager *scm, - Ogre::Bullet::DynamicsWorld *world) - : Ogre::TerrainPagedWorldSection::TerrainDefiner() - , Ogre::FrameListener() - , mScnMgr(scm) - , mWorld(world) +#define BRUSH_SIZE 64 +struct HeightData { + Ogre::Image img; + Ogre::Image img_brushes; + Ogre::Image img_noise; + static HeightData *singleton; + HeightData() { - Ogre::Root::getSingleton().addFrameListener(this); img.load( "world_map.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - img_noise.load( - "terrain.png", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); img_brushes.load( "brushes.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + img_noise.load( + "terrain.png", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } - -private: - float get_noise_height(const Ogre::Vector2 &worldOffset, int x, int y) + static HeightData *get_singleton() { - int h; - Ogre::Vector2 noisePoint; - - struct noise_types { - Ogre::Vector2 noiseOfft; - float noiseMul; - float noiseBias; - float noiseAmp; - }; - static struct noise_types noise_pass[] = { - { { -100.0f, 70.0f }, 10.2f, -0.55f, 5.0f }, - { { -130.0f, 55.0f }, 5.35f, -0.55f, 1.0f } - }; - static float noise_values[] = { 0.0f, 0.0f }; - for (h = 0; h < (int)sizeof(noise_values) / - (int)sizeof(noise_values[0]); - h++) { - noisePoint = (worldOffset + Ogre::Vector2(x, y) + - noise_pass[h].noiseOfft) * - noise_pass[h].noiseMul; - int noise_x = - (int)(noisePoint.x + img_noise.getWidth() / 2) % - img_noise.getWidth(); - int noise_y = (int)(noisePoint.y + - img_noise.getHeight() / 2) % - img_noise.getHeight(); - Ogre::ColourValue noise_color = - img_noise.getColourAt(noise_x, noise_y, 0); - noise_values[h] = - (noise_color.r + noise_pass[h].noiseBias) * - noise_pass[h].noiseAmp; - } - return noise_values[0] + noise_values[1]; + if (!singleton) + singleton = new HeightData(); + return singleton; } -#define BRUSH_SIZE 64 float get_brush_height(int id, int x, int y) { int m = 0; @@ -149,7 +102,96 @@ private: out: return height; } + float get_noise_height(const Ogre::Vector2 &worldOffset, int x, int y) + { + int h; + Ogre::Vector2 noisePoint; + struct noise_types { + Ogre::Vector2 noiseOfft; + float noiseMul; + float noiseBias; + float noiseAmp; + }; + static struct noise_types noise_pass[] = { + { { -100.0f, 70.0f }, 10.2f, -0.55f, 5.0f }, + { { -130.0f, 55.0f }, 5.35f, -0.55f, 1.0f } + }; + static float noise_values[] = { 0.0f, 0.0f }; + for (h = 0; h < (int)sizeof(noise_values) / + (int)sizeof(noise_values[0]); + h++) { + noisePoint = (worldOffset + Ogre::Vector2(x, y) + + noise_pass[h].noiseOfft) * + noise_pass[h].noiseMul; + int noise_x = + (int)(noisePoint.x + img_noise.getWidth() / 2) % + img_noise.getWidth(); + int noise_y = (int)(noisePoint.y + + img_noise.getHeight() / 2) % + img_noise.getHeight(); + Ogre::ColourValue noise_color = + img_noise.getColourAt(noise_x, noise_y, 0); + noise_values[h] = + (noise_color.r + noise_pass[h].noiseBias) * + noise_pass[h].noiseAmp; + } + return noise_values[0] + noise_values[1]; + } + float get_height(Ogre::TerrainGroup *terrainGroup, long x, long y, + int j, int i) + { + uint16_t terrainSize = terrainGroup->getTerrainSize(); + Ogre::Vector2 worldOffset(Ogre::Real(x * (terrainSize - 1)), + Ogre::Real(y * (terrainSize - 1))); + float brush_height0 = + HeightData::get_singleton()->get_brush_height( + 0, j % BRUSH_SIZE, i % BRUSH_SIZE) - + 0.55f; + float brush_height1 = + HeightData::get_singleton()->get_brush_height( + 1, j % BRUSH_SIZE, i % BRUSH_SIZE) - + 0.55f; + float mheight = + Ogre::Math::lerp( + brush_height1, brush_height0, + HeightData::get_singleton()->get_base_height( + worldOffset, j, i)) * + 120.0f; + float height = mheight; + if (mheight > 0.5f) + height += 2.0f + get_noise_height(worldOffset, j, i); + else if (mheight < -0.5f) + height -= 2.0f + get_noise_height(worldOffset, j, i); + return height; + } +}; +HeightData *HeightData::singleton = nullptr; + +class FlatTerrainDefiner + : public Ogre::TerrainPagedWorldSection::TerrainDefiner, + public Ogre::FrameListener { + Ogre::SceneManager *mScnMgr; + Ogre::Bullet::DynamicsWorld *mWorld; + struct gen_collider { + Ogre::TerrainGroup *group; + long x; + long y; + }; + std::deque collider_queue; + +public: + FlatTerrainDefiner(Ogre::SceneManager *scm, + Ogre::Bullet::DynamicsWorld *world) + : Ogre::TerrainPagedWorldSection::TerrainDefiner() + , Ogre::FrameListener() + , mScnMgr(scm) + , mWorld(world) + { + Ogre::Root::getSingleton().addFrameListener(this); + } + +private: public: void define(Ogre::TerrainGroup *terrainGroup, long x, long y) override { @@ -158,37 +200,15 @@ public: MEMCATEGORY_GEOMETRY); // float *heightMapCollider = OGRE_ALLOC_T( // float, terrainSize *terrainSize, MEMCATEGORY_GEOMETRY); - Ogre::Vector2 worldOffset(Ogre::Real(x * (terrainSize - 1)), - Ogre::Real(y * (terrainSize - 1))); - Ogre::Vector2 worldOrigin = - Ogre::Vector2(img.getWidth(), img.getHeight()) * 0.5f; + // Ogre::Vector2 worldOrigin = + // Ogre::Vector2(img.getWidth(), img.getHeight()) * 0.5f; float chunk = 128.0f; Ogre::Vector2 revisedValuePoint; for (int i = 0; i < terrainSize; i++) for (int j = 0; j < terrainSize; j++) { - float brush_height0 = - get_brush_height(0, j % BRUSH_SIZE, - i % BRUSH_SIZE) - - 0.55f; - float brush_height1 = - get_brush_height(1, j % BRUSH_SIZE, - i % BRUSH_SIZE) - - 0.55f; - float mheight = - Ogre::Math::lerp( - brush_height1, brush_height0, - get_base_height(worldOffset, j, - i)) * - 120.0f; - float height = mheight; - if (mheight > 0.5f) - height += 2.0f + - get_noise_height(worldOffset, - j, i); - else if (mheight < -0.5f) - height -= 2.0f + - get_noise_height(worldOffset, - j, i); + float height = + HeightData::get_singleton()->get_height( + terrainGroup, x, y, j, i); // height = -2.0f; heightMap[i * terrainSize + j] = height; @@ -277,6 +297,26 @@ public: created = true; } collider_queue.pop_front(); + // FIXME: create entities and components instead + Ogre::SceneNode *items = + terrain->_getRootSceneNode() + ->createChildSceneNode(); + for (int i = 0; i < ECS::get() + .altar_items.size(); + i++) { + const struct PlacementObjects::item &item = + ECS::get() + .altar_items[i]; + Ogre::Entity *ent = + group->getSceneManager() + ->createEntity( + item.entity); + Ogre::SceneNode *what = + items->createChildSceneNode(); + what->attachObject(ent); + what->setOrientation(item.rotation); + what->setPosition(item.position); + } } else { output.push_back(collider_queue.front()); collider_queue.pop_front(); @@ -433,6 +473,7 @@ TerrainModule::TerrainModule(flecs::world &ecs) terrain.mTerrainGroup->freeTemporaryResources(); std::cout << "Terrain setup done\n"; + ECS::get().set({}); } if (sun.mSun && priv.mSunUpdate.getMilliseconds() > 1000) { @@ -468,5 +509,113 @@ TerrainModule::TerrainModule(flecs::world &ecs) ECS::get().add(); } }); + ecs.system("UpdatePlacementObjects") + .kind(flecs::OnUpdate) + .each([](const Terrain &terrain, PlacementObjects &placement) { + if (placement.altar_items.size() == 0) { + struct PlacementObjects::item item; + int i, j; + int worldSize = terrain.mTerrainGroup + ->getTerrainWorldSize(); + uint16_t terrainSize = + terrain.mTerrainGroup->getTerrainSize(); + item.entity = "altar.glb"; + item.rotation = Ogre::Quaternion(0, 0, 0, 1); + item.position = Ogre::Vector3(0, 0, 0); + float height = + HeightData::get_singleton()->get_height( + terrain.mTerrainGroup, 0, 0, 0, + 0); + item.position.y = height; + placement.altar_items.push_back(item); + for (i = -64000; i < 64000; i += 1000) + for (j = -64000; j < 64000; j += 1000) { + if (i == 0 && j == 0) + continue; + Ogre::Vector3 position(i, 0, j); + long xslot, yslot; + terrain.mTerrainGroup + ->convertWorldPositionToTerrainSlot( + position, + &xslot, &yslot); + Ogre::Vector3 slotpos; + terrain.mTerrainGroup + ->convertTerrainSlotToWorldPosition( + xslot, yslot, + &slotpos); + Ogre::Vector3 offset = + (position - slotpos) * + terrainSize / worldSize; + height = + HeightData::get_singleton() + ->get_height( + terrain.mTerrainGroup, + xslot, + yslot, + (int)offset.x + + (terrainSize - + 1) / 2, + (int)offset.z + + (terrainSize - + 1) / 2); +#if 0 + height = + terrain.mTerrainGroup + ->getHeightAtWorldPosition( + position); +#endif + if (height > -9.0f) + continue; + std::cout << "worldSize: " + << worldSize - 1 + << std::endl; + std::cout << "height: " << i + << " " << j << " " + << height + << std::endl; + item.entity = "altar.glb"; + item.rotation = + Ogre::Quaternion(0, 0, + 0, 1); + position.y = height; + item.position = position; + placement.altar_items.push_back( + item); + } + for (i = 0; i < placement.altar_items.size(); + i++) { + std::cout << "placement: " << i << " " + << placement.altar_items[i] + .position + << std::endl; + } + } + flecs::entity player = ECS::player; + CharacterLocation &loc = + player.get_mut(); + float height = + get_height(terrain.mTerrainGroup, loc.position); + loc.position.y = height + 0.0f; + player.get().mBodyNode->setPosition( + loc.position); + player.get().mBodyNode->setOrientation( + Ogre::Quaternion()); + player.modified(); + }); +} +float TerrainModule::get_height(Ogre::TerrainGroup *group, + const Ogre::Vector3 &position) +{ + int worldSize = group->getTerrainWorldSize(); + uint16_t terrainSize = group->getTerrainSize(); + long xslot, yslot; + group->convertWorldPositionToTerrainSlot(position, &xslot, &yslot); + Ogre::Vector3 slotpos; + group->convertTerrainSlotToWorldPosition(xslot, yslot, &slotpos); + Ogre::Vector3 offset = (position - slotpos) * terrainSize / worldSize; + float height = HeightData::get_singleton()->get_height( + group, xslot, yslot, (int)offset.x + (terrainSize - 1) / 2, + (int)offset.z + (terrainSize - 1) / 2); + return height; } } \ No newline at end of file diff --git a/src/gamedata/TerrainModule.h b/src/gamedata/TerrainModule.h index 6c7c1df..befd053 100644 --- a/src/gamedata/TerrainModule.h +++ b/src/gamedata/TerrainModule.h @@ -23,8 +23,18 @@ struct Terrain { Ogre::Vector3 mTerrainPos; }; +struct PlacementObjects { + struct item { + Ogre::String entity; + Ogre::Quaternion rotation; + Ogre::Vector3 position; + }; + std::vector altar_items; +}; struct TerrainModule { TerrainModule(flecs::world &ecs); + static float get_height(Ogre::TerrainGroup *group, + const Ogre::Vector3 &position); }; } #endif \ No newline at end of file diff --git a/src/gamedata/WorldMapModule.cpp b/src/gamedata/WorldMapModule.cpp new file mode 100644 index 0000000..10dce6c --- /dev/null +++ b/src/gamedata/WorldMapModule.cpp @@ -0,0 +1,6 @@ +#include "WorldMapModule.h" + +ECS::WorldMapModule::WorldMapModule(flecs::world &ecs) +{ + ecs.component(); +} diff --git a/src/gamedata/WorldMapModule.h b/src/gamedata/WorldMapModule.h new file mode 100644 index 0000000..1ccd23a --- /dev/null +++ b/src/gamedata/WorldMapModule.h @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_MODULE_H +#define WORLD_MAP_MODULE_H +#include +namespace ECS +{ +struct WorldMap {}; +struct WorldMapModule { + WorldMapModule(flecs::world &ecs); +}; +} +#endif diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index c8ce393..2a97b51 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -19,7 +19,7 @@ foreach(LUA_FILE ${LUA_OBJ}) list(APPEND LUA_SRC lua-5.4.8/src/${LUA_SRC_ITEM}) endforeach() add_library(lua ${LUA_SRC}) -target_include_directories(lua PRIVATE lua-5.4.8/src) +target_include_directories(lua PUBLIC lua-5.4.8/src) add_executable(luavm lua-5.4.8/src/lua.c) target_link_libraries(luavm lua m) target_include_directories(luavm PRIVATE lua-5.4.8/src)