16#include "aeongames/AeonEngine.hpp"
18#include "aeongames/Node.hpp"
20#include "aeongames/Renderer.hpp"
21#include "aeongames/ProtoBufHelpers.hpp"
30#pragma warning( push )
31#pragma warning( disable : PROTOBUF_WARNINGS )
33#include <google/protobuf/text_format.h>
39#include "aeongames/Resource.hpp"
54 for (
auto & mRootNode : mNodes )
56 Remove ( mRootNode.get() );
62 Load (
crc32i ( aFilename.c_str(), aFilename.size() ) );
70 Load ( buffer.data(), buffer.size() );
79 Deserialize ( {
reinterpret_cast<const char*
> ( aBuffer ), aBufferSize} );
99 SetCamera (
Find ( [aNodeId] (
const Node & aNode ) ->
bool {
return aNode.
GetId() == aNodeId; } ) );
114 mFieldOfView = aFieldOfView;
142 mViewMatrix = aMatrix;
152 return mNodes.size();
157 return mNodes.at ( aIndex ).get();
162 auto index = std::find_if ( mNodes.begin(), mNodes.end(),
163 [aNode] (
const std::unique_ptr<Node>& node )
165 return node.get() == aNode;
167 if ( index != mNodes.end() )
169 return index - mNodes.begin();
171 throw std::runtime_error (
"Node is not a child of this object." );
176 return * ( mNodes[index] );
181 return const_cast<Node&
> (
static_cast<const Scene&
> ( *this ) [index] );
194 for (
auto & mRootNode : mNodes )
196 mRootNode->LoopTraverseDFSPreOrder ( [aMessageType, aMessageData] ( Node & node )
198 if ( node.mFlags[Node::Enabled] )
208 for (
auto & mRootNode : mNodes )
210 mRootNode->LoopTraverseDFSPreOrder ( aAction );
215 const std::function<
void ( Node& ) >& aPreamble,
216 const std::function<
void ( Node& ) >& aPostamble )
218 for (
auto & mRootNode : mNodes )
220 mRootNode->LoopTraverseDFSPreOrder ( aPreamble, aPostamble );
226 for (
const auto& mRootNode : mNodes )
228 static_cast<const Node*
> ( mRootNode.get() )->LoopTraverseDFSPreOrder ( aAction );
234 for (
auto & mRootNode : mNodes )
236 mRootNode->LoopTraverseDFSPostOrder ( aAction );
242 for (
const auto& mRootNode : mNodes )
244 static_cast<const Node*
> ( mRootNode.get() )->LoopTraverseDFSPostOrder ( aAction );
248 Node*
Scene::Find (
const std::function<
bool (
const Node& ) >& aUnaryPredicate )
const
250 for (
const auto& mRootNode : mNodes )
252 if ( Node * node =
static_cast<Node *
> ( mRootNode.get() )->Find ( aUnaryPredicate ) )
262 for (
auto & mRootNode : mNodes )
264 mRootNode->RecursiveTraverseDFSPreOrder ( aAction );
270 for (
auto & mRootNode : mNodes )
272 mRootNode->RecursiveTraverseDFSPostOrder ( aAction );
279 if ( aNode ==
nullptr )
283 std::visit ( [&aNode] (
auto&& parent )
285 if ( parent !=
nullptr )
287 if ( !parent->Remove ( aNode.get() ) )
289 std::cout <<
LogLevel::Warning <<
"Parent for node " << aNode->GetName() <<
" did not have it as a child.";
294 aNode->mParent =
this;
295 std::vector<std::unique_ptr<Node >>::iterator inserted_node;
296 if ( aIndex < mNodes.size() )
298 inserted_node = mNodes.insert ( mNodes.begin() + aIndex, std::move ( aNode ) );
302 inserted_node = mNodes.insert ( mNodes.end(), std::move ( aNode ) );
306 ( *inserted_node )->SetGlobalTransform ( ( *inserted_node )->mGlobalTransform );
307 return ( *inserted_node ).get();
313 if ( aNode ==
nullptr )
317 std::visit ( [&aNode] (
auto&& parent )
319 if ( parent !=
nullptr )
321 if ( !parent->Remove ( aNode.get() ) )
323 std::cout <<
LogLevel::Warning <<
"Parent for node " << aNode->GetName() <<
" did not have it as a child.";
328 aNode->mParent =
this;
329 mNodes.emplace_back ( std::move ( aNode ) );
332 mNodes.back()->SetGlobalTransform ( mNodes.back()->mGlobalTransform );
333 return mNodes.back().get();
338 if ( aNode ==
nullptr )
343 auto it = std::find_if ( mNodes.begin(), mNodes.end(),
344 [aNode] (
const std::unique_ptr<Node>& node )
346 return aNode == node.get();
348 if ( it != mNodes.end() )
351 aNode->mParent =
static_cast<Node*
> ( nullptr );
353 std::unique_ptr<Node> removed_node{std::move ( * ( it ) ) };
362 if ( aIndex >= mNodes.size() )
366 mNodes[aIndex]->mParent =
static_cast<Node*
> ( nullptr );
367 mNodes[aIndex]->SetLocalTransform ( mNodes[aIndex]->mGlobalTransform );
368 auto it = mNodes.begin() + aIndex;
369 std::unique_ptr<Node> removed_node{std::move ( * ( it ) ) };
376 static SceneMsg scene_buffer;
377 *scene_buffer.mutable_name() = mName;
380 *scene_buffer.mutable_camera()->mutable_node() = mCamera->GetName();
381 scene_buffer.mutable_camera()->set_field_of_view ( mFieldOfView );
382 scene_buffer.mutable_camera()->set_near_plane ( mNear );
383 scene_buffer.mutable_camera()->set_far_plane ( mFar );
385 std::unordered_map<const Node*, NodeMsg*> node_map;
387 [&node_map] (
const Node & node )
389 NodeMsg* node_buffer;
391 if ( parent != node_map.end() )
393 node_buffer = ( *parent ).second->add_node();
397 node_buffer = scene_buffer.add_node();
400 node_map.emplace ( std::make_pair ( &node, node_buffer ) );
402 std::stringstream serialization;
405 serialization <<
"AEONSCE" <<
'\0';
406 if ( !scene_buffer.SerializeToOstream ( &serialization ) )
408 std::cerr <<
LogLevel::Error <<
"Failed to serialize scene to binary format.";
409 throw std::runtime_error (
"Failed to serialize scene to binary format." );
415 serialization <<
"AEONSCE\n";
416 google::protobuf::TextFormat::Printer printer;
417 if ( !printer.PrintToString ( scene_buffer, &text ) )
419 std::cerr <<
LogLevel::Error <<
"Failed to serialize scene to text format.";
420 throw std::runtime_error (
"Failed to serialize scene to text format." );
422 serialization << text;
424 scene_buffer.Clear();
425 return serialization.str();
429 static std::mutex m{};
430 static SceneMsg scene_buffer{};
431 std::lock_guard<std::mutex> hold ( m );
432 LoadProtoBufObject ( scene_buffer, aSerializedScene.data(), aSerializedScene.size(),
"AEONSCE"_mgk );
433 mName = scene_buffer.name();
435 std::unordered_map<const NodeMsg*, std::tuple<const NodeMsg*, int, Node* >> node_map;
436 for (
auto &i : scene_buffer.node() )
438 const NodeMsg* node = &i;
439 node_map[node] = std::tuple<const NodeMsg*, int, Node*> {
nullptr, 0,
Add ( std::make_unique<Node>() ) };
440 std::get<2> ( node_map[node] )->Deserialize ( *node );
443 if ( std::get<1> ( node_map[node] ) < node->node().size() )
445 const NodeMsg* prev = node;
446 node = &node->node ( std::get<1> ( node_map[node] ) );
447 node_map[node] = std::tuple<const NodeMsg*, int, Node*> {prev, 0, std::get<2> ( node_map[prev] )->Add ( std::make_unique<Node>() ) };
448 std::get<2> ( node_map[node] )->Deserialize ( *node );
449 ++std::get<1> ( node_map[prev] );
453 std::get<1> ( node_map[node] ) = 0;
454 node = std::get<0> ( node_map[node] );
458 SetCamera ( scene_buffer.camera().node() );
459 mFieldOfView = scene_buffer.camera().field_of_view();
460 mFieldOfView = ( mFieldOfView == 0.0f ) ? 60.0f : mFieldOfView;
461 mNear = scene_buffer.camera().near_plane();
462 mNear = ( mNear == 0.0f ) ? 1.0f : mNear;
463 mFar = scene_buffer.camera().far_plane();
464 mFar = ( mFar == 0.0f ) ? 1600.0f : mFar;
467 mViewMatrix = mCamera->GetGlobalTransform().GetInvertedMatrix();
469 scene_buffer.Clear();
Defines log severity levels and stream output for the AeonGames engine.
#define LoopTraverseDFSPreOrder(...)
Macro generating LoopTraverseDFSPreOrder implementations for const and non-const variants.
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Header for the Scene class.
4 by 4 matrix in colum mayor order.
DLL void SetLocalTransform(const Transform &aTransform)
Set the local transform relative to the parent.
DLL uint32_t GetId() const
Get the unique identifier of this node.
DLL void Serialize(NodeMsg &aNodeMsg) const
Serialize this node's state into a protobuf message.
DLL void ProcessMessage(uint32_t aMessageType, const void *aMessageData)
Deliver a message to this node and its components.
DLL NodeParent GetParent() const
Get this node's parent.
DLL void Update(const double delta)
Update this node and its children.
DLL void BroadcastMessage(uint32_t aMessageType, const void *aMessageData)
Broadcast a message to all nodes in the scene.
DLL void Deserialize(const std::string &aSerializedScene)
Deserialize a scene from a string.
DLL const Node * GetCamera() const
Get the current camera node.
DLL void RecursiveTraverseDFSPostOrder(const std::function< void(Node &) > &aAction)
Recursive depth-first post-order traversal of all nodes in the scene.
DLL float GetNear() const
Get the near clipping plane distance.
DLL void SetNear(float aNear)
Set the near clipping plane distance.
DLL std::unique_ptr< Node > RemoveByIndex(size_t aIndex)
Remove a top-level node by index.
DLL void RecursiveTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Recursive depth-first pre-order traversal of all nodes in the scene.
DLL void LoopTraverseDFSPostOrder(const std::function< void(Node &) > &aAction)
Iterative depth-first post-order traversal of all nodes in the scene.
DLL void LoopTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Iterative depth-first pre-order traversal of all nodes in the scene.
DLL void SetFieldOfView(float aFieldOfView)
Set the vertical field of view.
DLL float GetFar() const
Get the far clipping plane distance.
DLL void SetCamera(Node *aNode)
Set rendering camera.
DLL void SetName(const char *aName)
Set the scene name.
DLL Node * Insert(size_t aIndex, std::unique_ptr< Node > aNode)
Insert a top-level node at a specific index.
DLL void SetFar(float aFar)
Set the far clipping plane distance.
DLL const char *const GetName() const
Get the scene name.
DLL void Load(uint32_t aId)
Load a scene from a resource identified by id.
DLL float GetFieldOfView() const
Get the vertical field of view.
DLL Scene()
Construct an empty scene.
DLL size_t GetChildIndex(const Node *aNode) const
Get the index of a top-level child node.
DLL std::string Serialize(bool aAsBinary=true) const
Serialize the scene to a string.
DLL const Node & operator[](const std::size_t index) const
Access a top-level child node by index (const).
DLL size_t GetChildrenCount() const
Get the number of top-level child nodes.
DLL Node * Add(std::unique_ptr< Node > aNode)
Add a top-level node to the scene.
DLL const Matrix4x4 & GetViewMatrix() const
Get the current view matrix.
DLL void Update(const double delta)
Update all nodes in the scene.
DLL void SetViewMatrix(const Matrix4x4 &aMatrix)
Set the view matrix directly.
DLL Node * Find(const std::function< bool(const Node &) > &aUnaryPredicate) const
Find the first node matching a predicate via depth-first search.
DLL Node * GetChild(size_t aIndex) const
Get a top-level child node by index.
DLL std::unique_ptr< Node > Remove(Node *aNode)
Remove a top-level node by pointer.
<- This is here just for the literals
DLL size_t GetResourceSize(uint32_t crc)
Node * GetNodePtr(const NodeParent &aNodeParent)
Extract the Node pointer from a NodeParent variant.
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
DLL void LoadResource(uint32_t crc, void *buffer, size_t buffer_size)
@ Warning
Potential issues that may need attention.
void LoadProtoBufObject(T &t, const void *aData, size_t aSize, uint64_t aMagick)
Loads a Protocol Buffer Object from a meory buffer into the provided reference.