Selaa lähdekoodia

fix selection ring for cavalery

djeada 1 kuukausi sitten
vanhempi
sitoutus
3f2f0c5c93

+ 10 - 2
game/systems/terrain_alignment_system.cpp

@@ -3,6 +3,7 @@
 #include "../core/entity.h"
 #include "../core/entity.h"
 #include "../core/world.h"
 #include "../core/world.h"
 #include "../map/terrain_service.h"
 #include "../map/terrain_service.h"
+#include "../units/troop_config.h"
 
 
 namespace Game::Systems {
 namespace Game::Systems {
 
 
@@ -31,8 +32,15 @@ void TerrainAlignmentSystem::alignEntityToTerrain(
   float terrainHeight = terrainService.getTerrainHeight(transform->position.x,
   float terrainHeight = terrainService.getTerrainHeight(transform->position.x,
                                                         transform->position.z);
                                                         transform->position.z);
 
 
-  const float entityBaseOffset = 0.0f;
-  transform->position.y = terrainHeight + entityBaseOffset;
+  float entityBaseOffset = 0.0f;
+  if (auto *unit = entity->getComponent<Engine::Core::UnitComponent>()) {
+    if (!unit->unitType.empty()) {
+      entityBaseOffset = Game::Units::TroopConfig::instance()
+                              .getSelectionRingGroundOffset(unit->unitType);
+    }
+  }
+
+  transform->position.y = terrainHeight + entityBaseOffset * transform->scale.y;
 }
 }
 
 
 } // namespace Game::Systems
 } // namespace Game::Systems

+ 21 - 0
game/units/troop_config.h

@@ -62,6 +62,18 @@ public:
     return getSelectionRingYOffset(troopTypeFromString(unitType));
     return getSelectionRingYOffset(troopTypeFromString(unitType));
   }
   }
 
 
+  float getSelectionRingGroundOffset(TroopType unitType) const {
+    auto it = m_selectionRingGroundOffset.find(unitType);
+    if (it != m_selectionRingGroundOffset.end()) {
+      return it->second;
+    }
+    return 0.0f;
+  }
+
+  float getSelectionRingGroundOffset(const std::string &unitType) const {
+    return getSelectionRingGroundOffset(troopTypeFromString(unitType));
+  }
+
   void registerTroopType(TroopType unitType, int individualsPerUnit) {
   void registerTroopType(TroopType unitType, int individualsPerUnit) {
     m_individualsPerUnit[unitType] = individualsPerUnit;
     m_individualsPerUnit[unitType] = individualsPerUnit;
   }
   }
@@ -78,33 +90,42 @@ public:
     m_selectionRingYOffset[unitType] = offset;
     m_selectionRingYOffset[unitType] = offset;
   }
   }
 
 
+  void registerSelectionRingGroundOffset(TroopType unitType, float offset) {
+    m_selectionRingGroundOffset[unitType] = offset;
+  }
+
 private:
 private:
   TroopConfig() {
   TroopConfig() {
     m_individualsPerUnit[TroopType::Archer] = 20;
     m_individualsPerUnit[TroopType::Archer] = 20;
     m_maxUnitsPerRow[TroopType::Archer] = 5;
     m_maxUnitsPerRow[TroopType::Archer] = 5;
     m_selectionRingSize[TroopType::Archer] = 1.2f;
     m_selectionRingSize[TroopType::Archer] = 1.2f;
     m_selectionRingYOffset[TroopType::Archer] = 0.0f;
     m_selectionRingYOffset[TroopType::Archer] = 0.0f;
+    m_selectionRingGroundOffset[TroopType::Archer] = 0.0f;
 
 
     m_individualsPerUnit[TroopType::Knight] = 15;
     m_individualsPerUnit[TroopType::Knight] = 15;
     m_maxUnitsPerRow[TroopType::Knight] = 5;
     m_maxUnitsPerRow[TroopType::Knight] = 5;
     m_selectionRingSize[TroopType::Knight] = 1.1f;
     m_selectionRingSize[TroopType::Knight] = 1.1f;
     m_selectionRingYOffset[TroopType::Knight] = 0.0f;
     m_selectionRingYOffset[TroopType::Knight] = 0.0f;
+    m_selectionRingGroundOffset[TroopType::Knight] = 0.0f;
 
 
     m_individualsPerUnit[TroopType::Spearman] = 24;
     m_individualsPerUnit[TroopType::Spearman] = 24;
     m_maxUnitsPerRow[TroopType::Spearman] = 6;
     m_maxUnitsPerRow[TroopType::Spearman] = 6;
     m_selectionRingSize[TroopType::Spearman] = 1.4f;
     m_selectionRingSize[TroopType::Spearman] = 1.4f;
     m_selectionRingYOffset[TroopType::Spearman] = 0.0f;
     m_selectionRingYOffset[TroopType::Spearman] = 0.0f;
+    m_selectionRingGroundOffset[TroopType::Spearman] = 0.0f;
 
 
     m_individualsPerUnit[TroopType::MountedKnight] = 9;
     m_individualsPerUnit[TroopType::MountedKnight] = 9;
     m_maxUnitsPerRow[TroopType::MountedKnight] = 3;
     m_maxUnitsPerRow[TroopType::MountedKnight] = 3;
     m_selectionRingSize[TroopType::MountedKnight] = 2.0f;
     m_selectionRingSize[TroopType::MountedKnight] = 2.0f;
     m_selectionRingYOffset[TroopType::MountedKnight] = 0.0f;
     m_selectionRingYOffset[TroopType::MountedKnight] = 0.0f;
+    m_selectionRingGroundOffset[TroopType::MountedKnight] = 1.35f;
   }
   }
 
 
   std::unordered_map<TroopType, int> m_individualsPerUnit;
   std::unordered_map<TroopType, int> m_individualsPerUnit;
   std::unordered_map<TroopType, int> m_maxUnitsPerRow;
   std::unordered_map<TroopType, int> m_maxUnitsPerRow;
   std::unordered_map<TroopType, float> m_selectionRingSize;
   std::unordered_map<TroopType, float> m_selectionRingSize;
   std::unordered_map<TroopType, float> m_selectionRingYOffset;
   std::unordered_map<TroopType, float> m_selectionRingYOffset;
+  std::unordered_map<TroopType, float> m_selectionRingGroundOffset;
 };
 };
 
 
 } // namespace Units
 } // namespace Units

+ 0 - 23
render/entity/arrow_vfx_renderer.cpp

@@ -376,28 +376,6 @@ static inline void drawBowAndArrow(const DrawContext &p, ISubmitter &out,
            nullptr, 1.0f);
            nullptr, 1.0f);
 }
 }
 
 
-static inline void drawSelectionFX(const DrawContext &p, ISubmitter &out) {
-  if (p.selected || p.hovered) {
-    float ringSize = 0.5f;
-    if (p.entity) {
-      auto *unit = p.entity->getComponent<Engine::Core::UnitComponent>();
-      if (unit && !unit->unitType.empty()) {
-        ringSize = Game::Units::TroopConfig::instance().getSelectionRingSize(
-            unit->unitType);
-      }
-    }
-
-    QMatrix4x4 ringM;
-    QVector3D pos = p.model.column(3).toVector3D();
-    ringM.translate(pos.x(), 0.15f, pos.z());
-    ringM.scale(ringSize, 1.0f, ringSize);
-    if (p.selected)
-      out.selectionRing(ringM, 0.6f, 0.25f, QVector3D(0.2f, 0.8f, 0.2f));
-    else
-      out.selectionRing(ringM, 0.35f, 0.15f, QVector3D(0.90f, 0.90f, 0.25f));
-  }
-}
-
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
   registry.registerRenderer(
   registry.registerRenderer(
       "archer", [](const DrawContext &p, ISubmitter &out) {
       "archer", [](const DrawContext &p, ISubmitter &out) {
@@ -429,7 +407,6 @@ void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
         drawArms(p, out, pose, colors);
         drawArms(p, out, pose, colors);
         drawHeadAndNeck(p, out, pose, colors);
         drawHeadAndNeck(p, out, pose, colors);
         drawBowAndArrow(p, out, pose, colors);
         drawBowAndArrow(p, out, pose, colors);
-        drawSelectionFX(p, out);
       });
       });
 }
 }
 
 

+ 0 - 53
render/humanoid_base.cpp

@@ -6,7 +6,6 @@
 #include "../game/units/troop_config.h"
 #include "../game/units/troop_config.h"
 #include "../game/visuals/team_colors.h"
 #include "../game/visuals/team_colors.h"
 #include "geom/math_utils.h"
 #include "geom/math_utils.h"
-#include "geom/selection_ring.h"
 #include "geom/transforms.h"
 #include "geom/transforms.h"
 #include "gl/mesh.h"
 #include "gl/mesh.h"
 #include "gl/primitives.h"
 #include "gl/primitives.h"
@@ -501,57 +500,6 @@ void HumanoidRendererBase::drawShoulderDecorations(const DrawContext &ctx,
                                                    const QVector3D &rightAxis,
                                                    const QVector3D &rightAxis,
                                                    ISubmitter &out) const {}
                                                    ISubmitter &out) const {}
 
 
-void HumanoidRendererBase::drawSelectionFX(const DrawContext &ctx,
-                                           ISubmitter &out) {
-  if (ctx.selected || ctx.hovered) {
-    float ringSize = 0.5f;
-    float ringOffset = 0.05f;
-    if (ctx.entity) {
-      auto *unit = ctx.entity->getComponent<Engine::Core::UnitComponent>();
-      if (unit && !unit->unitType.empty()) {
-        ringSize = Game::Units::TroopConfig::instance().getSelectionRingSize(
-            unit->unitType);
-        ringOffset += Game::Units::TroopConfig::instance()
-                          .getSelectionRingYOffset(unit->unitType);
-      }
-    }
-
-    QVector3D pos = ctx.model.column(3).toVector3D();
-    float groundY = pos.y();
-    bool haveTransformPosition = false;
-    auto &terrainService = Game::Map::TerrainService::instance();
-    if (terrainService.isInitialized()) {
-      groundY = terrainService.getTerrainHeight(pos.x(), pos.z());
-    } else if (ctx.entity) {
-      if (auto *transform =
-              ctx.entity->getComponent<Engine::Core::TransformComponent>()) {
-        groundY = transform->position.y;
-        pos.setX(transform->position.x);
-        pos.setZ(transform->position.z);
-        haveTransformPosition = true;
-      }
-    }
-
-    if (!haveTransformPosition && ctx.entity) {
-      if (auto *transform =
-              ctx.entity->getComponent<Engine::Core::TransformComponent>()) {
-        pos.setX(transform->position.x);
-        pos.setZ(transform->position.z);
-      }
-    }
-
-    pos.setY(groundY);
-
-    QMatrix4x4 ringM;
-    ringM.translate(pos.x(), pos.y() + ringOffset, pos.z());
-    ringM.scale(ringSize, 1.0f, ringSize);
-    if (ctx.selected)
-      out.selectionRing(ringM, 0.6f, 0.25f, QVector3D(0.2f, 0.4f, 1.0f));
-    else
-      out.selectionRing(ringM, 0.35f, 0.15f, QVector3D(0.90f, 0.90f, 0.25f));
-  }
-}
-
 void HumanoidRendererBase::render(const DrawContext &ctx,
 void HumanoidRendererBase::render(const DrawContext &ctx,
                                   ISubmitter &out) const {
                                   ISubmitter &out) const {
   FormationParams formation = resolveFormation(ctx);
   FormationParams formation = resolveFormation(ctx);
@@ -663,7 +611,6 @@ void HumanoidRendererBase::render(const DrawContext &ctx,
     addAttachments(instCtx, variant, pose, anim, out);
     addAttachments(instCtx, variant, pose, anim, out);
   }
   }
 
 
-  drawSelectionFX(ctx, out);
 }
 }
 
 
 } // namespace Render::GL
 } // namespace Render::GL

+ 0 - 1
render/humanoid_base.h

@@ -137,7 +137,6 @@ protected:
   void drawCommonBody(const DrawContext &ctx, const HumanoidVariant &v,
   void drawCommonBody(const DrawContext &ctx, const HumanoidVariant &v,
                       const HumanoidPose &pose, ISubmitter &out) const;
                       const HumanoidPose &pose, ISubmitter &out) const;
 
 
-  static void drawSelectionFX(const DrawContext &ctx, ISubmitter &out);
 };
 };
 
 
 } // namespace Render::GL
 } // namespace Render::GL

+ 51 - 3
render/scene_renderer.cpp

@@ -1,5 +1,7 @@
 #include "scene_renderer.h"
 #include "scene_renderer.h"
+#include "../game/map/terrain_service.h"
 #include "../game/map/visibility_service.h"
 #include "../game/map/visibility_service.h"
+#include "../game/units/troop_config.h"
 #include "entity/registry.h"
 #include "entity/registry.h"
 #include "game/core/component.h"
 #include "game/core/component.h"
 #include "game/core/world.h"
 #include "game/core/world.h"
@@ -233,6 +235,46 @@ void Renderer::selectionSmoke(const QMatrix4x4 &model, const QVector3D &color,
     m_activeQueue->submit(cmd);
     m_activeQueue->submit(cmd);
 }
 }
 
 
+void Renderer::enqueueSelectionRing(Engine::Core::Entity * /*entity*/,
+                                    Engine::Core::TransformComponent *transform,
+                                    Engine::Core::UnitComponent *unitComp,
+                                    bool selected, bool hovered) {
+  if ((!selected && !hovered) || !transform)
+    return;
+
+  float ringSize = 0.5f;
+  float ringOffset = 0.05f;
+  float groundOffset = 0.0f;
+
+  if (unitComp && !unitComp->unitType.empty()) {
+    auto &config = Game::Units::TroopConfig::instance();
+    ringSize = config.getSelectionRingSize(unitComp->unitType);
+    ringOffset += config.getSelectionRingYOffset(unitComp->unitType);
+    groundOffset = config.getSelectionRingGroundOffset(unitComp->unitType);
+  }
+
+  QVector3D pos(transform->position.x, transform->position.y,
+                transform->position.z);
+  auto &terrainService = Game::Map::TerrainService::instance();
+  float terrainY = transform->position.y;
+  if (terrainService.isInitialized()) {
+    terrainY = terrainService.getTerrainHeight(pos.x(), pos.z());
+  } else {
+    terrainY -= groundOffset * transform->scale.y;
+  }
+  pos.setY(terrainY);
+
+  QMatrix4x4 ringModel;
+  ringModel.translate(pos.x(), pos.y() + ringOffset, pos.z());
+  ringModel.scale(ringSize, 1.0f, ringSize);
+
+  if (selected) {
+    selectionRing(ringModel, 0.6f, 0.25f, QVector3D(0.2f, 0.4f, 1.0f));
+  } else if (hovered) {
+    selectionRing(ringModel, 0.35f, 0.15f, QVector3D(0.90f, 0.90f, 0.25f));
+  }
+}
+
 void Renderer::renderWorld(Engine::Core::World *world) {
 void Renderer::renderWorld(Engine::Core::World *world) {
   if (m_paused.load())
   if (m_paused.load())
     return;
     return;
@@ -294,6 +336,10 @@ void Renderer::renderWorld(Engine::Core::World *world) {
       }
       }
     }
     }
 
 
+    bool isSelected =
+        (m_selectedIds.find(entity->getId()) != m_selectedIds.end());
+    bool isHovered = (entity->getId() == m_hoveredEntityId);
+
     QMatrix4x4 modelMatrix;
     QMatrix4x4 modelMatrix;
     modelMatrix.translate(transform->position.x, transform->position.y,
     modelMatrix.translate(transform->position.x, transform->position.y,
                           transform->position.z);
                           transform->position.z);
@@ -309,12 +355,13 @@ void Renderer::renderWorld(Engine::Core::World *world) {
       if (fn) {
       if (fn) {
         DrawContext ctx{resources(), entity, world, modelMatrix};
         DrawContext ctx{resources(), entity, world, modelMatrix};
 
 
-        ctx.selected =
-            (m_selectedIds.find(entity->getId()) != m_selectedIds.end());
-        ctx.hovered = (entity->getId() == m_hoveredEntityId);
+        ctx.selected = isSelected;
+        ctx.hovered = isHovered;
         ctx.animationTime = m_accumulatedTime;
         ctx.animationTime = m_accumulatedTime;
         ctx.backend = m_backend.get();
         ctx.backend = m_backend.get();
         fn(ctx, *this);
         fn(ctx, *this);
+        enqueueSelectionRing(entity, transform, unitComp, isSelected,
+                             isHovered);
         drawnByRegistry = true;
         drawnByRegistry = true;
       }
       }
     }
     }
@@ -390,6 +437,7 @@ void Renderer::renderWorld(Engine::Core::World *world) {
         mesh(contactQuad, c2, col, white, outerAlpha);
         mesh(contactQuad, c2, col, white, outerAlpha);
       }
       }
     }
     }
+    enqueueSelectionRing(entity, transform, unitComp, isSelected, isHovered);
     mesh(meshToDraw, modelMatrix, color, res ? res->white() : nullptr, 1.0f);
     mesh(meshToDraw, modelMatrix, color, res ? res->white() : nullptr, 1.0f);
   }
   }
 }
 }

+ 7 - 0
render/scene_renderer.h

@@ -18,6 +18,8 @@
 namespace Engine::Core {
 namespace Engine::Core {
 class World;
 class World;
 class Entity;
 class Entity;
+class TransformComponent;
+class UnitComponent;
 } // namespace Engine::Core
 } // namespace Engine::Core
 
 
 namespace Render::GL {
 namespace Render::GL {
@@ -142,6 +144,11 @@ public:
                      const FireCampBatchParams &params);
                      const FireCampBatchParams &params);
 
 
 private:
 private:
+  void enqueueSelectionRing(Engine::Core::Entity *entity,
+                            Engine::Core::TransformComponent *transform,
+                            Engine::Core::UnitComponent *unitComp,
+                            bool selected, bool hovered);
+
   Camera *m_camera = nullptr;
   Camera *m_camera = nullptr;
   std::shared_ptr<Backend> m_backend;
   std::shared_ptr<Backend> m_backend;
   DrawQueue m_queues[2];
   DrawQueue m_queues[2];