CoriEngine
Loading...
Searching...
No Matches
Components.hpp
Go to the documentation of this file.
1#pragma once
2#define GLM_ENABLE_EXPERIMENTAL
3#include <box2cpp/box2cpp.h>
4#include "Entity.hpp"
6#include <glm/gtx/matrix_transform_2d.hpp>
7#include <utility>
8#include "Audio/Track.hpp"
9
10namespace Cori {
11 namespace Physics {
12 struct BodyUserData {
13 static constexpr auto in_place_delete = true;
14
15 BodyUserData() = default;
17 };
18 }
19}
20
21namespace Cori {
25 namespace World {
26 class Scene;
27
28 namespace Systems {
29 class Transform;
30 class Hierarchy;
31 class Animation;
32 }
33
37 namespace Components {
41 namespace Entity {
42 namespace Internal {
48 DirtyTransformFlag() = default;
49
50 private:
51 // entt cant create fully empty components
52 [[maybe_unused]] bool bober{};
53 };
54 }
55
59 struct Name {
60 Name() = default;
61 private:
62 friend World::Entity;
63 friend World::Scene;
64 std::string m_Name;
65 };
66
70 struct UUID {
71 UUID() = default;
72 explicit UUID(Core::UUID uuid) : m_UUID(std::move(uuid)) {}
73 explicit UUID(const std::string& uuid_str) : m_UUID(uuid_str) {}
74
75 UUID(const UUID&) = delete;
76 UUID& operator=(const UUID&) = delete;
77 UUID(UUID&&) = delete;
78 UUID& operator=(UUID&&) = delete;
79
81 };
82
86 struct Hierarchy {
87 Hierarchy() = default;
88
89 Hierarchy(const Hierarchy&) = delete;
90 Hierarchy& operator=(const Hierarchy&) = delete;
91 Hierarchy(Hierarchy&&) = delete;
93
94 private:
95 friend World::Entity;
96 friend Systems::Transform;
97 friend Systems::Hierarchy;
98 friend struct Transform;
99 entt::entity m_Parent { entt::null };
100 entt::entity m_FirstChild { entt::null };
101 entt::entity m_NextSibling { entt::null };
102 entt::entity m_PreviousSibling { entt::null };
103 };
104
108 struct Transform {
109 Transform() = default;
110
111 Transform(const Transform&) = delete;
112 Transform& operator=(const Transform&) = delete;
113 Transform(Transform&&) = delete;
115
121 void SetLocalPosition(const glm::vec2 localPosition) {
122 if (m_LocalPosition != localPosition) {
123 m_LocalPosition = localPosition;
124 m_DirtyTransform = true;
125
126 entt::entity root = m_Owner.GetRawEntity();
127 entt::entity currentParent = m_Owner.GetComponents<Hierarchy>().m_Parent;
128 while (m_Owner.GetRawHandle().registry()->valid(currentParent)) {
129 root = currentParent;
130 currentParent = m_Owner.GetRawHandle().registry()->get<Hierarchy>(root).m_Parent;
131 }
132
133 if (!m_Owner.GetRawHandle().registry()->all_of<Internal::DirtyTransformFlag>(root)) {
134 m_Owner.GetRawHandle().registry()->emplace<Internal::DirtyTransformFlag>(root);
135 }
136 }
137 }
138
144 void SetLocalRotation(const float localRotation) {
145 if (m_LocalRotation != localRotation) {
146 m_LocalRotation = localRotation;
147 m_DirtyTransform = true;
148
149 entt::entity root = m_Owner.GetRawEntity();
150 entt::entity currentParent = m_Owner.GetComponents<Hierarchy>().m_Parent;
151 while (m_Owner.GetRawHandle().registry()->valid(currentParent)) {
152 root = currentParent;
153 currentParent = m_Owner.GetRawHandle().registry()->get<Hierarchy>(root).m_Parent;
154 }
155
156 if (!m_Owner.GetRawHandle().registry()->all_of<Internal::DirtyTransformFlag>(root)) {
157 m_Owner.GetRawHandle().registry()->emplace<Internal::DirtyTransformFlag>(root);
158 }
159 }
160 }
161
167 void SetLocalScale(const glm::vec2 localScale) {
168 if (m_LocalScale != localScale) {
169 m_LocalScale = localScale;
170 m_DirtyTransform = true;
171
172 entt::entity root = m_Owner.GetRawEntity();
173 entt::entity currentParent = m_Owner.GetComponents<Hierarchy>().m_Parent;
174 while (m_Owner.GetRawHandle().registry()->valid(currentParent)) {
175 root = currentParent;
176 currentParent = m_Owner.GetRawHandle().registry()->get<Hierarchy>(root).m_Parent;
177 }
178
179 if (!m_Owner.GetRawHandle().registry()->all_of<Internal::DirtyTransformFlag>(root)) {
180 m_Owner.GetRawHandle().registry()->emplace<Internal::DirtyTransformFlag>(root);
181 }
182 }
183 }
184
190 void SetLocalDepth(const int16_t localDepth) {
191 if (m_LocalDepthOffset != localDepth) {
192 m_LocalDepthOffset = localDepth;
193 m_DirtyDepth = true;
194
195 entt::entity root = m_Owner.GetRawEntity();
196 entt::entity currentParent = m_Owner.GetComponents<Hierarchy>().m_Parent;
197 while (m_Owner.GetRawHandle().registry()->valid(currentParent)) {
198 root = currentParent;
199 currentParent = m_Owner.GetRawHandle().registry()->get<Hierarchy>(root).m_Parent;
200 }
201
202 if (!m_Owner.GetRawHandle().registry()->all_of<Internal::DirtyTransformFlag>(root)) {
203 m_Owner.GetRawHandle().registry()->emplace<Internal::DirtyTransformFlag>(root);
204 }
205 }
206 }
207
212 [[nodiscard]] glm::vec2 GetLocalPosition() const {
213 return m_LocalPosition;
214 }
215
220 [[nodiscard]] glm::vec2 GetLocalScale() const {
221 return m_LocalScale;
222 }
223
228 [[nodiscard]] float GetLocalRotation() const {
229 return m_LocalRotation;
230 }
231
236 [[nodiscard]] int16_t GetLocalDepthOffset() const {
237 return m_LocalDepthOffset;
238 }
239
245 void SetDetachedState(const bool state) {
246 m_Detached = state;
247 }
248
253 [[nodiscard]] bool GetDetachedState() const {
254 return m_Detached;
255 }
256
261 [[nodiscard]] glm::mat3 GetLocalTransform() const {
262 return glm::translate(glm::mat3(1.0f), m_LocalPosition) *
263 glm::rotate(glm::mat3(1.0f), glm::radians(m_LocalRotation)) *
264 glm::scale(glm::mat3(1.0f), m_LocalScale);
265 }
266
267 private:
268 friend Systems::Transform;
269 glm::vec2 m_LocalPosition{ 0.0f, 0.0f };
270 glm::vec2 m_LocalScale{ 1.0f, 1.0f };
271 float m_LocalRotation{ 0.0f };
272 glm::mat3 m_LastParentTransform{ 1.0f };
273 World::Entity m_Owner;
274 public:
275 glm::mat3 m_WorldTransform{ 1.0f };
276 uint8_t m_WorldDepth{ 1 };
277 private:
278 int16_t m_LocalDepthOffset{ 0 };
279 bool m_Detached{ false };
280 bool m_DirtyTransform{ true };
281 bool m_DirtyDepth{ true };
282 };
283
287 struct ChildCache {
288 ChildCache() = default;
289
290 ChildCache(const ChildCache&) = delete;
291 ChildCache& operator=(const ChildCache&) = delete;
294
295 private:
296 friend World::Entity;
297 friend Systems::Hierarchy;
298 struct TransparentHash {
299 using is_transparent = void;
300 size_t operator()(std::string_view sv) const noexcept {
301 return std::hash<std::string_view>{}(sv);
302 }
303 };
304
305 struct TransparentEqual {
306 using is_transparent = void;
307 bool operator()(std::string_view lhs, std::string_view rhs) const noexcept {
308 return lhs == rhs;
309 }
310 };
311
312 std::unordered_map<std::string, entt::entity, TransparentHash, TransparentEqual> m_Children;
313 };
314
321 private:
322 // entt cant create fully empty components
323 [[maybe_unused]] bool pingvin{};
324 };
325
332 private:
333 // entt cant create fully empty components
334 [[maybe_unused]] bool homik{};
335 };
336
342 QuadRenderer() = default;
343
344 QuadRenderer(const glm::vec2 halfSize, const std::shared_ptr<Graphics::Texture2D>& texture, const Graphics::UVs& uvs) : m_HalfSize(halfSize), m_UVs(uvs) {
345 const auto result = SetTexture(texture);
346 if (!result) {
347 CORI_CORE_WARN_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self, Logger::Tags::World::Entity::QuadRenderer }, "Failed to fully recreate Quad Renderer. Details: '{}'", result.error().what());
348 }
349 }
350
351 QuadRenderer(const glm::vec2 halfSize, const std::shared_ptr<Graphics::Texture2D>& texture, const Graphics::UVs& uvs, const glm::vec4& tintColor) : m_HalfSize(halfSize), m_UVs(uvs) {
352 const auto result = SetTexture(texture);
353 if (!result) {
354 CORI_CORE_WARN_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self, Logger::Tags::World::Entity::QuadRenderer }, "Failed to fully recreate Quad Renderer. Details: '{}'", result.error().what());
355 }
356 SetColor(tintColor);
357 }
358
359 QuadRenderer(const glm::vec2 halfSize, const glm::vec4& color) : m_HalfSize(halfSize), m_FlatColored(true) {
360 SetColor(color);
361 }
362
363 QuadRenderer(const QuadRenderer&) = delete;
367
374 std::expected<void, Core::CoriError<>> SetTexture(const std::shared_ptr<Graphics::Texture2D>& texture) {
375 if (!m_AnimatorBound) {
376 if (m_HasSemiTransparency && m_Color.a != 1.0f) {
377 m_Texture = texture;
378 return {};
379 }
380 m_HasSemiTransparency = texture->HasSemiTransparency();
381 m_Texture = texture;
382 return {};
383 }
384
385 return std::unexpected(Core::CoriError("Can't set Texture2D because Quad Animator is currently bound."));
386 }
387
392 [[nodiscard]] const std::shared_ptr<Graphics::Texture2D>& GetTexture() const {
393 return m_Texture;
394 }
395
400 void SetColor(const glm::vec4& color) {
401 if (m_HasSemiTransparency && (m_Texture ? m_Texture->HasSemiTransparency() : false)) {
402 m_Color = color;
403 return;
404 }
405 m_Color = color;
406 if (m_Color.a != 1.0f) {
407 m_HasSemiTransparency = true;
408 } else {
409 m_HasSemiTransparency = false;
410 }
411 }
412
417 [[nodiscard]] const glm::vec4& GetColor() const {
418 return m_Color;
419 }
420
427 std::expected<void, Core::CoriError<>> SetUVs(const Graphics::UVs& uvs) {
428 if (!m_AnimatorBound) {
429 m_UVs = uvs;
430 return {};
431 }
432
433 return std::unexpected(Core::CoriError("Can't set UVs because Quad Animator is currently bound."));
434 }
435
440 [[nodiscard]] const Graphics::UVs& GetUVs() const {
441 return m_UVs;
442 }
443
450 std::expected<void, Core::CoriError<>> SetHalfSize(const glm::vec2 halfSize) {
451 if (!m_AnimatorBound) {
452 m_HalfSize = halfSize;
453 return {};
454 }
455 return std::unexpected(Core::CoriError("Can't set HalfSize because Quad Animator is currently bound."));
456 }
457
462 [[nodiscard]] glm::vec2 GetHalfSize() const {
463 return m_HalfSize;
464 }
465
470 [[nodiscard]] bool GetSemiTransparencyState() const {
471 return m_HasSemiTransparency;
472 }
473
474 private:
475 friend class QuadAnimator;
476 friend Systems::Animation;
477
478 glm::vec2 m_HalfSize{ 0.0f };
479 Graphics::UVs m_UVs{};
480 std::shared_ptr<Graphics::Texture2D> m_Texture{ nullptr };
481 glm::vec4 m_Color{ 1.0f, 1.0f, 1.0f, 1.0f };
482 public:
483 bool m_Visible{ true };
484 bool m_FlatColored{ false };
485 bool m_FlipX{ false };
486 bool m_FlipY{ false };
487 private:
488 bool m_HasSemiTransparency{ false };
489 bool m_AnimatorBound{ false };
490 };
491
495 struct AudioSource {
496 AudioSource() = default;
497
498 AudioSource(const AudioSource&) = delete;
502
508 std::shared_ptr<Audio::Track> AddTrack(const std::string& name) {
509 std::shared_ptr<Audio::Track> track = Audio::Track::Create(name);
510 m_AudioTracks.insert({name, track});
511 return track;
512 }
513
519 std::shared_ptr<Audio::Track> AddTrack(const char* name) {
520 std::shared_ptr<Audio::Track> track = Audio::Track::Create(name);
521 m_AudioTracks.insert({name, track});
522 return track;
523 }
524
530 void RemoveTrack(const std::string& name) {
531 if (m_AudioTracks.contains(name)) {
532 m_AudioTracks.erase(name);
533 }
534 }
535
541 void RemoveTrack(const char* name) {
542 if (m_AudioTracks.contains(name)) {
543 m_AudioTracks.erase(name);
544 }
545 }
546
552 std::expected<std::shared_ptr<Audio::Track>, Core::CoriError<>> GetTrack(const std::string& name) {
553 if (m_AudioTracks.contains(name)) {
554 return m_AudioTracks.at(name);
555 }
556
557 return std::unexpected(Core::CoriError(std::format("No audio Track is found with the specified name '{}'", name)));
558 }
559
565 std::expected<std::shared_ptr<Audio::Track>, Core::CoriError<>> GetTrack(const char* name) {
566 if (m_AudioTracks.contains(name)) {
567 return m_AudioTracks.at(name);
568 }
569
570 return std::unexpected(Core::CoriError(std::format("No audio Track is found with the specified name '{}'", name)));
571 }
572
573 private:
574 struct TransparentHash {
575 using is_transparent = void;
576 size_t operator()(std::string_view sv) const noexcept {
577 return std::hash<std::string_view>{}(sv);
578 }
579 };
580
581 struct TransparentEqual {
582 using is_transparent = void;
583 bool operator()(std::string_view lhs, std::string_view rhs) const noexcept {
584 return lhs == rhs;
585 }
586 };
587
588 std::unordered_map<std::string, std::shared_ptr<Audio::Track>, TransparentHash, TransparentEqual> m_AudioTracks;
589 };
590
597 struct RigidBody : Physics::BodyRef {
603 RigidBody(Physics::WorldRef world, const std::derived_from<b2BodyDef> auto& def) : Physics::BodyRef{world.CreateBody(Physics::DestroyWithParent, def)} {}
604
605 ~RigidBody() { if (IsValid()) { Destroy(); } }
606
607 RigidBody(const RigidBody&) = delete;
608 RigidBody& operator=(const RigidBody&) = delete;
609 RigidBody(RigidBody&&) = delete;
611 };
612 }
613 }
614 }
615}
#define CORI_CORE_WARN_TAGGED(...)
Definition Logger.hpp:1038
static std::shared_ptr< Track > Create(std::string name)
Creates a Track object.
Definition Track.cpp:154
Custom error class mainly used in std::expected.
Definition Error.hpp:27
A 128bit UUID, can be serialized to the string and deserialized from it.
Definition Uuid.hpp:10
Entities are the essential part of WorldSystem.
Definition Entity.hpp:25
A scene in a game world.
Definition Scene.hpp:20
System that is responsible for Animations, every Scene has it by default.
Anything connected to physics is in this namespace. Please refer to Box2D docs 'https://box2d....
Components designed to be used with entities.
Components that are used with the WorldSystem (ECS).
Global engine namespace.
static constexpr char Self[]
Definition Logger.hpp:127
static constexpr char QuadRenderer[]
Definition Logger.hpp:131
static constexpr char Self[]
Definition Logger.hpp:119
static constexpr auto in_place_delete
Cori::World::Entity m_Entity
std::expected< std::shared_ptr< Audio::Track >, Core::CoriError<> > GetTrack(const char *name)
Retries a Track from the AudioSource cache.
AudioSource(const AudioSource &)=delete
AudioSource & operator=(AudioSource &&)=delete
std::shared_ptr< Audio::Track > AddTrack(const char *name)
Adds a Track to the AudioSource cache.
AudioSource & operator=(const AudioSource &)=delete
std::shared_ptr< Audio::Track > AddTrack(const std::string &name)
Adds a Track to the AudioSource cache.
void RemoveTrack(const char *name)
Removes a Track from the AudioSource, and deletes it if it is not referenced anywhere.
std::expected< std::shared_ptr< Audio::Track >, Core::CoriError<> > GetTrack(const std::string &name)
Retries a Track from the AudioSource cache.
void RemoveTrack(const std::string &name)
Removes a Track from the AudioSource, and deletes it if it is not referenced anywhere.
ChildCache(const ChildCache &)=delete
ChildCache & operator=(ChildCache &&)=delete
ChildCache & operator=(const ChildCache &)=delete
Every Entity has a hierarchy component by default, it's essential for entity hierarchy system.
Hierarchy & operator=(Hierarchy &&)=delete
Hierarchy & operator=(const Hierarchy &)=delete
Flags an Entity transform for recalculation. Only for internal usage!
glm::vec2 GetHalfSize() const
Gets the current quad half size.
void SetColor(const glm::vec4 &color)
Changes the tint color of the quad.
QuadRenderer & operator=(QuadRenderer &&)=delete
const std::shared_ptr< Graphics::Texture2D > & GetTexture() const
Returns a const reference to the currently active texture.
std::expected< void, Core::CoriError<> > SetUVs(const Graphics::UVs &uvs)
Changes the current UVs that are used when sampling fom the texture.
const Graphics::UVs & GetUVs() const
Gets a const reference to the current UVs of the quad.
QuadRenderer(const QuadRenderer &)=delete
QuadRenderer(const glm::vec2 halfSize, const std::shared_ptr< Graphics::Texture2D > &texture, const Graphics::UVs &uvs)
std::expected< void, Core::CoriError<> > SetHalfSize(const glm::vec2 halfSize)
Changes the current half size that are used when drawing the quad.
QuadRenderer(const glm::vec2 halfSize, const std::shared_ptr< Graphics::Texture2D > &texture, const Graphics::UVs &uvs, const glm::vec4 &tintColor)
bool GetSemiTransparencyState() const
Checks if a quad needs to be processed with transparency in mind or no.
QuadRenderer(const glm::vec2 halfSize, const glm::vec4 &color)
std::expected< void, Core::CoriError<> > SetTexture(const std::shared_ptr< Graphics::Texture2D > &texture)
Changes the texture that is used to render the quad.
const glm::vec4 & GetColor() const
Gets a const reference to the current tint color of the quad.
QuadRenderer & operator=(const QuadRenderer &)=delete
RigidBody(Physics::WorldRef world, const std::derived_from< b2BodyDef > auto &def)
Creates a RigidBody.
RigidBody & operator=(RigidBody &&)=delete
RigidBody & operator=(const RigidBody &)=delete
void SetLocalPosition(const glm::vec2 localPosition)
Changes the local position of the Entity.
void SetDetachedState(const bool state)
Sets the detach state.
void SetLocalRotation(const float localRotation)
Changes the local rotation of the Entity.
glm::vec2 GetLocalPosition() const
Retries the local position.
int16_t GetLocalDepthOffset() const
Retries the local depth.
Transform & operator=(Transform &&)=delete
void SetLocalScale(const glm::vec2 localScale)
Changes the local scale of the Entity.
float GetLocalRotation() const
Retries the local rotation.
void SetLocalDepth(const int16_t localDepth)
Changes the local depth of the Entity.
glm::mat3 GetLocalTransform() const
Calculates a local transform (matrix) of the Entity, combines all the positions (position,...
bool GetDetachedState() const
Gets the current state of detachment.
Transform & operator=(const Transform &)=delete
glm::vec2 GetLocalScale() const
Retries the local scale.
UUID & operator=(const UUID &)=delete
UUID(const std::string &uuid_str)
UUID & operator=(UUID &&)=delete