Leviathan  0.8.0.0
Leviathan game engine
Components.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "Components.h"
3 
4 #include "FileSystem.h"
5 #include "GameWorld.h"
6 #include "Generated/ComponentStates.h"
7 #include "Handlers/IDFactory.h"
10 #include "Physics/PhysicalWorld.h"
11 #include "Utility/Convert.h"
12 
13 #include "Engine.h"
14 #include "Rendering/Graphics.h"
15 
16 #include "bsfCore/Components/BsCAnimation.h"
17 #include "bsfCore/Components/BsCRenderable.h"
18 // #include "bsfCore/Importer/BsImporter.h"
19 #include "bsfCore/Renderer/BsRenderable.h"
20 #include "bsfCore/Scene/BsSceneObject.h"
21 
22 #include <limits>
23 using namespace Leviathan;
24 // ------------------------------------ //
25 // Position
26 DLLEXPORT void Position::ApplyState(const PositionState& state)
27 {
28  Members._Orientation = state._Orientation;
29  Members._Position = state._Position;
30  Marked = true;
31 }
32 
33 // ------------------ RenderNode ------------------ //
35 {
36  Marked = false;
37 
38  // Skip if no graphics
40  return;
41 
42  // TODO: allow for static render nodes
43  Node = bs::SceneObject::create("");
44 }
45 
47 {
48  if(Node)
49  Node->destroy();
50  Node = nullptr;
51 }
52 // ------------------------------------ //
53 DLLEXPORT RenderNode::RenderNode(const Test::TestComponentCreation& test) : Component(TYPE)
54 {
55  Marked = false;
56  Node = nullptr;
57 }
58 
59 // // ------------------------------------ //
60 // // Plane
61 // DLLEXPORT Plane::Plane(bs::Scene* scene, Ogre::SceneNode* parent, const std::string&
62 // material,
63 // const Ogre::Plane& plane, const Float2& size,
64 // const Ogre::Vector3& uvupvector /*= Ogre::Vector3::UNIT_Y*/) :
65 // Component(TYPE),
66 // GeneratedMeshName("Plane_Component_Mesh_" + std::to_string(IDFactory::GetID())),
67 // Material(material), PlaneDefinition(plane), Size(size), UpVector(uvupvector)
68 // {
69 // const auto mesh = Ogre::v1::MeshManager::getSingleton().createPlane(
70 // GeneratedMeshName + "_v1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
71 // plane, size.X, size.Y, 1, 1,
72 // // Normals
73 // true, 1, 1.0f, 1.0f, uvupvector, Ogre::v1::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
74 // Ogre::v1::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false, false);
75 
76 // const auto mesh2 = Ogre::MeshManager::getSingleton().createManual(
77 // GeneratedMeshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
78 
79 // // Fourth true is qtangent encoding which is not needed if we don't do normal mapping
80 // mesh2->importV1(mesh.get(), true, true, true);
81 
82 // Ogre::v1::MeshManager::getSingleton().remove(mesh);
83 
84 // GraphicalObject = scene->createItem(mesh2);
85 // parent->attachObject(GraphicalObject);
86 
87 // // This DOESN'T seem to throw if material is invalid
88 // GraphicalObject->setDatablockOrMaterialName(material);
89 
90 // GraphicalObject->setRenderQueueGroup(DEFAULT_RENDER_QUEUE);
91 // }
92 
93 // DLLEXPORT void Plane::Release(bs::Scene* scene)
94 // {
95 // scene->destroyItem(GraphicalObject);
96 
97 // Ogre::MeshManager::getSingleton().remove(GeneratedMeshName);
98 // }
99 // ------------------ Physics ------------------ //
101 {
102  if(Body) {
103  LOG_FATAL("Physics: Release not called before destructor!");
104  }
105 }
106 
108 {
109  if(Body) {
110  Body->SetOwningEntity(NULL_OBJECT);
111  world->DestroyBody(Body.get());
112  }
113 
114  Body.reset();
115 }
116 // ------------------------------------ //
118 {
119  if(Body)
120  Body->SetPosition(target.Members._Position, target.Members._Orientation);
121 }
122 // ------------------------------------ //
124  const PhysicsShape::pointer& shape, float mass, int physicsmaterialid /*= -1*/)
125 {
126  if(!world || !shape)
127  return nullptr;
128 
129  // Destroy old if there is one //
130  if(Body)
131  world->DestroyBody(Body.get());
132 
133  Body = world->CreateBodyFromCollision(shape, mass, &_Position, physicsmaterialid);
134 
135  if(!Body)
136  return nullptr;
137 
138  Body->SetOwningEntity(ThisEntity);
139 
140  return Body;
141 }
142 
143 DLLEXPORT bool Physics::ChangeShape(PhysicalWorld* world, const PhysicsShape::pointer& shape)
144 {
145  if(!world || !shape)
146  return false;
147 
148  return world->ChangeBodyShape(Body, shape);
149 }
150 
151 // ------------------ Received ------------------ //
152 // DLLEXPORT void Received::GetServerSentStates(
153 // StoredState const** first, StoredState const** second, int tick, float& progress) const
154 // {
155 // // Used to find the first tick before or on tick //
156 // int firstinpast = std::numeric_limits<int>::max();
157 // int secondfound = 0;
158 
159 // for(auto& obj : ClientStateBuffer) {
160 
161 // if(tick - obj.Tick < firstinpast && tick - obj.Tick >= 0) {
162 
163 // // This is (potentially) the first state //
164 // firstinpast = tick - obj.Tick;
165 
166 // *first = &obj;
167 // }
168 
169 // // For this to be found the client should be around 50-100 milliseconds in the past
170 // if(obj.Tick > tick && (secondfound == 0 || obj.Tick - tick < secondfound)) {
171 
172 // // The second state //
173 // *second = &obj;
174 
175 // secondfound = obj.Tick - tick;
176 // continue;
177 // }
178 // }
179 
180 // if(firstinpast == std::numeric_limits<int>::max() || secondfound == 0) {
181 
182 // throw InvalidState("No stored server states around tick");
183 // }
184 
185 // // If the range is not 1, meaning firstinpast != 0 || secondfound > 1 we need to adjust
186 // // progress
187 // int range = firstinpast + secondfound;
188 
189 // if(range == 1)
190 // return;
191 
192 // progress = ((tick + progress) - (*first)->Tick) / range;
193 // }
194 // // ------------------ Trail ------------------ //
195 // DLLEXPORT bool Trail::SetTrailProperties(const Properties &variables, bool force /*=
196 // false*/){
197 
198 //
199 
200 // if(!TrailEntity || !_RenderNode)
201 // return false;
202 
203 // // Set if we unconnected the node and we should reconnect it afterwards //
204 // bool ConnectAgain = false;
205 
206 // // Determine if we need to unconnect the node //
207 // if(force || variables.MaxChainElements != CurrentSettings.MaxChainElements){
208 
209 // // This to avoid Ogre bug //
210 // TrailEntity->removeNode(_RenderNode->Node);
211 // ConnectAgain = true;
212 
213 // // Apply the properties //
214 // TrailEntity->setUseVertexColours(true);
215 // TrailEntity->setRenderingDistance(variables.MaxDistance);
216 // TrailEntity->setMaxChainElements(variables.MaxChainElements);
217 // TrailEntity->setCastShadows(variables.CastShadows);
218 // TrailEntity->setTrailLength(variables.TrailLenght);
219 // }
220 
221 // // Update cached settings //
222 // CurrentSettings = variables;
223 
224 // // Apply per element properties //
225 // for(size_t i = 0; i < variables.Elements.size(); i++){
226 // // Apply settings //
227 // const ElementProperties& tmp = variables.Elements[i];
228 
229 // TrailEntity->setInitialColour(i, tmp.InitialColour);
230 // TrailEntity->setInitialWidth(i, tmp.InitialSize);
231 // TrailEntity->setColourChange(i, tmp.ColourChange);
232 // TrailEntity->setWidthChange(i, tmp.SizeChange);
233 // }
234 
235 // // More bug avoiding //
236 // if(ConnectAgain)
237 // TrailEntity->addNode(_RenderNode->Node);
238 
239 // return true;
240 // }
241 // // ------------------------------------ //
242 // DLLEXPORT void Trail::Release(bs::Scene* scene){
243 
244 // if(TrailEntity){
245 
246 // scene->destroyRibbonTrail(TrailEntity);
247 // TrailEntity = nullptr;
248 // }
249 // }
250 // ------------------ Sendable ------------------ //
252 {
253  if(SentPackets.empty())
254  return;
255 
256  // Looped in reverse to hopefully remove only last elements //
257  for(int i = static_cast<int>(SentPackets.size() - 1); i >= 0;) {
258 
259  auto& tuple = SentPackets[i];
260 
261  if(std::get<2>(tuple)->IsFinalized()) {
262 
263  if(std::get<2>(tuple)->GetStatus()) {
264 
265  // Succeeded //
266  if(std::get<0>(tuple) > LastConfirmedTickNumber) {
267 
268  LastConfirmedTickNumber = std::get<0>(tuple);
269 
270  // This is always erased (a few lines later) so it's fine to swap
271  LastConfirmedData = std::move(std::get<1>(tuple));
272  }
273  }
274 
275  SentPackets.erase(SentPackets.begin() + i);
276 
277  if(SentPackets.empty())
278  break;
279 
280  } else {
281 
282  i--;
283  }
284  }
285 
286  if(SentPackets.capacity() > 10) {
287 
288  LOG_WARNING("Sendable::ActiveConnection: SentPackets has space for over 10 "
289  "sent packets");
290  SentPackets.shrink_to_fit();
291  }
292 }
293 // ------------------------------------ //
294 DLLEXPORT Model::Model(bs::Scene* scene, RenderNode& parent, const std::string& meshname,
295  const bs::HMaterial& material) :
296  Component(TYPE),
297  MeshName(meshname), Material(material)
298 {
299  Marked = false;
300 
301  // Skip if no graphics
302  if(!parent.Node)
303  return;
304 
305  GraphicalObject = parent.Node->addComponent<bs::CRenderable>();
306 
307  // GraphicalObject->setLayer(1 << *parent.Scene);
308  GraphicalObject->setLayer(1 << *scene);
309 
310  ApplyMeshName();
311 
312  GraphicalObject->setMaterial(Material);
313 }
314 
316 {
317  if(GraphicalObject)
318  GraphicalObject->destroy();
319 }
320 
322 {
323  if(MeshName.empty()) {
324  GraphicalObject->setMesh(nullptr);
325  return;
326  }
327 
328  // Find the mesh
329  auto mesh = Engine::Get()->GetGraphics()->LoadMeshByName(MeshName);
330 
331  GraphicalObject->setMesh(mesh);
332 }
333 
334 // // ------------------ ManualObject ------------------ //
335 // DLLEXPORT ManualObject::ManualObject(bs::Scene* scene) : Component(TYPE)
336 // {
337 // Object = scene->createManualObject();
338 // Object->setRenderQueueGroup(DEFAULT_RENDER_QUEUE);
339 // }
340 
341 // DLLEXPORT void ManualObject::Release(bs::Scene* scene)
342 // {
343 // if(Object) {
344 
345 // scene->destroyManualObject(Object);
346 // Object = nullptr;
347 // }
348 
349 // CreatedMesh.clear();
350 // }
351 
352 // ------------------------------------ //
353 // Animated
355 {
356  Animation = node.Node->addComponent<bs::CAnimation>();
357 }
358 
360 {
361  if(Animation)
362  Animation->destroy();
363  Animation = nullptr;
364 }
bs::HAnimation Animation
Created animation component for this entity.
Definition: Components.h:304
DLLEXPORT void CheckReceivedPackets()
Checks has any packet been successfully received and updates last confirmed.
Definition: Components.cpp:251
ObjectID ThisEntity
For passing to PhysicsBody::SetOwningEntity.
Definition: Components.h:488
DLLEXPORT bs::HMesh LoadMeshByName(const std::string &name)
Works the same as LoadShaderByName.
Definition: Graphics.cpp:597
bs::HRenderable GraphicalObject
The entity that has this model's mesh loaded.
Definition: Components.h:244
constexpr ObjectID NULL_OBJECT
Definition: EntityCommon.h:14
#define LOG_FATAL(x)
Definition: Define.h:92
DLLEXPORT bool ChangeBodyShape(const PhysicsBody::pointer &body, const PhysicsShape::pointer &shape)
Applies a changed shape to a body.
DLLEXPORT RenderNode(bs::Scene *scene)
Definition: Components.cpp:34
std::string MeshName
Definition: Components.h:247
DLLEXPORT PhysicsBody::pointer CreateBodyFromCollision(const PhysicsShape::pointer &shape, float mass, PhysicsPositionProvider *positionsynchronization, int physicsmaterialid=-1)
Constraints body to a 2d plane of movement specified by its normal.
DLLEXPORT void ApplyState(const PositionState &state)
Applies the state and marks this as changed. Doesn't check if the state is actually different.
Definition: Components.cpp:26
#define LOG_WARNING(x)
Definition: Define.h:89
std::vector< std::tuple< int, std::shared_ptr< EntityState >, std::shared_ptr< SentNetworkThing > > > SentPackets
Holds packets sent to this connection that haven't failed or been received yet.
Definition: Components.h:153
bs::HMaterial Material
Material set on the object.
Definition: Components.h:250
DLLEXPORT bool ChangeShape(PhysicalWorld *world, const PhysicsShape::pointer &shape)
Updates the shape. This can be the same pointer as before. BUT if the shape is modified this MUST be ...
Definition: Components.cpp:143
DLLEXPORT bool DestroyBody(PhysicsBody *body)
Destroys a physics body.
std::shared_ptr< EntityState > LastConfirmedData
Definition: Components.h:143
Entity has position and direction it is looking at.
Definition: Components.h:34
Entity has a scene node.
Definition: Components.h:79
DLLEXPORT void Release()
Definition: Components.cpp:315
DLLEXPORT ~Physics()
Definition: Components.cpp:100
DLLEXPORT Model(bs::Scene *scene, RenderNode &parent, const std::string &meshname, const bs::HMaterial &material)
Definition: Components.cpp:294
bs::HSceneObject Node
Definition: Components.h:91
Graphics * GetGraphics()
Definition: Engine.h:179
static constexpr auto TYPE
Definition: Components.h:164
DLLEXPORT void Release()
Definition: Components.cpp:359
DLLEXPORT PhysicsBody::pointer CreatePhysicsBody(PhysicalWorld *world, const PhysicsShape::pointer &shape, float mass, int physicsmaterialid=-1)
Use this to create a body for this component once Collision is set.
Definition: Components.cpp:123
bool IsInGraphicalMode()
DLLEXPORT void Release(PhysicalWorld *world)
Destroys the physical body.
Definition: Components.cpp:107
DLLEXPORT void JumpTo(Position &target)
Syncs this physics body to a changed position.
Definition: Components.cpp:117
DLLEXPORT Animated(RenderNode &node)
Definition: Components.cpp:354
#define DLLEXPORT
Definition: Include.h:84
Base class for all components.
Definition: Component.h:52
Position & _Position
Physics object requires a position.
Definition: Components.h:494
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
DLLEXPORT void Release(bs::Scene *worldsscene)
Gracefully releases while world is still valid.
Definition: Components.cpp:46
DLLEXPORT void ApplyMeshName()
Definition: Components.cpp:321
int32_t Scene
Definition: Define.h:68