9.22 routine backup

This commit is contained in:
Isuru Samarathunga
2025-09-22 15:19:25 +05:30
parent 6a6debb0db
commit 28ca737c21
25 changed files with 585 additions and 140 deletions

View File

@ -27,6 +27,7 @@
"regex": "cpp", "regex": "cpp",
"system_error": "cpp", "system_error": "cpp",
"xlocmon": "cpp", "xlocmon": "cpp",
"xiosbase": "cpp" "xiosbase": "cpp",
"map": "cpp"
} }
} }

View File

@ -8,4 +8,4 @@ add_executable(IAESandbox ${IAESandbox_Sources})
target_include_directories(IAESandbox PRIVATE imp/hpp) target_include_directories(IAESandbox PRIVATE imp/hpp)
target_link_libraries(IAESandbox PRIVATE IAEngine RmlUi::RmlUi) target_link_libraries(IAESandbox PRIVATE IAEngine)

View File

@ -2,6 +2,8 @@
#include <IAEngine/Input.hpp> #include <IAEngine/Input.hpp>
#include <IAEngine/Rendering/Camera.hpp> #include <IAEngine/Rendering/Camera.hpp>
#include <IAEngine/Components/PhysicsBody2D.hpp>
#include <IAEngine/Components/BoxCollider2D.hpp>
#include <IAEngine/Components/SpriteRenderer.hpp> #include <IAEngine/Components/SpriteRenderer.hpp>
#include <IACore/File.hpp> #include <IACore/File.hpp>
@ -11,12 +13,12 @@ namespace ia::iae::game
RefPtr<Scene> scene; RefPtr<Scene> scene;
RefPtr<Node> g_player; RefPtr<Node> g_player;
PhysicsBody2DComponent* g_playerPhysicsBody{};
VOID Game::Initialize() VOID Game::Initialize()
{ {
scene = Engine::CreateScene(); scene = Engine::CreateScene();
scene->YSortingEnabled() = true; scene->YSortingEnabled() = true;
Engine::ChangeScene(scene.get());
g_player = MakeRefPtr<Node>(); g_player = MakeRefPtr<Node>();
{ {
@ -32,6 +34,19 @@ namespace ia::iae::game
}); });
t->BakeAnimations(); t->BakeAnimations();
} }
{
g_playerPhysicsBody = g_player->AddComponent<PhysicsBody2DComponent>();
g_playerPhysicsBody->IsDynamic() = true;
const auto collider = g_player->AddComponent<BoxCollider2DComponent>();
collider->Rect() = {
0,
0,
g_player->DrawnSize().x,
g_player->DrawnSize().y/2.0f,
};
collider->IsDebugDrawEnabled() = true;
}
g_player->Tags() = NODE_TAG_PLAYER;
g_player->SetLocalPosition({200, 200}); g_player->SetLocalPosition({200, 200});
const auto obstacle = MakeRefPtr<Node>(); const auto obstacle = MakeRefPtr<Node>();
@ -41,18 +56,31 @@ namespace ia::iae::game
.ShouldLoop = true, .ShouldLoop = true,
.Keys = { .Keys = {
SpriteRendererComponent::AnimationKeyFrame { SpriteRendererComponent::AnimationKeyFrame {
.Scale = {0.5f, 0.5f}, .Scale = {3.0f, 0.5f},
.ColorOverlay = {0.75f, 0.0f, 0.0f, 1.0f} .ColorOverlay = {0.75f, 0.0f, 0.0f, 1.0f}
} }
}, },
}); });
t->BakeAnimations(); t->BakeAnimations();
} }
{
obstacle->AddComponent<PhysicsBody2DComponent>();
const auto collider = obstacle->AddComponent<BoxCollider2DComponent>();
collider->Rect() = {
0, 0,
obstacle->DrawnSize().x,
obstacle->DrawnSize().y
};
collider->IsDebugDrawEnabled() = true;
}
obstacle->Tags() = NODE_TAG_GROUND;
obstacle->SetLocalSortIndex(20); obstacle->SetLocalSortIndex(20);
obstacle->SetLocalPosition({150, 100}); obstacle->SetLocalPosition({200, 400});
//scene->AddNode(g_player); scene->AddNode(g_player);
//scene->AddNode(obstacle); scene->AddNode(obstacle);
Engine::ChangeScene(scene.get());
} }
VOID Game::Terminate() VOID Game::Terminate()
@ -61,6 +89,8 @@ namespace ia::iae::game
VOID Game::Update() VOID Game::Update()
{ {
g_player->SetLocalPosition(g_player->GetLocalPosition() + Input::GetDirectionalInput()); if(Input::WasKeyPressed(Input::KEY_SPACE))
g_playerPhysicsBody->Jump(200.0f);
g_playerPhysicsBody->SetVelocityX(Input::GetDirectionalInput().x * 100.0f);
} }
} }

View File

@ -29,7 +29,7 @@ set(IAEngine_Sources
imp/cpp/Components/SpriteRenderer.cpp imp/cpp/Components/SpriteRenderer.cpp
imp/cpp/Components/SoundEmitter.cpp imp/cpp/Components/SoundEmitter.cpp
imp/cpp/Components/ParticleEmitter.cpp imp/cpp/Components/ParticleEmitter.cpp
imp/cpp/Components/PhysicsBody.cpp imp/cpp/Components/PhysicsBody2D.cpp
imp/cpp/Components/TextureRenderer.cpp imp/cpp/Components/TextureRenderer.cpp
) )

View File

@ -14,38 +14,45 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Nodes/Node.hpp>
#include <IAEngine/Physics/Physics.hpp>
#include <IAEngine/Components/BoxCollider2D.hpp> #include <IAEngine/Components/BoxCollider2D.hpp>
#include <IAEngine/IAEngine.hpp> #include <IAEngine/Components/PhysicsBody2D.hpp>
#include <IAEngine/Components/TextureRenderer.hpp>
#include <IACore/File.hpp> #include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/Physics/Physics.hpp>
#include <IAEngine/Nodes/Node.hpp>
namespace ia::iae namespace ia::iae
{ {
Texture g_debugBoxTexture{}; EXTERN Texture g_whiteStrokeTexture;
BoxCollider2DComponent::BoxCollider2DComponent(IN Node *node) : IComponent(node) BoxCollider2DComponent::BoxCollider2DComponent(IN Node *node) : IComponent(node)
{ {
Physics::AddCollider(this); IA_RELEASE_ASSERT(m_body = node->GetComponent<PhysicsBody2DComponent>());
g_debugBoxTexture = Engine::CreateTexture(File::ReadToVector("Resources/Engine/debug_box.png")); m_physicsHandle = Physics::AddColliderToBody(m_body->PhysicsHandle(), this);
} }
VOID BoxCollider2DComponent::Draw() VOID BoxCollider2DComponent::Draw()
{ {
//g_debugBoxTexture.Draw( if (!m_isDebugDrawEnabled)
// 0, return;
// m_node->GetPosition() + glm::vec3{m_shape.x, m_shape.y, 0}, Renderer::Draw(Renderer::GetMesh_Quad(), g_whiteStrokeTexture.GetHandle(), m_node->GetPosition() + glm::vec2{m_rect.x, m_rect.y},
// {m_shape.z/256.0f, m_shape.w/256.0f, 1}, glm::vec2{m_rect.z, m_rect.w}, 0, Renderer::MAX_LAYER_INDEX,
// m_node->GetRotation().z, false, false, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}); 0, {1.0f, 1.0f, 1.0f, 1.0f});
} }
VOID BoxCollider2DComponent::Update() VOID BoxCollider2DComponent::Update()
{ {
const auto pos = m_node->GetPosition(); }
m_absoluteShape.x = pos.x + m_shape.x;
m_absoluteShape.y = pos.y + m_shape.y; VOID BoxCollider2DComponent::OnCollisionEnter(IN Node *other)
m_absoluteShape.z = m_absoluteShape.x + m_shape.z; {
m_absoluteShape.w = m_absoluteShape.y + m_shape.w; if (other->HasTag(NODE_TAG_GROUND))
m_body->IsGrounded() = true;
}
VOID BoxCollider2DComponent::OnCollisionExit(IN Node *other)
{
if (other->HasTag(NODE_TAG_GROUND))
m_body->IsGrounded() = false;
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -1,22 +0,0 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Components/PhysicsBody.hpp>
namespace ia::iae
{
}

View File

@ -0,0 +1,66 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Components/BoxCollider2D.hpp>
#include <IAEngine/Components/PhysicsBody2D.hpp>
#include <IAEngine/Nodes/Node.hpp>
#include <IAEngine/Physics/Physics.hpp>
namespace ia::iae
{
PhysicsBody2DComponent::PhysicsBody2DComponent(IN Node *node) : IComponent(node)
{
m_physicsHandle = Physics::AddBody(this);
}
VOID PhysicsBody2DComponent::Draw()
{
}
VOID PhysicsBody2DComponent::Update()
{
if (m_isDynamic)
m_node->SetLocalPosition(Physics::GetBodyPosition(m_physicsHandle));
if (!m_isRotationLocked)
m_node->SetLocalRotation(Physics::GetBodyRotation(m_physicsHandle));
}
VOID PhysicsBody2DComponent::SetVelocity(IN glm::vec2 v)
{
Physics::SetBodyVelocity(m_physicsHandle, v);
}
VOID PhysicsBody2DComponent::SetVelocityX(IN FLOAT32 v)
{
Physics::SetBodyVelocityX(m_physicsHandle, v);
}
VOID PhysicsBody2DComponent::SetVelocityY(IN FLOAT32 v)
{
Physics::SetBodyVelocityY(m_physicsHandle, v);
}
VOID PhysicsBody2DComponent::ApplyForce(IN glm::vec2 force)
{
Physics::ApplyBodyForce(m_physicsHandle, force);
}
VOID PhysicsBody2DComponent::Jump(IN FLOAT32 velocity)
{
if(m_isGrounded)
Physics::SetBodyVelocityY(m_physicsHandle, -velocity);
}
} // namespace ia::iae

View File

@ -60,6 +60,9 @@ namespace ia::iae
m_currentAnimationState = m_prevAnimationKeyFrame; m_currentAnimationState = m_prevAnimationKeyFrame;
m_activeAnimationHandle = animation; m_activeAnimationHandle = animation;
CurrentTexture() = m_currentAnimationState.Texture;
m_node->DrawnSize() = m_node->GetScale() * m_currentAnimationState.Texture.GetExtent() * m_currentAnimationState.Scale;
} }
VOID SpriteRendererComponent::Update() VOID SpriteRendererComponent::Update()

View File

@ -31,13 +31,27 @@ namespace ia::iae
VOID TextureRendererComponent::Draw() VOID TextureRendererComponent::Draw()
{ {
m_node->DrawnSize() = m_node->GetScale() * m_texture.GetExtent() * m_scaleOffset;
Renderer::SetState_FlippedH(m_isFlippedH); Renderer::SetState_FlippedH(m_isFlippedH);
Renderer::SetState_FlippedV(m_isFlippedV); Renderer::SetState_FlippedV(m_isFlippedV);
Renderer::SetState_CameraRelative(m_isCameraRelative); Renderer::SetState_CameraRelative(m_isCameraRelative);
Renderer::SetState_TextureOffset(m_textureOffset.x, m_textureOffset.y); Renderer::SetState_TextureOffset(m_textureOffset.x, m_textureOffset.y);
if (m_shouldDrawOutline)
{
const auto outlineFactor = 1.2f;
Renderer::Draw(Renderer::GetMesh_Quad(), m_texture.GetHandle(),
m_node->GetPosition() + m_positionOffset -
glm::vec2{m_node->DrawnSize().x * (outlineFactor - 1.0f) / 2.0f,
m_node->DrawnSize().y * (outlineFactor - 1.0f) / 2.0f},
m_node->DrawnSize() * glm::vec2{outlineFactor, outlineFactor},
m_node->GetRotation() + m_rotationOffset, m_node->LayerIndex(), m_node->GetSortIndex(),
m_outlineColor);
}
Renderer::Draw(Renderer::GetMesh_Quad(), m_texture.GetHandle(), m_node->GetPosition() + m_positionOffset, Renderer::Draw(Renderer::GetMesh_Quad(), m_texture.GetHandle(), m_node->GetPosition() + m_positionOffset,
m_node->GetScale() * m_texture.GetExtent() * m_scaleOffset, m_node->GetRotation() + m_rotationOffset, m_node->LayerIndex(), m_node->DrawnSize(), m_node->GetRotation() + m_rotationOffset, m_node->LayerIndex(),
m_node->GetSortIndex(), m_colorOverlay); m_node->GetSortIndex(), m_colorOverlay);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -147,7 +147,10 @@ namespace ia::iae
VOID Engine::ChangeScene(IN Scene *scene) VOID Engine::ChangeScene(IN Scene *scene)
{ {
if(g_activeScene)
g_activeScene->OnDeactivate();
g_activeScene = scene; g_activeScene = scene;
g_activeScene->OnActivate();
} }
Scene *Engine::GetActiveScene() Scene *Engine::GetActiveScene()

View File

@ -56,6 +56,7 @@ namespace ia::iae
VOID Input::OnEvent(IN PVOID _event) VOID Input::OnEvent(IN PVOID _event)
{ {
memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys));
const auto event = (SDL_Event *) _event; const auto event = (SDL_Event *) _event;
if (event->type == SDL_EVENT_KEY_DOWN) if (event->type == SDL_EVENT_KEY_DOWN)
{ {
@ -65,7 +66,6 @@ namespace ia::iae
{ {
s_keys[event->key.scancode] = false; s_keys[event->key.scancode] = false;
} }
memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys));
} }
glm::vec2 Input::GetDirectionalInput() glm::vec2 Input::GetDirectionalInput()

View File

@ -14,56 +14,174 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp>
#include <IAEngine/Physics/Physics.hpp> #include <IAEngine/Physics/Physics.hpp>
#include <IAEngine/Nodes/Node.hpp> #include <IAEngine/Nodes/Node.hpp>
#include <box2d/box2d.h>
#include <map>
namespace ia::iae namespace ia::iae
{ {
Vector<BoxCollider2DComponent *> g_colliders; struct Body
{
struct Collider
{
b2ShapeId ShapeId{};
BoxCollider2DComponent *ColliderComponent{};
};
b2BodyId BodyId{.world0 = 0xFFFF};
PhysicsBody2DComponent *BodyComponent;
Vector<Collider> Colliders;
};
b2WorldId g_worldId{};
Vector<Body> g_bodies;
std::map<Handle, BoxCollider2DComponent*> g_shapeColliders;
INLINE Handle ShapeIdToHandle(IN b2ShapeId id)
{
return *reinterpret_cast<Handle*>(&id.index1);
}
VOID Physics::Initialize() VOID Physics::Initialize()
{ {
auto worldDef = b2DefaultWorldDef();
worldDef.gravity = b2Vec2{0.0f, 1000.0f};
g_worldId = b2CreateWorld(&worldDef);
} }
VOID Physics::Terminate() VOID Physics::Terminate()
{ {
} b2DestroyWorld(g_worldId);
INLINE BOOL IsIntersectingH(IN CONST glm::vec4 &shape, IN FLOAT32 x)
{
return (x >= shape.x) && (x <= shape.z);
}
INLINE BOOL IsIntersectingV(IN CONST glm::vec4 &shape, IN FLOAT32 y)
{
return (y >= shape.y) && (y <= shape.w);
} }
VOID Physics::Update() VOID Physics::Update()
{ {
for (SIZE_T i = 0; i < g_colliders.size(); i++) CONSTEXPR FLOAT32 TIME_STEP = 1.0f / 60.0f;
{ CONSTEXPR INT32 SUB_STEP_COUNT = 4;
for (SIZE_T j = i + 1; j < g_colliders.size(); j++) b2World_Step(g_worldId, TIME_STEP, SUB_STEP_COUNT);
{
const auto boxA = g_colliders[i]->AbsoluteShape();
const auto boxB = g_colliders[j]->AbsoluteShape();
const auto nodeA = g_colliders[i]->GetNode();
if(IsIntersectingH(boxB, boxA.z) && (IsIntersectingV(boxB, boxA.y) || IsIntersectingV(boxB, boxA.w))) // Process contact events
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(-boxA.z + boxB.x, 0)); const auto contactEvents = b2World_GetContactEvents(g_worldId);
else if(IsIntersectingH(boxB, boxA.x) && (IsIntersectingV(boxB, boxA.y) || IsIntersectingV(boxB, boxA.w))) for(INT32 i = 0; i < contactEvents.beginCount; i++)
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(-boxA.x + boxB.z, 0)); {
else if(IsIntersectingV(boxB, boxA.w) && (IsIntersectingH(boxB, boxA.x) || IsIntersectingH(boxB, boxA.z))) const auto& shapeA = g_shapeColliders[ShapeIdToHandle(contactEvents.beginEvents[i].shapeIdA)];
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(0, -boxA.w + boxB.y)); const auto& shapeB = g_shapeColliders[ShapeIdToHandle(contactEvents.beginEvents[i].shapeIdB)];
else if(IsIntersectingV(boxB, boxA.y) && (IsIntersectingH(boxB, boxA.x) || IsIntersectingH(boxB, boxA.z))) shapeA->OnCollisionEnter(shapeB->GetNode());
nodeA->SetLocalPosition(nodeA->GetLocalPosition() + glm::vec2(0, -boxA.y + boxB.w)); shapeB->OnCollisionEnter(shapeA->GetNode());
}
for(INT32 i = 0; i < contactEvents.endCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(contactEvents.endEvents[i].shapeIdA)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(contactEvents.endEvents[i].shapeIdB)];
shapeA->OnCollisionExit(shapeB->GetNode());
shapeB->OnCollisionExit(shapeA->GetNode());
}
// Process sensor events
const auto sensorEvents = b2World_GetSensorEvents(g_worldId);
for(INT32 i = 0; i < sensorEvents.beginCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(sensorEvents.beginEvents[i].sensorShapeId)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(sensorEvents.beginEvents[i].visitorShapeId)];
shapeA->OnCollisionEnter(shapeB->GetNode());
shapeB->OnCollisionEnter(shapeA->GetNode());
}
for(INT32 i = 0; i < sensorEvents.endCount; i++)
{
const auto& shapeA = g_shapeColliders[ShapeIdToHandle(sensorEvents.endEvents[i].sensorShapeId)];
const auto& shapeB = g_shapeColliders[ShapeIdToHandle(sensorEvents.endEvents[i].visitorShapeId)];
shapeA->OnCollisionExit(shapeB->GetNode());
shapeB->OnCollisionExit(shapeA->GetNode());
}
}
VOID Physics::Bake()
{
for (auto &b : g_bodies)
{
const auto pos = b.BodyComponent->GetNode()->GetPosition();
auto bodyDef = b2DefaultBodyDef();
if (b.BodyComponent->IsDynamic())
bodyDef.type = b2_dynamicBody;
bodyDef.position = b2Vec2{pos.x, pos.y};
if (b.BodyId.world0 != 0xFFFF)
b2DestroyBody(b.BodyId);
b.BodyId = b2CreateBody(g_worldId, &bodyDef);
for (auto &c : b.Colliders)
{
const auto rect = c.ColliderComponent->Rect();
const auto halfW = rect.z/2.0f;
const auto halfH = rect.w/2.0f;
const auto box = b2MakeOffsetBox(halfW, halfH, {rect.x, rect.y - halfH/2.0f}, b2MakeRot(0));
auto boxShapeDef = b2DefaultShapeDef();
boxShapeDef.density = 1.0f;
boxShapeDef.isSensor = c.ColliderComponent->IsTrigger();
boxShapeDef.enableContactEvents = c.ColliderComponent->CollisionsEnabled();
boxShapeDef.enableSensorEvents = boxShapeDef.enableContactEvents;
c.ShapeId = b2CreatePolygonShape(b.BodyId, &boxShapeDef, &box);
g_shapeColliders[ShapeIdToHandle(c.ShapeId)] = c.ColliderComponent;
} }
} }
} }
VOID Physics::AddCollider(IN BoxCollider2DComponent *collider) Handle Physics::AddBody(IN PhysicsBody2DComponent *body)
{ {
g_colliders.pushBack(collider); g_bodies.pushBack(Body{
.BodyComponent = body,
});
return g_bodies.size() - 1;
}
Handle Physics::AddColliderToBody(IN Handle bodyHandle, IN BoxCollider2DComponent *collider)
{
auto &b = g_bodies[bodyHandle];
b.Colliders.pushBack(Body::Collider{
.ColliderComponent = collider,
});
return b.Colliders.size() - 1;
}
FLOAT32 Physics::GetBodyRotation(IN Handle handle)
{
const auto &b = g_bodies[handle];
return acosf(b2Body_GetRotation(b.BodyId).c);
}
glm::vec2 Physics::GetBodyPosition(IN Handle handle)
{
const auto &b = g_bodies[handle];
const auto v = b2Body_GetPosition(b.BodyId);
return {v.x, v.y};
}
VOID Physics::ApplyBodyForce(IN Handle handle, IN glm::vec2 force)
{
const auto &b = g_bodies[handle];
b2Body_ApplyForce(b.BodyId, {force.x, force.y}, b2Body_GetLocalCenterOfMass(b.BodyId), true);
}
VOID Physics::SetBodyVelocity(IN Handle handle, IN glm::vec2 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {v.x, v.y});
}
VOID Physics::SetBodyVelocityX(IN Handle handle, IN FLOAT32 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {v, b2Body_GetLinearVelocity(b.BodyId).y});
}
VOID Physics::SetBodyVelocityY(IN Handle handle, IN FLOAT32 v)
{
const auto &b = g_bodies[handle];
b2Body_SetLinearVelocity(b.BodyId, {b2Body_GetLinearVelocity(b.BodyId).x, v});
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -45,7 +45,7 @@ namespace ia::iae
SDL_Rect Scissor{0, 0, 0, 0}; SDL_Rect Scissor{0, 0, 0, 0};
}; };
Vector<Mesh> g_meshes{}; Vector<Mesh*> g_meshes{};
RenderState g_renderState{}; RenderState g_renderState{};
} // namespace ia::iae } // namespace ia::iae
@ -83,7 +83,8 @@ namespace ia::iae
Handle g_meshHandleQuad{}; Handle g_meshHandleQuad{};
RefPtr<GPUTexture> g_whiteTexture{}; Texture g_whiteFillTexture{};
Texture g_whiteStrokeTexture{};
BOOL Renderer::Initialize() BOOL Renderer::Initialize()
{ {
@ -150,21 +151,34 @@ namespace ia::iae
g_defaultScissor.w = s_width; g_defaultScissor.w = s_width;
g_defaultScissor.h = s_height; g_defaultScissor.h = s_height;
{ // Generate default textures
constexpr auto size = 100;
constexpr auto strokeWeight = 5;
const auto data = new UINT32[size * size];
memset(data, 0, size * size * 4);
for (SIZE_T i = 0; i < size; i++)
{ {
constexpr auto l = 100; for (SIZE_T j = 0; j < strokeWeight; j++)
const auto data = new UINT32[l * l]; {
for (SIZE_T i = 0; i < l * l; i++) data[i + (size * j)] = 0xFFFFFFFF;
data[j + (size * i)] = 0xFFFFFFFF;
data[i + (size * (size - 1 - j))] = 0xFFFFFFFF;
data[(size - 1 - j) + (size * i)] = 0xFFFFFFFF;
}
}
g_whiteStrokeTexture = Engine::CreateTexture((PCUINT8) data, size, size);
for (SIZE_T i = 0; i < size * size; i++)
data[i] = 0xFFFFFFFF; data[i] = 0xFFFFFFFF;
g_whiteTexture = GPUTexture::Create((PCUINT8) data, l, l); g_whiteFillTexture = Engine::CreateTexture((PCUINT8) data, size, size);
delete[] data; delete[] data;
} }
g_meshHandleQuad = CreateMesh( g_meshHandleQuad = CreateMesh(
{ {
{glm::vec3{0, 1, 0}, glm::vec2{0, 1}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}}, {glm::vec3{-0.5, 0.5, 0}, glm::vec2{0, 1}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}},
{glm::vec3{1, 1, 0}, glm::vec2{1, 1}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}}, {glm::vec3{0.5, 0.5, 0}, glm::vec2{1, 1}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}},
{glm::vec3{1, 0, 0}, glm::vec2{1, 0}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}}, {glm::vec3{0.5, -0.5, 0}, glm::vec2{1, 0}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}},
{glm::vec3{0, 0, 0}, glm::vec2{0, 0}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}}, {glm::vec3{-0.5, -0.5, 0}, glm::vec2{0, 0}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}},
}, },
{0, 1, 2, 2, 3, 0}); {0, 1, 2, 2, 3, 0});
@ -177,14 +191,13 @@ namespace ia::iae
for (auto &mesh : g_meshes) for (auto &mesh : g_meshes)
{ {
mesh.VertexBuffer.reset(); mesh->VertexBuffer.reset();
mesh.IndexBuffer.reset(); mesh->IndexBuffer.reset();
delete mesh;
} }
g_pipelineUnlitMesh.reset(); g_pipelineUnlitMesh.reset();
g_whiteTexture.reset();
GPUTexture::Terminate(); GPUTexture::Terminate();
GPUBuffer::TerminateStagingBuffer(); GPUBuffer::TerminateStagingBuffer();
@ -322,14 +335,25 @@ namespace ia::iae
Handle Renderer::CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices) Handle Renderer::CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices)
{ {
Mesh mesh{}; const auto mesh = CreateUnmanagedMesh(vertices, indices);
mesh.VertexBuffer = GPUBuffer::Create(GPUBuffer::Usage::VERTEX, vertices.data(), g_meshes.pushBack((Mesh*)mesh);
return mesh;
}
Handle Renderer::CreateUnmanagedMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices)
{
const auto mesh = new Mesh();
mesh->VertexBuffer = GPUBuffer::Create(GPUBuffer::Usage::VERTEX, vertices.data(),
static_cast<UINT32>(vertices.size() * sizeof(vertices[0]))); static_cast<UINT32>(vertices.size() * sizeof(vertices[0])));
mesh.IndexBuffer = GPUBuffer::Create(GPUBuffer::Usage::INDEX, indices.data(), mesh->IndexBuffer = GPUBuffer::Create(GPUBuffer::Usage::INDEX, indices.data(),
static_cast<UINT32>(indices.size() * sizeof(indices[0]))); static_cast<UINT32>(indices.size() * sizeof(indices[0])));
mesh.IndexCount = static_cast<UINT32>(indices.size()); mesh->IndexCount = static_cast<UINT32>(indices.size());
g_meshes.pushBack(mesh); return (Handle)mesh;
return static_cast<Handle>(g_meshes.size() - 1); }
VOID Renderer::DestroyUnmanagedMesh(IN Handle handle)
{
delete ((Mesh*)handle);
} }
VOID Renderer::Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position, VOID Renderer::Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position,
@ -368,7 +392,7 @@ namespace ia::iae
s_fragmentUniform.FlippedV = g_renderState.FlippedV; s_fragmentUniform.FlippedV = g_renderState.FlippedV;
s_fragmentUniform.TextureOffset = g_renderState.TextureOffset; s_fragmentUniform.TextureOffset = g_renderState.TextureOffset;
SDL_GPUTextureSamplerBinding textureBinding{ SDL_GPUTextureSamplerBinding textureBinding{
.texture = (SDL_GPUTexture *) (textureHandle ? textureHandle : g_whiteTexture->GetHandle()), .texture = (SDL_GPUTexture *) (textureHandle ? textureHandle : g_whiteFillTexture.GetHandle()),
.sampler = (SDL_GPUSampler *) GPUTexture::GetDefaultSampler()}; .sampler = (SDL_GPUSampler *) GPUTexture::GetDefaultSampler()};
SDL_BindGPUFragmentSamplers(g_renderPass, 0, &textureBinding, 1); SDL_BindGPUFragmentSamplers(g_renderPass, 0, &textureBinding, 1);
SDL_PushGPUFragmentUniformData(g_cmdBuffer, 0, &s_fragmentUniform, sizeof(s_fragmentUniform)); SDL_PushGPUFragmentUniformData(g_cmdBuffer, 0, &s_fragmentUniform, sizeof(s_fragmentUniform));
@ -378,12 +402,12 @@ namespace ia::iae
else else
SDL_SetGPUScissor(g_renderPass, &g_defaultScissor); SDL_SetGPUScissor(g_renderPass, &g_defaultScissor);
const auto &mesh = g_meshes[meshHandle]; const auto mesh = (Mesh*)meshHandle;
SDL_GPUBufferBinding bufferBindings[] = { SDL_GPUBufferBinding bufferBindings[] = {
{.buffer = (SDL_GPUBuffer *) mesh.VertexBuffer->GetHandle(), .offset = 0}, {.buffer = (SDL_GPUBuffer *) mesh->VertexBuffer->GetHandle(), .offset = 0},
{.buffer = (SDL_GPUBuffer *) mesh.IndexBuffer->GetHandle(), .offset = 0}}; {.buffer = (SDL_GPUBuffer *) mesh->IndexBuffer->GetHandle(), .offset = 0}};
SDL_BindGPUVertexBuffers(g_renderPass, 0, bufferBindings, 1); SDL_BindGPUVertexBuffers(g_renderPass, 0, bufferBindings, 1);
SDL_BindGPUIndexBuffer(g_renderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT); SDL_BindGPUIndexBuffer(g_renderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT);
SDL_DrawGPUIndexedPrimitives(g_renderPass, mesh.IndexCount, 1, 0, 0, 0); SDL_DrawGPUIndexedPrimitives(g_renderPass, mesh->IndexCount, 1, 0, 0, 0);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Scene.hpp> #include <IAEngine/Scene.hpp>
#include <IAEngine/Physics/Physics.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -24,6 +25,15 @@ namespace ia::iae
n.reset(); n.reset();
} }
VOID Scene::OnActivate()
{
Physics::Bake();
}
VOID Scene::OnDeactivate()
{
}
VOID Scene::Draw() VOID Scene::Draw()
{ {
for (auto &n : m_nodes) for (auto &n : m_nodes)

View File

@ -24,6 +24,8 @@
#include <SDL3/SDL_events.h> #include <SDL3/SDL_events.h>
#include <IACore/File.hpp>
namespace ia::iae namespace ia::iae
{ {
class RmlUIRenderInterface : public Rml::RenderInterface class RmlUIRenderInterface : public Rml::RenderInterface

View File

@ -20,21 +20,41 @@
namespace ia::iae namespace ia::iae
{ {
class Physics;
class PhysicsBody2DComponent;
class BoxCollider2DComponent : public IComponent class BoxCollider2DComponent : public IComponent
{ {
public: public:
BoxCollider2DComponent(IN Node *node); BoxCollider2DComponent(IN Node *node);
BOOL& IsDynamic(){return m_isDynamic;} VOID OnCollisionEnter(IN Node *other);
VOID OnCollisionExit(IN Node *other);
glm::vec4& Shape() public:
BOOL &IsDebugDrawEnabled()
{ {
return m_shape; return m_isDebugDrawEnabled;
} }
CONST glm::vec4& AbsoluteShape() CONST BOOL &CollisionsEnabled()
{ {
return m_absoluteShape; return m_collisionsEnabled;
}
BOOL &IsTrigger()
{
return m_isTrigger;
}
glm::vec4 &Rect()
{
return m_rect;
}
Handle PhysicsHandle() CONST
{
return m_physicsHandle;
} }
public: public:
@ -42,8 +62,11 @@ namespace ia::iae
VOID Update(); VOID Update();
private: private:
BOOL m_isDynamic{}; glm::vec4 m_rect{};
glm::vec4 m_shape{}; BOOL m_isTrigger{false};
glm::vec4 m_absoluteShape{}; BOOL m_isDebugDrawEnabled{false};
BOOL m_collisionsEnabled{true};
Handle m_physicsHandle{INVALID_HANDLE};
PhysicsBody2DComponent *m_body{};
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -1,24 +0,0 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Components/Component.hpp>
namespace ia::iae
{
}

View File

@ -0,0 +1,66 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Components/Component.hpp>
namespace ia::iae
{
class PhysicsBody2DComponent : public IComponent
{
public:
PhysicsBody2DComponent(IN Node *node);
VOID SetVelocity(IN glm::vec2 v);
VOID SetVelocityX(IN FLOAT32 v);
VOID SetVelocityY(IN FLOAT32 v);
VOID ApplyForce(IN glm::vec2 force);
VOID Jump(IN FLOAT32 velocity);
public:
BOOL &IsGrounded()
{
return m_isGrounded;
}
BOOL &IsDynamic()
{
return m_isDynamic;
}
BOOL &IsRotationLocked()
{
return m_isRotationLocked;
}
Handle PhysicsHandle() CONST
{
return m_physicsHandle;
}
public:
VOID Draw();
VOID Update();
private:
BOOL m_isDynamic{};
BOOL m_isGrounded{};
BOOL m_isRotationLocked{};
Handle m_physicsHandle{INVALID_HANDLE};
};
} // namespace ia::iae

View File

@ -71,6 +71,16 @@ namespace ia::iae
return m_isCameraRelative; return m_isCameraRelative;
} }
BOOL& ShouldDrawOutline()
{
return m_shouldDrawOutline;
}
glm::vec4& OutlineColor()
{
return m_outlineColor;
}
public: public:
VOID Draw(); VOID Draw();
VOID Update(); VOID Update();
@ -78,6 +88,8 @@ namespace ia::iae
private: private:
BOOL m_isFlippedH{}; BOOL m_isFlippedH{};
BOOL m_isFlippedV{}; BOOL m_isFlippedV{};
BOOL m_shouldDrawOutline{};
glm::vec4 m_outlineColor{0.25f, 0.25f, 0.25f, 0.75f};
BOOL m_isCameraRelative{}; BOOL m_isCameraRelative{};
glm::vec2 m_positionOffset{}; glm::vec2 m_positionOffset{};
glm::vec2 m_scaleOffset{}; glm::vec2 m_scaleOffset{};

View File

@ -18,6 +18,7 @@
#include <IAEngine/Components/Component.hpp> #include <IAEngine/Components/Component.hpp>
#include <IAEngine/Nodes/Transform.hpp> #include <IAEngine/Nodes/Transform.hpp>
#include <IAEngine/Nodes/Tag.hpp>
#include <IAEngine/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
@ -59,10 +60,33 @@ namespace ia::iae
return m_layerIndex; return m_layerIndex;
} }
glm::vec2 &DrawnSize()
{
return m_drawnSize;
}
String &Name()
{
return m_name;
}
NodeTags& Tags()
{
return m_tags;
}
BOOL HasTag(IN NodeTags tag) CONST
{
return m_tags & tag;
}
protected: protected:
Scene *m_scene{}; Scene *m_scene{};
UINT8 m_layerIndex{}; UINT8 m_layerIndex{};
BOOL m_isEnabled{true}; BOOL m_isEnabled{true};
glm::vec2 m_drawnSize{};
String m_name;
NodeTags m_tags;
protected: protected:
Vector<RefPtr<IComponent>> m_components; Vector<RefPtr<IComponent>> m_components;

View File

@ -0,0 +1,69 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Base.hpp>
namespace ia::iae
{
using NodeTags = UINT64;
CONSTEXPR NodeTags NODE_TAG_PLAYER = (((NodeTags) 1) << 0);
CONSTEXPR NodeTags NODE_TAG_ENEMY = (((NodeTags) 1) << 1);
CONSTEXPR NodeTags NODE_TAG_GROUND = (((NodeTags) 1) << 2);
CONSTEXPR NodeTags NODE_TAG_OBSTACLE = (((NodeTags) 1) << 3);
CONSTEXPR NodeTags NODE_TAG_PICKUP = (((NodeTags) 1) << 4);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_1 = (((NodeTags) 1) << 5);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_2 = (((NodeTags) 1) << 6);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_3 = (((NodeTags) 1) << 7);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_4 = (((NodeTags) 1) << 8);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_5 = (((NodeTags) 1) << 9);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_6 = (((NodeTags) 1) << 10);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_7 = (((NodeTags) 1) << 11);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_8 = (((NodeTags) 1) << 12);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_9 = (((NodeTags) 1) << 13);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_10 = (((NodeTags) 1) << 14);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_11 = (((NodeTags) 1) << 15);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_12 = (((NodeTags) 1) << 16);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_13 = (((NodeTags) 1) << 17);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_14 = (((NodeTags) 1) << 18);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_15 = (((NodeTags) 1) << 19);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_16 = (((NodeTags) 1) << 20);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_17 = (((NodeTags) 1) << 21);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_18 = (((NodeTags) 1) << 22);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_19 = (((NodeTags) 1) << 23);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_20 = (((NodeTags) 1) << 24);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_21 = (((NodeTags) 1) << 25);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_22 = (((NodeTags) 1) << 26);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_23 = (((NodeTags) 1) << 27);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_24 = (((NodeTags) 1) << 28);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_25 = (((NodeTags) 1) << 29);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_26 = (((NodeTags) 1) << 30);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_27 = (((NodeTags) 1) << 31);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_28 = (((NodeTags) 1) << 32);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_29 = (((NodeTags) 1) << 33);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_30 = (((NodeTags) 1) << 34);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_31 = (((NodeTags) 1) << 35);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_32 = (((NodeTags) 1) << 36);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_33 = (((NodeTags) 1) << 37);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_34 = (((NodeTags) 1) << 38);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_35 = (((NodeTags) 1) << 39);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_36 = (((NodeTags) 1) << 40);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_37 = (((NodeTags) 1) << 41);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_38 = (((NodeTags) 1) << 42);
CONSTEXPR NodeTags NODE_TAG_CUSTOM_39 = (((NodeTags) 1) << 43);
} // namespace ia::iae

View File

@ -41,7 +41,7 @@ namespace ia::iae
RecalculateScale(); RecalculateScale();
} }
VOID SetLocalRotation(IN CONST glm::vec2 &v) VOID SetLocalRotation(IN FLOAT32 v)
{ {
m_local.Rotation = v; m_local.Rotation = v;
RecalculateRotation(); RecalculateRotation();

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Components/BoxCollider2D.hpp> #include <IAEngine/Components/BoxCollider2D.hpp>
#include <IAEngine/Components/PhysicsBody2D.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -26,8 +27,18 @@ namespace ia::iae
STATIC VOID Initialize(); STATIC VOID Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
STATIC VOID Bake();
STATIC VOID Update(); STATIC VOID Update();
STATIC VOID AddCollider(IN BoxCollider2DComponent* collider); STATIC Handle AddBody(IN PhysicsBody2DComponent* body);
STATIC Handle AddColliderToBody(IN Handle bodyHandle, IN BoxCollider2DComponent* collider);
STATIC FLOAT32 GetBodyRotation(IN Handle handle);
STATIC glm::vec2 GetBodyPosition(IN Handle handle);
STATIC VOID SetBodyVelocity(IN Handle handle, IN glm::vec2 v);
STATIC VOID SetBodyVelocityX(IN Handle handle, IN FLOAT32 v);
STATIC VOID SetBodyVelocityY(IN Handle handle, IN FLOAT32 v);
STATIC VOID ApplyBodyForce(IN Handle handle, IN glm::vec2 force);
}; };
} }

View File

@ -32,6 +32,9 @@ namespace ia::iae
std::function<VOID()> ContentDrawCallback{}; std::function<VOID()> ContentDrawCallback{};
}; };
public:
STATIC CONSTEXPR UINT8 MAX_LAYER_INDEX = 255;
public: public:
STATIC BOOL Initialize(); STATIC BOOL Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
@ -55,6 +58,8 @@ namespace ia::iae
STATIC Handle GetMesh_Quad(); STATIC Handle GetMesh_Quad();
STATIC Handle CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices); STATIC Handle CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices);
STATIC Handle CreateUnmanagedMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices);
STATIC VOID DestroyUnmanagedMesh(IN Handle handle);
STATIC VOID Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position, STATIC VOID Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position,
IN CONST glm::vec2 &scale, IN FLOAT32 rotation = 0, IN UINT8 layerIndex = 0, IN CONST glm::vec2 &scale, IN FLOAT32 rotation = 0, IN UINT8 layerIndex = 0,

View File

@ -25,6 +25,9 @@ namespace ia::iae
public: public:
~Scene(); ~Scene();
VOID OnActivate();
VOID OnDeactivate();
VOID Draw(); VOID Draw();
VOID Update(); VOID Update();