Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions OloEngine/src/OloEngine/Animation/NoiseAnimationComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,30 @@ namespace OloEngine
OLO_PROPERTY()
u32 EndBoneIndex = 0; // chain tip bone (e.g. head or chest)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 1u)
u32 ChainLength = 1; // bones in the chain including the tip (>= 1)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1e4f)
f32 Frequency = 1.0f; // noise evolution speed — higher = faster wobble
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = -6.2832f, Max = 6.2832f)
glm::vec3 RotationAmplitude{ 0.08f, 0.08f, 0.08f }; // peak rotation offset per local axis (radians)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = -1e4f, Max = 1e4f)
glm::vec3 TranslationAmplitude{ 0.0f, 0.0f, 0.0f }; // peak translation offset per local axis (model units)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 1u, Max = 8u)
u32 Octaves = 2; // fractal octaves (clamped 1..8)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 1.0f, Max = 8.0f)
f32 Lacunarity = 2.0f; // frequency multiplier per octave (clamped 1..8)
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1.0f)
f32 Gain = 0.5f; // amplitude multiplier per octave (clamped 0..1)
OLO_PROPERTY()
u32 Seed = 0; // de-correlates entities/instances sharing a clip
OLO_PROPERTY()
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1.0f)
f32 Weight = 1.0f; // 0 = animated pose, 1 = full noise offset

// Trivially-copyable POD component: a single whole-struct bitwise compare
Expand Down
15 changes: 10 additions & 5 deletions OloEngine/src/OloEngine/Scene/ComponentReflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,28 @@
// [Min, Max] (both given), or applies a one-sided std::max/std::min (only
// one given). Mirrors the SanitizeFloat/std::clamp idiom every hand-written
// clamp-only component already used, so the generated block reproduces the
// same result for valid data. Only scalar Float/Int/UInt/SmallInt/
// SmallUInt/Enum fields support Clamp today (Vec*/vector-of-T clamping is a
// follow-up) — requesting it on any other type marks the whole component
// non-trivial (fail-safe) rather than silently dropping the annotation.
// same result for valid data. Scalar Float/Int/UInt/SmallInt/SmallUInt/Enum
// fields and glm::vec3 (clamped per-component) support Clamp today
// (Vec2/Vec4/vector-of-T clamping remain a follow-up) — requesting it on
// any other type marks the whole component non-trivial (fail-safe) rather
// than silently dropping the annotation.
// Note this is CLAMP-to-range, not REJECT-out-of-range: a component whose
// hand-written deserialize instead *rejects* an out-of-bounds value (keeps
// the constructor default rather than clamping to the bound) is a different
// semantic and must stay hand-written.
// Min — Clamp lower bound, e.g. Min = 0.0f. Emitted as a static_cast to the
// field's own type, so an int literal is fine for a float field.
// field's own type, so an int literal is fine for a float field. For a
// glm::vec3 field, broadcast to all three components via glm::vec3(Min).
// Max — Clamp upper bound, e.g. Max = 100.0f.
//
// Usage:
// struct SomeComponent
// {
// OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 100.0f)
// f32 m_Density = 0.5f; // deserialize: m_Density = std::clamp(v, 0.0f, 100.0f)
// OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1000.0f)
// glm::vec3 m_Extents{ 0.5f, 0.5f, 0.5f };
// // deserialize: m_Extents = glm::clamp(v, glm::vec3(0.0f), glm::vec3(1000.0f))
// };
//
// May co-exist with OLO_PROPERTY on the same field (e.g. a runtime field exposed to
Expand Down
14 changes: 10 additions & 4 deletions OloEngine/src/OloEngine/Scene/Components.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
return Tag;
}

// Authoring-only equality — `renaming` is a transient editor flag toggled

Check warning on line 101 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "=default" instead of the default implementation of this comparison function.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-K&open=AZ87vOa3p7dppQPiSw-K&pullRequest=580
// while the user is mid-rename. Including it would treat start/end of an
// inline edit as a real change and pollute the undo stack.
auto operator==(const TagComponent& other) const -> bool
Expand All @@ -110,22 +110,22 @@
struct PrefabComponent
{
UUID m_PrefabID{};
UUID m_PrefabEntityID{};

Check warning on line 113 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this "struct" to a "class" or remove its member functions.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-L&open=AZ87vOa3p7dppQPiSw-L&pullRequest=580

// Component-level override tracking for prefab instances.
// Components listed here have been intentionally modified on this instance
// and will not be updated when the source prefab changes.

Check warning on line 117 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-M&open=AZ87vOa3p7dppQPiSw-M&pullRequest=580
std::unordered_set<std::string> m_OverriddenComponents;

// Components added to this instance that do not exist in the source prefab.

Check warning on line 120 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-N&open=AZ87vOa3p7dppQPiSw-N&pullRequest=580
std::unordered_set<std::string> m_AddedComponents;

// Components removed from this instance that exist in the source prefab.

Check warning on line 123 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-O&open=AZ87vOa3p7dppQPiSw-O&pullRequest=580
std::unordered_set<std::string> m_RemovedComponents;

PrefabComponent() = default;
PrefabComponent(const PrefabComponent&) = default;
PrefabComponent(PrefabComponent&&) = default;

Check failure on line 128 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Customize this struct's destructor to participate in resource management.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-Q&open=AZ87vOa3p7dppQPiSw-Q&pullRequest=580

Check warning on line 128 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Don't mix public and private data members.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-P&open=AZ87vOa3p7dppQPiSw-P&pullRequest=580
PrefabComponent& operator=(const PrefabComponent&) = default;
PrefabComponent& operator=(PrefabComponent&&) = default;
PrefabComponent(UUID prefabID, UUID prefabEntityID)
Expand Down Expand Up @@ -156,21 +156,21 @@
return !m_OverriddenComponents.empty() || !m_AddedComponents.empty() || !m_RemovedComponents.empty();
}

inline void MarkComponentOverridden(const std::string& componentName)

Check warning on line 159 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-S&open=AZ87vOa3p7dppQPiSw-S&pullRequest=580

Check warning on line 159 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-R&open=AZ87vOa3p7dppQPiSw-R&pullRequest=580
{
m_OverriddenComponents.insert(componentName);

Check warning on line 161 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-T&open=AZ87vOa3p7dppQPiSw-T&pullRequest=580
}

inline void ClearComponentOverride(const std::string& componentName)
{

Check warning on line 165 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-V&open=AZ87vOa3p7dppQPiSw-V&pullRequest=580

Check warning on line 165 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-U&open=AZ87vOa3p7dppQPiSw-U&pullRequest=580
m_OverriddenComponents.erase(componentName);
m_AddedComponents.erase(componentName);

Check warning on line 167 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-W&open=AZ87vOa3p7dppQPiSw-W&pullRequest=580
m_RemovedComponents.erase(componentName);
}

inline void ClearAllOverrides()

Check warning on line 171 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-X&open=AZ87vOa3p7dppQPiSw-X&pullRequest=580

Check warning on line 171 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-Y&open=AZ87vOa3p7dppQPiSw-Y&pullRequest=580
{
m_OverriddenComponents.clear();

Check warning on line 173 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-Z&open=AZ87vOa3p7dppQPiSw-Z&pullRequest=580
m_AddedComponents.clear();
m_RemovedComponents.clear();
}
Expand Down Expand Up @@ -209,17 +209,17 @@

public:
TransformComponent() = default;
TransformComponent(const TransformComponent& other) = default;

Check warning on line 212 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-a&open=AZ87vOa3p7dppQPiSw-a&pullRequest=580
explicit TransformComponent(const glm::vec3& translation)
: Translation(translation) {}

[[nodiscard("Store this!")]] glm::vec3 GetRotationEuler() const
{

Check warning on line 217 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-b&open=AZ87vOa3p7dppQPiSw-b&pullRequest=580
return RotationEuler;
}

void SetRotationEuler(const glm::vec3& euler)
{

Check warning on line 222 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent equality "std::equal_to<>" and a custom transparent heterogeneous hasher with this associative string container.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-c&open=AZ87vOa3p7dppQPiSw-c&pullRequest=580
RotationEuler = euler;
Rotation = glm::quat(euler);
}
Expand Down Expand Up @@ -1423,7 +1423,7 @@
// it rebinds on next Play().
OLO_PROPERTY()
AssetHandle SoundGraphHandle = 0;
f32 VolumeMultiplier = 1.0f;

Check warning on line 1426 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this "struct" to a "class" or remove its member functions.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-d&open=AZ87vOa3p7dppQPiSw-d&pullRequest=580
f32 PitchMultiplier = 1.0f;
bool Looping = false;
bool PlayOnAwake = true;
Expand All @@ -1444,7 +1444,7 @@
}

auto operator=(const AudioSoundGraphComponent& other) -> AudioSoundGraphComponent&
{

Check warning on line 1447 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Don't mix public and private data members.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-e&open=AZ87vOa3p7dppQPiSw-e&pullRequest=580
if (this != &other)
{
SoundGraphHandle = other.SoundGraphHandle;
Expand All @@ -1455,15 +1455,15 @@
Sound = nullptr;
}
return *this;
}

Check warning on line 1458 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this 292 characters long line (which is greater than 230 authorized).

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-n&open=AZ87vOa3p7dppQPiSw-n&pullRequest=580

// Equality for undo/redo — compares serialized/editor-visible fields only.
// Float fields use Math::BitwiseEqual per cpp-coding-quality §2a.
auto operator==(const AudioSoundGraphComponent& other) const -> bool
{
return static_cast<u64>(SoundGraphHandle) == static_cast<u64>(other.SoundGraphHandle) && Math::BitwiseEqual(VolumeMultiplier, other.VolumeMultiplier) && Math::BitwiseEqual(PitchMultiplier, other.PitchMultiplier) && Looping == other.Looping && PlayOnAwake == other.PlayOnAwake;

Check warning on line 1464 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this 286 characters long line (which is greater than 230 authorized).

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-o&open=AZ87vOa3p7dppQPiSw-o&pullRequest=580
}

Check warning on line 1465 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this 286 characters long line (which is greater than 230 authorized).

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-p&open=AZ87vOa3p7dppQPiSw-p&pullRequest=580

Check warning on line 1466 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this 283 characters long line (which is greater than 230 authorized).

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-q&open=AZ87vOa3p7dppQPiSw-q&pullRequest=580
// Gameplay-facing helpers to drive graph input parameters at runtime. Returns
// false if the component has no live Sound (e.g. graph not instantiated yet
// because PlayOnAwake was false and Play hasn't been called, or the asset failed
Expand All @@ -1472,34 +1472,34 @@
bool SetParameter(const std::string& name, f32 value) const;
bool SetParameter(const std::string& name, i32 value) const;
bool SetParameter(const std::string& name, bool value) const;
};

// Plays a video file (MPEG-1 .mpg) as a fullscreen overlay — cutscenes, studio logos,
// splash screens, credits. Decoded frames stream to a GPU texture the renderer

Check warning on line 1478 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Overloaded member functions with same access specifier should be grouped in the interface.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-f&open=AZ87vOa3p7dppQPiSw-f&pullRequest=580
// composites on top of the scene. The file is referenced by an asset-relative path;
// the live VideoPlayer is runtime-only (allocated when playback starts, not serialized
// and not shared across copies).
struct VideoOverlayComponent
{
OLO_PROPERTY(Name = "PlayOnStart", Type = "bool", Get = "comp.PlayOnStart", Set = "comp.PlayOnStart = {v}")
OLO_PROPERTY(Name = "SkipOnInput", Type = "bool", Get = "comp.SkipOnInput", Set = "comp.SkipOnInput = {v}")
OLO_PROPERTY(Name = "Looping", Type = "bool", Get = "comp.Looping", Set = "comp.Looping = {v}")
OLO_PROPERTY(Name = "Volume", Type = "float", Get = "comp.Volume", Set = "comp.Volume = {v}")
OLO_PROPERTY(Name = "VideoPath", Type = "string", Get = "comp.VideoPath", Set = "comp.VideoPath = {v}")
std::string VideoPath; // Asset-relative path to the video file.

Check warning on line 1489 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Overloaded member functions with same access specifier should be grouped in the interface.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-g&open=AZ87vOa3p7dppQPiSw-g&pullRequest=580
bool PlayOnStart = false;
bool SkipOnInput = true;
bool Looping = false;
f32 Volume = 1.0f;

Check warning on line 1494 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-h&open=AZ87vOa3p7dppQPiSw-h&pullRequest=580
// Runtime-only state, not serialized and reset to null on copy.
Ref<VideoPlayer> Player = nullptr;

VideoOverlayComponent() = default;

Check warning on line 1498 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-i&open=AZ87vOa3p7dppQPiSw-i&pullRequest=580

VideoOverlayComponent(const VideoOverlayComponent& other)
: VideoPath(other.VideoPath),
PlayOnStart(other.PlayOnStart),

Check warning on line 1502 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-j&open=AZ87vOa3p7dppQPiSw-j&pullRequest=580
SkipOnInput(other.SkipOnInput),
Looping(other.Looping),
Volume(other.Volume),
Expand All @@ -1507,7 +1507,7 @@
{
}

auto operator=(const VideoOverlayComponent& other) -> VideoOverlayComponent&

Check warning on line 1510 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-k&open=AZ87vOa3p7dppQPiSw-k&pullRequest=580
{
if (this != &other)
{
Expand All @@ -1515,7 +1515,7 @@
PlayOnStart = other.PlayOnStart;
SkipOnInput = other.SkipOnInput;
Looping = other.Looping;
Volume = other.Volume;

Check warning on line 1518 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-l&open=AZ87vOa3p7dppQPiSw-l&pullRequest=580
Player = nullptr;
}
return *this;
Expand All @@ -1523,7 +1523,7 @@

// Equality for undo/redo — compares serialized/editor-visible fields only.
auto operator==(const VideoOverlayComponent& other) const -> bool
{

Check warning on line 1526 in OloEngine/src/OloEngine/Scene/Components.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why the return value should not be discarded.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vOa3p7dppQPiSw-m&open=AZ87vOa3p7dppQPiSw-m&pullRequest=580
return VideoPath == other.VideoPath && PlayOnStart == other.PlayOnStart && SkipOnInput == other.SkipOnInput && Looping == other.Looping && Math::BitwiseEqual(Volume, other.Volume);
}
};
Expand Down Expand Up @@ -3083,12 +3083,18 @@
// Local-space half-extents of the buoyancy box (the 8 corners become the
// submersion probes). Default matches a 1 m cube; pick values close to the
// body's collider so the displaced-volume estimate is sensible.
OLO_SERIALIZE(Clamp, Min = 0.01f, Max = 1000.0f)
glm::vec3 m_ProbeExtents = { 0.5f, 0.5f, 0.5f };

f32 m_FluidDensity = 1000.0f; ///< kg/m^3 (fresh water ~1000). Body floats when its mass < density * boxVolume.
f32 m_BuoyancyScale = 1.0f; ///< global multiplier on the Archimedes force (tuning / artistic control)
f32 m_LinearDrag = 0.8f; ///< submerged linear drag coefficient (damps vertical bobbing)
f32 m_AngularDrag = 0.5f; ///< submerged angular drag coefficient (damps rocking)
OLO_SERIALIZE(Clamp, Min = 1.0f, Max = 100000.0f)
f32 m_FluidDensity = 1000.0f; ///< kg/m^3 (fresh water ~1000). Body floats when its mass < density * boxVolume.
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1000.0f)
f32 m_BuoyancyScale = 1.0f; ///< global multiplier on the Archimedes force (tuning / artistic control)
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1000.0f)
f32 m_LinearDrag = 0.8f; ///< submerged linear drag coefficient (damps vertical bobbing)
OLO_SERIALIZE(Clamp, Min = 0.0f, Max = 1000.0f)
f32 m_AngularDrag = 0.5f; ///< submerged angular drag coefficient (damps rocking)
OLO_SERIALIZE(Clamp, Min = 0.001f, Max = 100.0f)
f32 m_SubmergenceRamp = 0.25f; ///< metres over which a probe ramps dry -> fully wet (smooths the waterline)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@
// double-emit, so a new trivial component is auto-serialized and a new complex
// one fails the coverage test until hand-written.

if (auto node = entity["BuoyancyComponent"]; node)
{
auto& comp = deserializedEntity.AddComponent<BuoyancyComponent>();
comp.m_Enabled = node["Enabled"].as<bool>(comp.m_Enabled);
comp.m_ProbeExtents = node["ProbeExtents"].as<glm::vec3>(comp.m_ProbeExtents);
comp.m_ProbeExtents = glm::clamp(comp.m_ProbeExtents, glm::vec3(0.01f), glm::vec3(1000.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["FluidDensity"], v))
comp.m_FluidDensity = std::clamp(v, static_cast<f32>(1.0f), static_cast<f32>(100000.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["BuoyancyScale"], v))
comp.m_BuoyancyScale = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1000.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["LinearDrag"], v))
comp.m_LinearDrag = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1000.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["AngularDrag"], v))
comp.m_AngularDrag = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1000.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["SubmergenceRamp"], v))
comp.m_SubmergenceRamp = std::clamp(v, static_cast<f32>(0.001f), static_cast<f32>(100.0f));
}

if (auto node = entity["CharacterController3DComponent"]; node)
{
auto& comp = deserializedEntity.AddComponent<CharacterController3DComponent>();
Expand Down Expand Up @@ -206,6 +224,28 @@ if (auto node = entity["NetworkLODComponent"]; node)
comp.Level = static_cast<decltype(comp.Level)>(node["Level"].as<int>(static_cast<int>(comp.Level)));
}

if (auto node = entity["NoiseAnimationComponent"]; node)
{
auto& comp = deserializedEntity.AddComponent<NoiseAnimationComponent>();
comp.Enabled = node["Enabled"].as<bool>(comp.Enabled);
comp.EndBoneIndex = node["EndBoneIndex"].as<u32>(comp.EndBoneIndex);
comp.ChainLength = std::max(node["ChainLength"].as<u32>(comp.ChainLength), static_cast<u32>(1u));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["Frequency"], v))
comp.Frequency = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1e4f));
comp.RotationAmplitude = node["RotationAmplitude"].as<glm::vec3>(comp.RotationAmplitude);
comp.RotationAmplitude = glm::clamp(comp.RotationAmplitude, glm::vec3(-6.2832f), glm::vec3(6.2832f));
comp.TranslationAmplitude = node["TranslationAmplitude"].as<glm::vec3>(comp.TranslationAmplitude);
comp.TranslationAmplitude = glm::clamp(comp.TranslationAmplitude, glm::vec3(-1e4f), glm::vec3(1e4f));
comp.Octaves = std::clamp(node["Octaves"].as<u32>(comp.Octaves), static_cast<u32>(1u), static_cast<u32>(8u));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["Lacunarity"], v))
comp.Lacunarity = std::clamp(v, static_cast<f32>(1.0f), static_cast<f32>(8.0f));
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["Gain"], v))
comp.Gain = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1.0f));
comp.Seed = node["Seed"].as<u32>(comp.Seed);
if (f32 v; ::OloEngine::YAMLUtils::TryReadFiniteF32(node["Weight"], v))
comp.Weight = std::clamp(v, static_cast<f32>(0.0f), static_cast<f32>(1.0f));
}

if (auto node = entity["PerceptibleComponent"]; node)
{
auto& comp = deserializedEntity.AddComponent<PerceptibleComponent>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@
// double-emit, so a new trivial component is auto-serialized and a new complex
// one fails the coverage test until hand-written.

if (entity.HasComponent<BuoyancyComponent>())
{
out << YAML::Key << "BuoyancyComponent";
out << YAML::BeginMap; // BuoyancyComponent
auto const& comp = entity.GetComponent<BuoyancyComponent>();
out << YAML::Key << "Enabled" << YAML::Value << comp.m_Enabled;
out << YAML::Key << "ProbeExtents" << YAML::Value << comp.m_ProbeExtents;
out << YAML::Key << "FluidDensity" << YAML::Value << comp.m_FluidDensity;
out << YAML::Key << "BuoyancyScale" << YAML::Value << comp.m_BuoyancyScale;
out << YAML::Key << "LinearDrag" << YAML::Value << comp.m_LinearDrag;
out << YAML::Key << "AngularDrag" << YAML::Value << comp.m_AngularDrag;
out << YAML::Key << "SubmergenceRamp" << YAML::Value << comp.m_SubmergenceRamp;
out << YAML::EndMap; // BuoyancyComponent
}

if (entity.HasComponent<CharacterController3DComponent>())
{
out << YAML::Key << "CharacterController3DComponent";
Expand Down Expand Up @@ -217,6 +232,25 @@ if (entity.HasComponent<NetworkLODComponent>())
out << YAML::EndMap; // NetworkLODComponent
}

if (entity.HasComponent<NoiseAnimationComponent>())
{
out << YAML::Key << "NoiseAnimationComponent";
out << YAML::BeginMap; // NoiseAnimationComponent
auto const& comp = entity.GetComponent<NoiseAnimationComponent>();
out << YAML::Key << "Enabled" << YAML::Value << comp.Enabled;
out << YAML::Key << "EndBoneIndex" << YAML::Value << comp.EndBoneIndex;
out << YAML::Key << "ChainLength" << YAML::Value << comp.ChainLength;
out << YAML::Key << "Frequency" << YAML::Value << comp.Frequency;
out << YAML::Key << "RotationAmplitude" << YAML::Value << comp.RotationAmplitude;
out << YAML::Key << "TranslationAmplitude" << YAML::Value << comp.TranslationAmplitude;
out << YAML::Key << "Octaves" << YAML::Value << comp.Octaves;
out << YAML::Key << "Lacunarity" << YAML::Value << comp.Lacunarity;
out << YAML::Key << "Gain" << YAML::Value << comp.Gain;
out << YAML::Key << "Seed" << YAML::Value << comp.Seed;
out << YAML::Key << "Weight" << YAML::Value << comp.Weight;
out << YAML::EndMap; // NoiseAnimationComponent
}

if (entity.HasComponent<PerceptibleComponent>())
{
out << YAML::Key << "PerceptibleComponent";
Expand Down
84 changes: 0 additions & 84 deletions OloEngine/src/OloEngine/Scene/SceneSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1791,7 +1791,7 @@
TrySet(sgc.PitchMultiplier, soundGraphComponent["PitchMultiplier"]);
TrySet(sgc.Looping, soundGraphComponent["Looping"]);
TrySet(sgc.PlayOnAwake, soundGraphComponent["PlayOnAwake"]);
}

Check failure on line 1794 in OloEngine/src/OloEngine/Scene/SceneSerializer.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not pass an array as a single pointer. Consider using std::string_view to avoid array to pointer decay.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vONNp7dppQPiSw-J&open=AZ87vONNp7dppQPiSw-J&pullRequest=580

Check warning on line 1794 in OloEngine/src/OloEngine/Scene/SceneSerializer.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rewrite the function arguments to make its use less error-prone.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vONNp7dppQPiSw-H&open=AZ87vONNp7dppQPiSw-H&pullRequest=580

if (const auto& videoOverlayComponent = entity["VideoOverlayComponent"])
{
Expand Down Expand Up @@ -2808,26 +2808,6 @@
DeserializeWaterComponent(water, waterComponent);
}

if (auto buoyancyComponent = entity["BuoyancyComponent"]; buoyancyComponent)
{
auto& buoyancy = deserializedEntity.AddComponent<BuoyancyComponent>();
buoyancy.m_Enabled = buoyancyComponent["Enabled"].as<bool>(buoyancy.m_Enabled);
buoyancy.m_ProbeExtents = buoyancyComponent["ProbeExtents"].as<glm::vec3>(buoyancy.m_ProbeExtents);
buoyancy.m_FluidDensity = buoyancyComponent["FluidDensity"].as<f32>(buoyancy.m_FluidDensity);
buoyancy.m_BuoyancyScale = buoyancyComponent["BuoyancyScale"].as<f32>(buoyancy.m_BuoyancyScale);
buoyancy.m_LinearDrag = buoyancyComponent["LinearDrag"].as<f32>(buoyancy.m_LinearDrag);
buoyancy.m_AngularDrag = buoyancyComponent["AngularDrag"].as<f32>(buoyancy.m_AngularDrag);
buoyancy.m_SubmergenceRamp = buoyancyComponent["SubmergenceRamp"].as<f32>(buoyancy.m_SubmergenceRamp);

// Validate every float read from YAML (project rule).
SanitizeVec3Clamped(buoyancy.m_ProbeExtents, 0.01f, 1000.0f, { 0.5f, 0.5f, 0.5f });
SanitizeFloat(buoyancy.m_FluidDensity, 1.0f, 100000.0f, 1000.0f);
SanitizeFloat(buoyancy.m_BuoyancyScale, 0.0f, 1000.0f, 1.0f);
SanitizeFloat(buoyancy.m_LinearDrag, 0.0f, 1000.0f, 0.8f);
SanitizeFloat(buoyancy.m_AngularDrag, 0.0f, 1000.0f, 0.5f);
SanitizeFloat(buoyancy.m_SubmergenceRamp, 0.001f, 100.0f, 0.25f);
}

if (auto decalComponent = entity["DecalComponent"]; decalComponent)
{
DeserializeDecalComponent(deserializedEntity, decalComponent);
Expand Down Expand Up @@ -3627,32 +3607,6 @@
SanitizeFloat(ik.ChainWeight, 0.0f, 1.0f, 1.0f);
}

if (auto noiseNode = entity["NoiseAnimationComponent"]; noiseNode)
{
auto& noise = deserializedEntity.AddComponent<NoiseAnimationComponent>();
TrySet(noise.Enabled, noiseNode["Enabled"]);
TrySet(noise.EndBoneIndex, noiseNode["EndBoneIndex"]);
TrySet(noise.ChainLength, noiseNode["ChainLength"]);
TrySet(noise.Frequency, noiseNode["Frequency"]);
TrySet(noise.RotationAmplitude, noiseNode["RotationAmplitude"]);
TrySet(noise.TranslationAmplitude, noiseNode["TranslationAmplitude"]);
TrySet(noise.Octaves, noiseNode["Octaves"]);
TrySet(noise.Lacunarity, noiseNode["Lacunarity"]);
TrySet(noise.Gain, noiseNode["Gain"]);
TrySet(noise.Seed, noiseNode["Seed"]);
TrySet(noise.Weight, noiseNode["Weight"]);

// Sanitize float/vector fields — replace NaN/Inf with defaults and clamp to valid ranges
noise.ChainLength = std::max(1u, noise.ChainLength);
noise.Octaves = std::clamp(noise.Octaves, 1u, 8u);
SanitizeFloat(noise.Frequency, 0.0f, 1e4f, 1.0f);
SanitizeVec3Clamped(noise.RotationAmplitude, -6.2832f, 6.2832f, glm::vec3(0.08f));
SanitizeVec3Clamped(noise.TranslationAmplitude, -1e4f, 1e4f, glm::vec3(0.0f));
SanitizeFloat(noise.Lacunarity, 1.0f, 8.0f, 2.0f);
SanitizeFloat(noise.Gain, 0.0f, 1.0f, 0.5f);
SanitizeFloat(noise.Weight, 0.0f, 1.0f, 1.0f);
}

// Auto-generated trivial-component deserialize blocks (OloHeaderTool, issue
// #380) — the read-side complement of SceneSerializeComponents.Generated.inl.
// Floats are validated with std::isfinite; a missing key keeps the default.
Expand Down Expand Up @@ -3832,7 +3786,7 @@

out << YAML::EndMap; // AudioListenerComponent
}

Check warning on line 3789 in OloEngine/src/OloEngine/Scene/SceneSerializer.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "std::to_underlying" to cast enums to their underlying type.

See more on https://sonarcloud.io/project/issues?id=drsnuggles8_OloEngineBase&issues=AZ87vONNp7dppQPiSw-I&open=AZ87vONNp7dppQPiSw-I&pullRequest=580
if (entity.HasComponent<AudioSoundGraphComponent>())
{
out << YAML::Key << "AudioSoundGraphComponent";
Expand Down Expand Up @@ -4941,23 +4895,6 @@
out << YAML::EndMap; // WaterComponent
}

if (entity.HasComponent<BuoyancyComponent>())
{
out << YAML::Key << "BuoyancyComponent";
out << YAML::BeginMap;

auto const& buoyancy = entity.GetComponent<BuoyancyComponent>();
out << YAML::Key << "Enabled" << YAML::Value << buoyancy.m_Enabled;
out << YAML::Key << "ProbeExtents" << YAML::Value << buoyancy.m_ProbeExtents;
out << YAML::Key << "FluidDensity" << YAML::Value << buoyancy.m_FluidDensity;
out << YAML::Key << "BuoyancyScale" << YAML::Value << buoyancy.m_BuoyancyScale;
out << YAML::Key << "LinearDrag" << YAML::Value << buoyancy.m_LinearDrag;
out << YAML::Key << "AngularDrag" << YAML::Value << buoyancy.m_AngularDrag;
out << YAML::Key << "SubmergenceRamp" << YAML::Value << buoyancy.m_SubmergenceRamp;

out << YAML::EndMap; // BuoyancyComponent
}

if (entity.HasComponent<DecalComponent>())
{
out << YAML::Key << "DecalComponent";
Expand Down Expand Up @@ -5744,27 +5681,6 @@
out << YAML::EndMap; // IKTargetComponent
}

if (entity.HasComponent<NoiseAnimationComponent>())
{
out << YAML::Key << "NoiseAnimationComponent";
out << YAML::BeginMap;

auto const& noise = entity.GetComponent<NoiseAnimationComponent>();
out << YAML::Key << "Enabled" << YAML::Value << noise.Enabled;
out << YAML::Key << "EndBoneIndex" << YAML::Value << noise.EndBoneIndex;
out << YAML::Key << "ChainLength" << YAML::Value << noise.ChainLength;
out << YAML::Key << "Frequency" << YAML::Value << noise.Frequency;
out << YAML::Key << "RotationAmplitude" << YAML::Value << noise.RotationAmplitude;
out << YAML::Key << "TranslationAmplitude" << YAML::Value << noise.TranslationAmplitude;
out << YAML::Key << "Octaves" << YAML::Value << noise.Octaves;
out << YAML::Key << "Lacunarity" << YAML::Value << noise.Lacunarity;
out << YAML::Key << "Gain" << YAML::Value << noise.Gain;
out << YAML::Key << "Seed" << YAML::Value << noise.Seed;
out << YAML::Key << "Weight" << YAML::Value << noise.Weight;

out << YAML::EndMap; // NoiseAnimationComponent
}

// Auto-generated trivial-component serialize blocks (OloHeaderTool, issue #380).
// One `if (entity.HasComponent<T>()) { … }` per all-trivial component not in
// the generator's kComponentsCustomSerialize set. Editing the touch-point out
Expand Down
1 change: 1 addition & 0 deletions OloEngine/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ add_executable(OloEngine-Tests
Serialization/FontAssetPackSerializerTest.cpp
Serialization/NestedStructSerializerCodegenTest.cpp
Serialization/ContainerSerializerCodegenTest.cpp
Serialization/Vec3ClampSerializerCodegenTest.cpp
# SaveGame Tests
SaveGame/SaveGameFileTest.cpp
SaveGame/SaveGameManagerTest.cpp
Expand Down
Loading
Loading