1 /* Copyright (C) 2016 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
22 #include "ObjectBase.h"
23 #include "ObjectEntry.h"
24 #include "ObjectManager.h"
25 #include "SkeletonAnim.h"
26 #include "SkeletonAnimDef.h"
27 #include "UnitAnimation.h"
29 CUnit::CUnit(CObjectEntry
* object
, CObjectManager
& objectManager
,
30 const std::set
<CStr
>& actorSelections
, uint32_t seed
)
31 : m_Object(object
), m_Model(object
->m_Model
->Clone()),
32 m_ID(INVALID_ENTITY
), m_ActorSelections(actorSelections
),
33 m_ObjectManager(objectManager
), m_Seed(seed
)
35 if (m_Model
->ToCModel())
36 m_Animation
= new CUnitAnimation(m_ID
, m_Model
->ToCModel(), m_Object
);
47 CUnit
* CUnit::Create(const CStrW
& actorName
, uint32_t seed
, const std::set
<CStr
>& selections
, CObjectManager
& objectManager
)
49 CObjectBase
* base
= objectManager
.FindObjectBase(actorName
);
54 std::set
<CStr
> actorSelections
= base
->CalculateRandomVariation(seed
, selections
);
56 std::vector
<std::set
<CStr
> > selectionsVec
;
57 selectionsVec
.push_back(actorSelections
);
59 CObjectEntry
* obj
= objectManager
.FindObjectVariation(base
, selectionsVec
);
64 return new CUnit(obj
, objectManager
, actorSelections
, seed
);
67 void CUnit::UpdateModel(float frameTime
)
70 m_Animation
->Update(frameTime
*1000.0f
);
73 void CUnit::SetID(entity_id_t id
)
77 m_Animation
->SetEntityID(id
);
80 void CUnit::SetEntitySelection(const CStr
& key
, const CStr
& selection
)
82 CStr selection_lc
= selection
.LowerCase();
84 if (m_EntitySelections
[key
] == selection_lc
)
86 m_EntitySelections
[key
] = selection_lc
;
91 void CUnit::SetEntitySelection(const std::map
<CStr
, CStr
>& selections
)
93 for (const std::pair
<CStr
, CStr
>& s
: selections
)
94 m_EntitySelections
[s
.first
] = s
.second
.LowerCase();
99 void CUnit::SetActorSelections(const std::set
<CStr
>& selections
)
101 m_ActorSelections
= selections
;
105 void CUnit::ReloadObject()
107 std::set
<CStr
> entitySelections
;
108 for (const std::pair
<CStr
, CStr
>& selection
: m_EntitySelections
)
109 entitySelections
.insert(selection
.second
);
110 std::vector
<std::set
<CStr
> > selections
;
111 selections
.push_back(entitySelections
);
112 selections
.push_back(m_ActorSelections
);
114 // randomly select any remain selections necessary to completely identify a variation (e.g., the new selection
115 // made might define some additional props that require a random variant choice). Also, FindObjectVariation
116 // expects the selectors passed to it to be complete.
117 // see http://trac.wildfiregames.com/ticket/979
119 // Use the entity ID as randomization seed (same as when the unit was first created)
120 std::set
<CStr
> remainingSelections
= m_Object
->m_Base
->CalculateRandomRemainingSelections(m_Seed
, selections
);
121 if (!remainingSelections
.empty())
122 selections
.push_back(remainingSelections
);
124 // If these selections give a different object, change this unit to use it
125 CObjectEntry
* newObject
= m_ObjectManager
.FindObjectVariation(m_Object
->m_Base
, selections
);
126 if (newObject
&& newObject
!= m_Object
)
128 // Clone the new object's base (non-instance) model
129 CModelAbstract
* newModel
= newObject
->m_Model
->Clone();
131 // Copy the old instance-specific settings from the old model to the new instance
132 newModel
->SetTransform(m_Model
->GetTransform());
133 newModel
->SetPlayerID(m_Model
->GetPlayerID());
134 if (newModel
->ToCModel() && m_Model
->ToCModel())
136 newModel
->ToCModel()->CopyAnimationFrom(m_Model
->ToCModel());
138 // Copy flags that belong to this model instance (not those defined by the actor XML)
139 int instanceFlags
= (MODELFLAG_SILHOUETTE_DISPLAY
|MODELFLAG_SILHOUETTE_OCCLUDER
|MODELFLAG_IGNORE_LOS
) & m_Model
->ToCModel()->GetFlags();
140 newModel
->ToCModel()->AddFlagsRec(instanceFlags
);
145 m_Object
= newObject
;
147 if (m_Model
->ToCModel())
150 m_Animation
->ReloadUnit(m_Model
->ToCModel(), m_Object
); // TODO: maybe this should try to preserve animation state?
152 m_Animation
= new CUnitAnimation(m_ID
, m_Model
->ToCModel(), m_Object
);
156 SAFE_DELETE(m_Animation
);