added basic structures

This commit is contained in:
2026-01-17 13:48:25 +01:00
parent 0e4689cf35
commit 53c7d564d7
23 changed files with 2247 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
#include "BehaviourScript.hpp"
namespace TSE
{
BehaviourScript::BehaviourScript()
: baseObject(nullptr), enabled(true) {}
void BehaviourScript::SetEnabled(bool value) {
enabled = value;
}
bool BehaviourScript::IsEnabled() const {
return enabled;
}
void BehaviourScript::SetBaseObject(Transformable* obj) {
baseObject = obj;
}
Transformable* BehaviourScript::GetTransform() const {
return baseObject;
}
} // namespace TSE

View File

@@ -0,0 +1,29 @@
#pragma once
namespace TSE
{
class Transformable;
class BehaviourScript
{
public:
BehaviourScript();
virtual ~BehaviourScript() = default;
inline virtual void OnUpdate() { };
inline virtual void OnEnable() { };
inline virtual void OnDisable() { };
inline virtual void Start() { };
virtual const char* GetName() = 0;
inline virtual void CustomDraw(const bool& debug) { };
void SetEnabled(bool v);
bool IsEnabled() const;
void SetBaseObject(Transformable* obj);
Transformable* GetTransform() const;
Transformable* baseObject;
protected:
bool enabled = true;
};
} // namespace TSE

View File

@@ -0,0 +1,96 @@
#include "Layer.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "elements/BehaviourScript.hpp"
void HandleObject(TSE::Transformable* trans, TSE::TransformationStack& stack, TSE::IRenderer& rnd)
{
using namespace TSE;
if(!trans->IsEnabled()) return;
//OPTIMIZE this if statement
if(trans->HasBehaviourScript(RENDERABLE) && trans->GetBehaviourScript(RENDERABLE)->IsEnabled() && ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial() != nullptr && ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial()->GetShader() != nullptr)
{
rnd.Submit(*trans, ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial()->GetShader(), stack);
}
if(trans->GetChildren().size() > 0)
{
stack.Push(trans->GetLocalMatrix());
for(auto child : trans->GetChildren())
{
HandleObject(child, stack, rnd);
}
stack.Pop();
}
}
TSE::Layer::Layer(string &n)
{
name = n;
}
void TSE::Layer::Render(IRenderer &rnd) const
{
TransformationStack stack;
for(auto obj : objectsToRender)
{
HandleObject(obj, stack, rnd);
}
}
void TSE::Layer::AddTransformable(Transformable *t)
{
objectsToRender.push_back(t);
}
bool TSE::Layer::HasTransformable(const Transformable *t) const
{
for(auto trans2 : objectsToRender)
{
if(t->id == trans2->id)
{
return true;
}
}
return false;
}
void TSE::Layer::RemoveTransformable(const Transformable *t)
{
RemoveTransformable(t->id);
}
void TSE::Layer::RemoveTransformable(const uuids::uuid id)
{
auto it = objectsToRender.begin();
for(auto trans : objectsToRender)
{
if(trans->id == id)
{
objectsToRender.erase(it);
break;
}
it++;
}
}
TSE::string TSE::Layer::GetName() const
{
return name;
}
void TSE::Layer::SetName(const string &n)
{
name = n;
}
std::vector<TSE::Transformable *> &TSE::Layer::GetAllObjects()
{
return objectsToRender;
}
void TSE::Layer::Update()
{
for(auto trans : objectsToRender)
{
trans->Update();
}
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include "Transformable.hpp"
#include "Types.hpp"
#include "interfaces/IRenderer.hpp"
#include <vector>
namespace TSE
{
class Layer
{
private:
string name;
std::vector<Transformable*> objectsToRender;
public:
Layer(string& name);
void Render(IRenderer& rnd) const;
void AddTransformable(Transformable* t);
bool HasTransformable(const Transformable* t) const;
void RemoveTransformable(const Transformable* t);
void RemoveTransformable(const uuids::uuid id);
string GetName() const;
void SetName(const string& name);
std::vector<Transformable*>& GetAllObjects();
void Update();
};
} // namespace TSE

View File

@@ -0,0 +1,81 @@
#include "Material.hpp"
#include <stdexcept>
#include "IdGenerator.hpp"
#include "interfaces/ITexture.hpp"
#include "Types.hpp"
#include "Vector2.hpp"
#include "Vector3.hpp"
#include "Vector4.hpp"
#include "Color.hpp"
#include "Matrix4x4.hpp"
namespace TSE
{
Material::Material()
: name(""), shader(nullptr)
{
id = GenerateRandomUUID();
}
Material::Material(const string& name, IShader* shader, uuids::uuid id)
: name(name), shader(shader), id(id) {}
Material::Material(const string &name, IShader *shader)
: name(name), shader(shader)
{
id = GenerateRandomUUID();
}
bool Material::HasValue(const string &key) const
{
return values.find(key) != values.end();
}
int Material::GetValueCount() const
{
return values.size();
}
std::tuple<std::any, string, string> &Material::GetValueAt(int j)
{
auto it = values.begin();
for (int i = 0; i < j; i++)
{
it++;
}
return it->second;
}
string &Material::GetName()
{
return name;
}
IShader *Material::GetShader() const
{
return shader;
}
void Material::SetShader(IShader *shader)
{
this->shader = shader;
}
uuids::uuid Material::GetID() const
{
return id;
}
template void Material::SetValue<int>(const string&, const int&);
template void Material::SetValue<float>(const string&, const float&);
template void Material::SetValue<Vector2>(const string&, const Vector2&);
template void Material::SetValue<Vector3>(const string&, const Vector3&);
template void Material::SetValue<Vector4>(const string&, const Vector4&);
template void Material::SetValue<Matrix4x4>(const string&, const Matrix4x4&);
template void Material::SetValue<Color>(const string&, const Color&);
template void Material::SetValue<string>(const string&, const string&);
template void Material::SetValue<ITexture>(const string&, const ITexture*);
template int Material::GetValue<int>(const string&) const;
template float Material::GetValue<float>(const string&) const;
template Vector2 Material::GetValue<Vector2>(const string&) const;
template Vector3 Material::GetValue<Vector3>(const string&) const;
template Vector4 Material::GetValue<Vector4>(const string&) const;
template Matrix4x4 Material::GetValue<Matrix4x4>(const string&) const;
template Color Material::GetValue<Color>(const string&) const;
template string Material::GetValue<string>(const string&) const;
template ITexture* Material::GetValue<ITexture*>(const string&) const;
} // namespace TSE

View File

@@ -0,0 +1,65 @@
#pragma once
#include "uuid.h"
#include "interfaces/IShader.hpp"
#include <unordered_map>
#include <any>
#include <string>
#include <tuple>
namespace TSE
{
struct Material
{
private:
string name;
uuids::uuid id;
IShader* shader;
std::unordered_map<string, std::tuple<std::any, string, string>> values;
public:
Material();
Material(const string& name, IShader* shader);
Material(const string& name, IShader* shader, uuids::uuid id);
template<typename T>
void SetValue(const string& key, const T& value);
template<typename T>
T GetValue(const string& key) const;
template<typename T>
void SetValue(const string& key, const T* value);
bool HasValue(const string& key) const;
int GetValueCount() const;
std::tuple<std::any, string, string>& GetValueAt(int i);
string& GetName();
IShader* GetShader() const;
void SetShader(IShader* shader);
uuids::uuid GetID() const;
};
template<typename T>
void Material::SetValue(const string& key, const T& value) {
values[key] = std::make_tuple(value, typeid(T).name(), key);
}
template<typename T>
T Material::GetValue(const string& key) const {
auto it = values.find(key);
if (it == values.end()) {
throw std::runtime_error("Material::GetValue - key '" + key + "' not found");
}
auto [a,b,c] = it->second;
return std::any_cast<T>(a);
}
template<typename T>
void Material::SetValue(const string& key, const T* value) {
values[key] = std::make_tuple(value, typeid(T).name(), key);
}
} // namespace TSE

View File

@@ -0,0 +1,469 @@
#include "Transformable.hpp"
#include "IdGenerator.hpp"
#include "MathF.hpp"
#include "BehaviourScript.hpp"
#include "Layer.hpp"
#include "Debug.hpp"
namespace TSE
{
Transformable::Transformable()
: position(0, 0, 0), scale(1, 1, 1), rotation(), name("")
{
id = GenerateRandomUUID();
objectEntries[id] = this;
}
Transformable::Transformable(uuids::uuid id)
: id(id), position(0, 0, 0), scale(1, 1, 1), rotation(), name("")
{
objectEntries[id] = this;
}
Transformable::Transformable(const string &name)
: position(0, 0, 0), scale(1, 1, 1), rotation(), name(name)
{
id = GenerateRandomUUID();
objectEntries[id] = this;
}
Transformable::Transformable(const string &name, uuids::uuid id)
: id(id), position(0, 0, 0), scale(1, 1, 1), rotation(), name(name)
{
objectEntries[id] = this;
}
Vector3 Transformable::forward() const
{
return Vector3::Normalize(GetGlobalMatrix() * Vector3::forward - GetGlobalMatrix() * Vector3::zero);
}
Vector3 Transformable::right() const
{
return Vector3::Normalize(GetGlobalMatrix() * Vector3::right - GetGlobalMatrix() * Vector3::zero);
}
Vector3 Transformable::up() const
{
return Vector3::Normalize(GetGlobalMatrix() * Vector3::up - GetGlobalMatrix() * Vector3::zero);
}
Vector3 Transformable::GetPosition() const
{
return position;
}
void Transformable::SetPosition(const Vector3 &pos)
{
position = pos;
}
Quaternion Transformable::GetRotation() const
{
return rotation;
}
void Transformable::SetRotation(const Quaternion &rot)
{
rotation = rot;
}
Vector3 Transformable::GetScale() const
{
return scale;
}
void Transformable::SetScale(const Vector3 &s)
{
scale = s;
}
string Transformable::GetName() const
{
return name;
}
uuids::uuid Transformable::GetId() const
{
return id;
}
Vector3 Transformable::GetEuler()
{
return rotation.ToEulerAngles();
}
void Transformable::SetEuler(const Vector3 &euler)
{
rotation = Quaternion::FromEulerAngles(euler);
}
int Transformable::GetComponentCount()
{
return components.size();
}
Matrix4x4 Transformable::GetLocalMatrix() const
{
return Matrix4x4::ToTranslationMatrix(position) * Matrix4x4::ToRotationMatrix(rotation) * Matrix4x4::ToScaleMatrix(scale);;
}
Matrix4x4 Transformable::GetGlobalMatrix() const
{
if (parent != nullptr)
return parent->GetGlobalMatrix() * GetLocalMatrix();
return GetLocalMatrix();
}
Vector3 Transformable::GetGlobalPosition() const
{
return LocalToGlobalPosition(Vector3::zero);
}
Vector3 Transformable::GlobalToLocalPosition(const Vector3& global) const
{
Matrix4x4 globalMatrix = GetGlobalMatrix();
if(globalMatrix.IsAffine())
{
globalMatrix.InvertAffine();
}
else
{
globalMatrix.Invert();
}
return globalMatrix * global;
}
Vector3 Transformable::LocalToGlobalPosition(const Vector3& local) const
{
return GetGlobalMatrix() * local;
}
void Transformable::LookAt_2D(const Vector3& globalTarget)
{
Vector3 to = globalTarget - GetGlobalPosition();
Vector3 toXY = {to.x, to.y, 0.0f};
if(Vector3::Dot(toXY, toXY) < TSE_EPSILON) return;
toXY.Normalize();
Vector3 fwdWorld = rotation.Rotate(Vector3::up);
Vector3 fwdXY = Vector3(fwdWorld.x, fwdWorld.y, 0);
fwdXY.Normalize();
float cosA = std::clamp(Vector3::Dot(fwdXY, toXY), -1.0f, 1.0f);
float sinA = fwdXY.x * toXY.y - fwdXY.y * toXY.x;
float angle = atan2(sinA, cosA);
Quaternion twist = Quaternion::FromAngleAxis(angle, Vector3::forward);
rotation = twist * rotation;
}
void Transformable::SetParent(Transformable *p)
{
Transformable* t(this);
if (parent != nullptr && parent != p) {
auto it = parent->children.begin();
for (int i = 0; i < parent->children.size(); i++)
{
if(**it == *t)
{
parent->children.erase(it);
break;
}
it++;
}
}
if (p != nullptr && p != parent) {
p->children.push_back(t);
}
parent = p;
}
Transformable *Transformable::GetParent() const
{
return parent;
}
const std::vector<Transformable *> &Transformable::GetChildren() const
{
return children;
}
bool Transformable::IsMyChild(Transformable *other)
{
for (auto child : children)
{
if(child->id == other->id)
{
return true;
}
else if(child->IsMyChild(other))
{
return true;
}
}
return false;
}
void Transformable::MoveUp(Layer *l)
{
if(l != nullptr)
{
auto it = l->GetAllObjects().begin();
for(int i = 0; i < l->GetAllObjects().size(); i++)
{
if((*it)->id == id)
{
if(i == 0) return;
std::swap(l->GetAllObjects()[i - 1], l->GetAllObjects()[i]);
}
it++;
}
return;
}
auto it = parent->children.begin();
for(int i = 0; i < parent->children.size(); i++)
{
if((*it)->id == id)
{
if(i == 0) return;
std::swap(parent->children[i - 1], parent->children[i]);
}
it++;
}
}
void Transformable::MoveDown(Layer *l)
{
if(l != nullptr)
{
auto it = l->GetAllObjects().begin();
for(int i = 0; i < l->GetAllObjects().size(); i++)
{
if((*it)->id == id)
{
if(i == l->GetAllObjects().size() - 1) return;
std::swap(l->GetAllObjects()[i + 1], l->GetAllObjects()[i]);
}
it++;
}
return;
}
auto it = parent->children.begin();
for(int i = 0; i < parent->children.size(); i++)
{
if((*it)->id == id)
{
if(i == parent->children.size() - 1) return;
std::swap(parent->children[i + 1], parent->children[i]);
}
it++;
}
}
bool Transformable::IsEnabled() const
{
return _enabled;
}
void Transformable::SetEnabled(bool v)
{
if (_enabled != v) {
_enabled = v;
if (_enabled) OnEnable();
else OnDisable();
}
}
BehaviourScript *Transformable::AddBehaviourScript(BehaviourScript *script)
{
if (!script) return nullptr;
const std::string key = typeid(*script).name();
components.emplace(key, script);
script->SetBaseObject(this);
script->Start();
return script;
}
BehaviourScript *Transformable::GetBehaviourScript(const string &name) const
{
auto it = components.find(name);
return (it != components.end()) ? it->second : nullptr;
}
BehaviourScript *Transformable::GetBehaviourScriptAt(const int i) const
{
auto it = components.begin();
for (int j = 0; j < i; j++)
{
it++;
}
return (*it).second;
}
std::vector<BehaviourScript *> Transformable::GetAllBehaviourScripts(const string &name) const
{
std::vector<BehaviourScript *> res;
auto it = components.begin();
while(it != components.end())
{
if((*it).first == name)
{
res.push_back((*it).second);
}
}
return res;
}
void Transformable::RemoveBehaviourScript(BehaviourScript *script)
{
for (auto it = components.begin(); it != components.end(); ++it) {
if (it->second == script) {
components.erase(it);
break;
}
}
}
bool Transformable::HasBehaviourScript(const string &name) const
{
auto it = components.find(name);
return it != components.end();
}
void Transformable::Update()
{
for (auto& [name, script] : components) {
if (script && script->IsEnabled()) script->OnUpdate();
}
for (auto child : children)
{
child->Update();
}
}
void Transformable::Delete(Transformable *t)
{
objectEntries.erase(t->id);
delete t;
}
void Transformable::Delete(const uuids::uuid id)
{
if(!Exists(id)) return;
Transformable* t = objectEntries.at(id);
objectEntries.erase(id);
delete t;
}
void Transformable::HardDelete(Transformable *t, bool onlyThis)
{
//deleting children
if(!onlyThis)
for(auto child : t->children)
{
HardDelete(child);
}
//deleting atteched scripts
for (auto& [_, script] : t->components)
delete script;
//deleting self
Delete(t);
}
void Transformable::HardDelete(const uuids::uuid id, bool onlyThis)
{
if(!Exists(id)) return;
Transformable* t = objectEntries.at(id);
//deleting children
if(!onlyThis)
for(auto child : t->children)
{
HardDelete(child);
}
//deleting atteched scripts
for (auto& [_, script] : t->components)
delete script;
//deleting self
Delete(t);
}
void Transformable::DeleteAll()
{
auto it = objectEntries.begin();
for(int i = 0; i < objectEntries.size(); i++)
{
delete it->second;
it++;
}
objectEntries.clear();
}
bool Transformable::Exists(const uuids::uuid id)
{
auto it = objectEntries.find(id);
return it != objectEntries.end();
}
bool Transformable::operator==(const Transformable &other) const
{
return other.id == id;
}
bool Transformable::operator!=(const Transformable &other) const
{
return other.id != id;
}
void Transformable::OnEnable()
{
for (auto& [_, script] : components)
if (script && script->IsEnabled()) script->OnEnable();
}
void Transformable::OnDisable()
{
for (auto& [_, script] : components)
if (script && script->IsEnabled()) script->OnDisable();
}
int Transformable::GetTansformableCount()
{
return objectEntries.size();
}
Transformable *Transformable::Find(string name)
{
for(auto obj : objectEntries)
{
if(obj.second->name == name)
{
return obj.second;
}
}
return nullptr;
}
Transformable *Transformable::Find(uuids::uuid id)
{
for(auto obj : objectEntries)
{
if(obj.second->id == id)
{
return obj.second;
}
}
return nullptr;
}
} // namespace TSE

View File

@@ -0,0 +1,106 @@
#pragma once
#include "Vector3.hpp"
#include "Quaternion.hpp"
#include "Matrix4x4.hpp"
#include "uuid.h"
#include "Types.hpp"
#include <list>
#include <string>
#include <unordered_map>
namespace TSE
{
class BehaviourScript;
class Layer;
class Transformable
{
public:
Vector3 position;
Vector3 scale;
Quaternion rotation;
string name;
bool _enabled = true;
uuids::uuid id;
private:
std::unordered_multimap<string, BehaviourScript*> components;
std::vector<Transformable*> children;
Transformable* parent = nullptr;
static std::unordered_map<uuids::uuid, Transformable*> objectEntries;
public:
Transformable();
Transformable(uuids::uuid id);
Transformable(const string& name);
Transformable(const string& name, uuids::uuid id);
~Transformable() = default;
Vector3 forward() const;
Vector3 right() const;
Vector3 up() const;
Vector3 GetPosition() const;
void SetPosition(const Vector3& pos);
Quaternion GetRotation() const;
void SetRotation(const Quaternion& rot);
Vector3 GetScale() const;
void SetScale(const Vector3& scale);
string GetName() const;
uuids::uuid GetId() const;
Vector3 GetEuler();
void SetEuler(const Vector3& euler);
int GetComponentCount();
Matrix4x4 GetLocalMatrix() const;
Matrix4x4 GetGlobalMatrix() const;
Vector3 GetGlobalPosition() const;
Vector3 GlobalToLocalPosition(const Vector3& global) const;
Vector3 LocalToGlobalPosition(const Vector3& local) const;
void LookAt_2D(const Vector3& globalTarget);
void SetParent(Transformable* parent);
Transformable* GetParent() const;
const std::vector<Transformable*>& GetChildren() const;
bool IsMyChild(Transformable* other);
void MoveUp(Layer* l = nullptr);
void MoveDown(Layer* l = nullptr);
bool IsEnabled() const;
void SetEnabled(bool v);
BehaviourScript* AddBehaviourScript(BehaviourScript* script);
BehaviourScript* GetBehaviourScript(const string& name) const;
BehaviourScript* GetBehaviourScriptAt(const int i) const;
std::vector<BehaviourScript*> GetAllBehaviourScripts(const string& name) const;
void RemoveBehaviourScript(BehaviourScript* script);
bool HasBehaviourScript(const string& name) const;
void Update();
static void Delete(Transformable* t);
static void Delete(const uuids::uuid id);
static void HardDelete(Transformable* t, bool onlyThis = false);
static void HardDelete(const uuids::uuid id, bool onlyThis = false);
static void DeleteAll();
static bool Exists(const uuids::uuid id);
bool operator==(const Transformable& other) const;
bool operator!=(const Transformable& other) const;
private:
void OnEnable();
void OnDisable();
public:
static int GetTansformableCount();
static Transformable* Find(string name);
static Transformable* Find(uuids::uuid id);
};
}