Files
FlaxEngine/Source/Engine/Networking/Components/NetworkTransform.cpp
2022-10-31 16:31:06 +01:00

170 lines
5.4 KiB
C++

// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "NetworkTransform.h"
#include "Engine/Core/Math/Transform.h"
#include "Engine/Level/Actor.h"
#include "Engine/Networking/NetworkReplicator.h"
#include "Engine/Networking/NetworkStream.h"
PACK_STRUCT(struct Data
{
uint8 LocalSpace : 1;
NetworkTransform::SyncModes SyncMode : 9;
});
static_assert((int32)NetworkTransform::SyncModes::All + 1 == 512, "Invalid SyncModes bit count for Data.");
NetworkTransform::NetworkTransform(const SpawnParams& params)
: Script(params)
{
}
void NetworkTransform::OnEnable()
{
// Register for replication
NetworkReplicator::AddObject(this);
}
void NetworkTransform::OnDisable()
{
// Unregister from replication
NetworkReplicator::RemoveObject(this);
}
void NetworkTransform::Serialize(NetworkStream* stream)
{
// Get transform
Transform transform;
if (const auto* parent = GetParent())
transform = LocalSpace ? parent->GetLocalTransform() : parent->GetTransform();
else
transform = Transform::Identity;
// Encode data
Data data;
data.LocalSpace = LocalSpace;
data.SyncMode = SyncMode;
stream->Write(data);
if ((data.SyncMode & SyncModes::All) == (int)SyncModes::All)
{
stream->Write(transform);
}
else
{
if ((data.SyncMode & SyncModes::Position) == (int)SyncModes::Position)
{
stream->Write(transform.Translation);
}
else if (data.SyncMode & SyncModes::Position)
{
if (data.SyncMode & SyncModes::PositionX)
stream->Write(transform.Translation.X);
if (data.SyncMode & SyncModes::PositionY)
stream->Write(transform.Translation.X);
if (data.SyncMode & SyncModes::PositionZ)
stream->Write(transform.Translation.X);
}
if ((data.SyncMode & SyncModes::Scale) == (int)SyncModes::Scale)
{
stream->Write(transform.Scale);
}
else if (data.SyncMode & SyncModes::Scale)
{
if (data.SyncMode & SyncModes::ScaleX)
stream->Write(transform.Scale.X);
if (data.SyncMode & SyncModes::ScaleY)
stream->Write(transform.Scale.X);
if (data.SyncMode & SyncModes::ScaleZ)
stream->Write(transform.Scale.X);
}
if ((data.SyncMode & SyncModes::Rotation) == (int)SyncModes::Rotation)
{
const Float3 rotation = transform.Orientation.GetEuler();
stream->Write(rotation);
}
else if (data.SyncMode & SyncModes::Rotation)
{
const Float3 rotation = transform.Orientation.GetEuler();
if (data.SyncMode & SyncModes::RotationX)
stream->Write(rotation.X);
if (data.SyncMode & SyncModes::RotationY)
stream->Write(rotation.Y);
if (data.SyncMode & SyncModes::RotationZ)
stream->Write(rotation.Z);
}
}
}
void NetworkTransform::Deserialize(NetworkStream* stream)
{
// Get transform
Transform transform;
if (const auto* parent = GetParent())
transform = LocalSpace ? parent->GetLocalTransform() : parent->GetTransform();
else
transform = Transform::Identity;
// Decode data
Data data;
stream->Read(data);
if ((data.SyncMode & SyncModes::All) == (int)SyncModes::All)
{
stream->Read(transform);
}
else
{
if ((data.SyncMode & SyncModes::Position) == (int)SyncModes::Position)
{
stream->Read(transform.Translation);
}
else if (data.SyncMode & SyncModes::Position)
{
if (data.SyncMode & SyncModes::PositionX)
stream->Read(transform.Translation.X);
if (data.SyncMode & SyncModes::PositionY)
stream->Read(transform.Translation.X);
if (data.SyncMode & SyncModes::PositionZ)
stream->Read(transform.Translation.X);
}
if ((data.SyncMode & SyncModes::Scale) == (int)SyncModes::Scale)
{
stream->Read(transform.Scale);
}
else if (data.SyncMode & SyncModes::Scale)
{
if (data.SyncMode & SyncModes::ScaleX)
stream->Read(transform.Scale.X);
if (data.SyncMode & SyncModes::ScaleY)
stream->Read(transform.Scale.X);
if (data.SyncMode & SyncModes::ScaleZ)
stream->Read(transform.Scale.X);
}
if ((data.SyncMode & SyncModes::Rotation) == (int)SyncModes::Rotation)
{
Float3 rotation;
stream->Read(rotation);
transform.Orientation = Quaternion::Euler(rotation);
}
else if (data.SyncMode & SyncModes::Rotation)
{
Float3 rotation = transform.Orientation.GetEuler();
if (data.SyncMode & SyncModes::RotationX)
stream->Read(rotation.X);
if (data.SyncMode & SyncModes::RotationY)
stream->Read(rotation.Y);
if (data.SyncMode & SyncModes::RotationZ)
stream->Read(rotation.Z);
transform.Orientation = Quaternion::Euler(rotation);
}
}
// Set transform
if (auto* parent = GetParent())
{
if (data.LocalSpace)
parent->SetLocalTransform(transform);
else
parent->SetTransform(transform);
}
}