mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Allow actors to override the entity's anchor type
Optionally let actor templates define their own anchor types. These override the default value defined in the template. Useful for actors without their own entity template. Reviewed-By: Itms Reviewed-On: https://gitea.wildfiregames.com/0ad/0ad/pulls/7542
This commit is contained in:
parent
0ce889ca6d
commit
eb2f59eeaa
8 changed files with 67 additions and 22 deletions
|
|
@ -214,6 +214,16 @@
|
|||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="anchor">
|
||||
<choice>
|
||||
<value>upright</value>
|
||||
<value>pitch</value>
|
||||
<value>roll</value>
|
||||
<value>pitch-roll</value>
|
||||
</choice>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="material">
|
||||
<ref name="qualitySettings"/>
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ CObjectBase::CObjectBase(CObjectManager& objectManager, CActorDef& actorDef, u8
|
|||
: m_ObjectManager(objectManager), m_ActorDef(actorDef)
|
||||
{
|
||||
m_QualityLevel = qualityLevel;
|
||||
m_Properties.m_AnchorType = "";
|
||||
m_Properties.m_CastShadows = false;
|
||||
m_Properties.m_FloatOnWater = false;
|
||||
|
||||
|
|
@ -82,6 +83,7 @@ bool CObjectBase::Load(const CXeromyces& XeroFile, const XMBElement& root)
|
|||
// Define all the elements used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
|
||||
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
|
||||
EL(anchor);
|
||||
EL(castshadow);
|
||||
EL(float);
|
||||
EL(group);
|
||||
|
|
@ -143,6 +145,8 @@ bool CObjectBase::Load(const CXeromyces& XeroFile, const XMBElement& root)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if (child_name == el_anchor)
|
||||
m_Properties.m_AnchorType = child.GetText();
|
||||
else if (child_name == el_castshadow)
|
||||
m_Properties.m_CastShadows = true;
|
||||
else if (child_name == el_float)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -159,6 +159,8 @@ public:
|
|||
|
||||
|
||||
struct {
|
||||
// whether and how to adapt the rotation to the terrrain slope below
|
||||
CStr m_AnchorType;
|
||||
// cast shadows from this object
|
||||
bool m_CastShadows;
|
||||
// float on top of water
|
||||
|
|
|
|||
|
|
@ -59,13 +59,16 @@ public:
|
|||
|
||||
// Template state:
|
||||
|
||||
enum
|
||||
enum class AnchorType
|
||||
{
|
||||
UNDEFINED = -1, // Used for m_ActorAnchorType only since it's optional.
|
||||
UPRIGHT = 0,
|
||||
PITCH = 1,
|
||||
PITCH_ROLL = 2,
|
||||
ROLL = 3,
|
||||
} m_AnchorType;
|
||||
};
|
||||
|
||||
AnchorType m_AnchorType;
|
||||
|
||||
bool m_Floating;
|
||||
entity_pos_t m_FloatDepth;
|
||||
|
|
@ -94,6 +97,7 @@ public:
|
|||
std::set<entity_id_t> m_Turrets;
|
||||
|
||||
// Not serialized:
|
||||
AnchorType m_ActorAnchorType;
|
||||
float m_InterpolatedRotX, m_InterpolatedRotY, m_InterpolatedRotZ;
|
||||
float m_LastInterpolatedRotX, m_LastInterpolatedRotZ;
|
||||
bool m_ActorFloating;
|
||||
|
|
@ -135,15 +139,8 @@ public:
|
|||
|
||||
void Init(const CParamNode& paramNode) override
|
||||
{
|
||||
const std::string& anchor = paramNode.GetChild("Anchor").ToString();
|
||||
if (anchor == "pitch")
|
||||
m_AnchorType = PITCH;
|
||||
else if (anchor == "pitch-roll")
|
||||
m_AnchorType = PITCH_ROLL;
|
||||
else if (anchor == "roll")
|
||||
m_AnchorType = ROLL;
|
||||
else
|
||||
m_AnchorType = UPRIGHT;
|
||||
m_AnchorType = ParseAnchorString(paramNode.GetChild("Anchor").ToString());
|
||||
m_ActorAnchorType = AnchorType::UNDEFINED;
|
||||
|
||||
m_InWorld = false;
|
||||
|
||||
|
|
@ -199,19 +196,19 @@ public:
|
|||
const char* anchor = "???";
|
||||
switch (m_AnchorType)
|
||||
{
|
||||
case PITCH:
|
||||
case AnchorType::PITCH:
|
||||
anchor = "pitch";
|
||||
break;
|
||||
|
||||
case PITCH_ROLL:
|
||||
case AnchorType::PITCH_ROLL:
|
||||
anchor = "pitch-roll";
|
||||
break;
|
||||
|
||||
case ROLL:
|
||||
case AnchorType::ROLL:
|
||||
anchor = "roll";
|
||||
break;
|
||||
|
||||
case UPRIGHT: // upright is the default
|
||||
case AnchorType::UPRIGHT: // upright is the default
|
||||
default:
|
||||
anchor = "upright";
|
||||
break;
|
||||
|
|
@ -493,6 +490,11 @@ public:
|
|||
AdvertiseInterpolatedPositionChanges();
|
||||
}
|
||||
|
||||
void SetActorAnchor(const CStr& anchor) override
|
||||
{
|
||||
m_ActorAnchorType = ParseAnchorString(anchor);
|
||||
}
|
||||
|
||||
void SetConstructionProgress(fixed progress) override
|
||||
{
|
||||
m_ConstructionProgress = progress;
|
||||
|
|
@ -854,6 +856,17 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
AnchorType ParseAnchorString(const CStr& anchor)
|
||||
{
|
||||
if (anchor == "pitch")
|
||||
return AnchorType::PITCH;
|
||||
if (anchor == "roll")
|
||||
return AnchorType::ROLL;
|
||||
if (anchor == "pitch-roll")
|
||||
return AnchorType::PITCH_ROLL;
|
||||
return AnchorType::UPRIGHT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called whenever m_RotY or m_InterpolatedRotY change,
|
||||
* to determine whether we need to call Interpolate to make the unit rotate.
|
||||
|
|
@ -935,7 +948,8 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_AnchorType == UPRIGHT || !m_RotZ.IsZero() || !m_RotX.IsZero())
|
||||
AnchorType anchor = m_ActorAnchorType == AnchorType::UNDEFINED ? m_AnchorType : m_ActorAnchorType;
|
||||
if (anchor == AnchorType::UPRIGHT || !m_RotZ.IsZero() || !m_RotX.IsZero())
|
||||
{
|
||||
// set the visual rotations to the ones fixed by the interface
|
||||
m_InterpolatedRotX = m_RotX.ToFloat();
|
||||
|
|
@ -961,10 +975,10 @@ private:
|
|||
normal.Z = projected.Y;
|
||||
|
||||
// project and calculate the angles
|
||||
if (m_AnchorType == PITCH || m_AnchorType == PITCH_ROLL)
|
||||
if (anchor == AnchorType::PITCH || anchor == AnchorType::PITCH_ROLL)
|
||||
m_InterpolatedRotX = -atan2(normal.Z, normal.Y);
|
||||
|
||||
if (m_AnchorType == ROLL || m_AnchorType == PITCH_ROLL)
|
||||
if (anchor == AnchorType::ROLL || anchor == AnchorType::PITCH_ROLL)
|
||||
m_InterpolatedRotZ = atan2(normal.X, normal.Y);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ public:
|
|||
if (!m_Unit || !m_Unit->GetAnimation() || !m_Unit->GetID())
|
||||
return;
|
||||
|
||||
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
|
||||
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
|
||||
}
|
||||
|
||||
void SelectMovementAnimation(const std::string& name, fixed speed) override
|
||||
|
|
@ -638,10 +638,15 @@ void CCmpVisualActor::InitModel()
|
|||
model.ToCModelDecal()->RemoveShadowsReceive();
|
||||
}
|
||||
|
||||
CStr anchor = m_Unit->GetObject().m_Base->m_Properties.m_AnchorType;
|
||||
bool floating = m_Unit->GetObject().m_Base->m_Properties.m_FloatOnWater;
|
||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
|
||||
if (cmpPosition)
|
||||
{
|
||||
if (!anchor.empty())
|
||||
cmpPosition->SetActorAnchor(anchor);
|
||||
cmpPosition->SetActorFloating(floating);
|
||||
}
|
||||
|
||||
if (!m_ModelTag.valid())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include "simulation2/helpers/Position.h"
|
||||
#include "maths/FixedVector3D.h"
|
||||
#include "maths/FixedVector2D.h"
|
||||
#include "ps/CStr.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
@ -158,6 +159,13 @@ public:
|
|||
*/
|
||||
virtual void SetActorFloating(bool flag) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Set the entity's anchor type, in a non-network-synchronised visual-only way.
|
||||
* (This is to support the 'anchor' flag in actor XMLs.)
|
||||
*/
|
||||
virtual void SetActorAnchor(const CStr& anchor) = 0;
|
||||
|
||||
/**
|
||||
* Set construction progress of the model, this affects the rendered position of the model.
|
||||
* 0.0 will be fully underground, 1.0 will be fully visible, 0.5 will be half underground.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -60,6 +60,7 @@ public:
|
|||
bool CanFloat() const override { return false; }
|
||||
void SetFloating(bool UNUSED(flag)) override { }
|
||||
void SetActorFloating(bool UNUSED(flag)) override { }
|
||||
void SetActorAnchor(const CStr& UNUSED(anchor)) override { }
|
||||
void SetConstructionProgress(fixed UNUSED(progress)) override { }
|
||||
CFixedVector3D GetPosition() const override { return m_Pos; }
|
||||
CFixedVector2D GetPosition2D() const override { return CFixedVector2D(m_Pos.X, m_Pos.Z); }
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ public:
|
|||
bool CanFloat() const override { return false; }
|
||||
void SetFloating(bool) override {}
|
||||
void SetActorFloating(bool) override {}
|
||||
void SetActorAnchor(const CStr&) override {}
|
||||
void SetConstructionProgress(fixed) override {}
|
||||
CFixedVector3D GetPosition() const override { return m_Pos; }
|
||||
CFixedVector2D GetPosition2D() const override { return CFixedVector2D(m_Pos.X, m_Pos.Z); }
|
||||
|
|
|
|||
Loading…
Reference in a new issue