Compare commits
46 Commits
70d9cb3a85
...
old
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b308db058 | |||
| 6a87771d8f | |||
| f6c022f38e | |||
| 0d5c2e639e | |||
| ae20f51e9a | |||
| 9038fa54b0 | |||
| 9269306146 | |||
| b18bfe873f | |||
| 5f112f7531 | |||
| 3380eb993e | |||
| fe88538e3c | |||
| 3c5792e975 | |||
| 2bd9fb91fc | |||
| e4e6a2ed3c | |||
| ddf162b6a6 | |||
| 21d4357081 | |||
| f5693ef0fa | |||
| 1573644c51 | |||
| 3db1904ba4 | |||
| d4e0d3b3a1 | |||
| 860beab3a2 | |||
| 70bf71d2da | |||
| 0e7474d4e4 | |||
| 60c40c45a8 | |||
| afaced62d4 | |||
| 8793554994 | |||
| 28ca737c21 | |||
| 6a6debb0db | |||
| ece65b18da | |||
| 7eecf8f968 | |||
| 1c6d38781f | |||
| 05aa5b08f8 | |||
| 8809375282 | |||
| 829ca638cb | |||
| 6974a647f5 | |||
| ad869ef71d | |||
| 9ed9f83558 | |||
| 4f4f25e165 | |||
| 0c4205acbb | |||
| c6a8a8a76c | |||
| 594180c5d3 | |||
| 3687a70aba | |||
| 62edc71750 | |||
| 50f3f14c47 | |||
| 8a2baf6659 | |||
| a0b5dc2af2 |
16
.gitmodules
vendored
16
.gitmodules
vendored
@ -11,7 +11,15 @@
|
||||
path = Dependencies/IACore
|
||||
url = https://git.iasoft.dev/dev0/IACore
|
||||
branch = main
|
||||
[submodule "Dependencies/IAMath"]
|
||||
path = Dependencies/IAMath
|
||||
url = https://git.iasoft.dev/dev0/IAMath
|
||||
branch = main
|
||||
[submodule "Vendor/glm"]
|
||||
path = Vendor/glm
|
||||
url = https://github.com/g-truc/glm
|
||||
[submodule "Vendor/RmlUi"]
|
||||
path = Vendor/RmlUi
|
||||
url = https://github.com/mikke89/RmlUi
|
||||
[submodule "Vendor/box2d"]
|
||||
path = Vendor/box2d
|
||||
url = https://github.com/erincatto/box2d
|
||||
[submodule "Vendor/freetype"]
|
||||
path = Vendor/freetype
|
||||
url = https://github.com/freetype/freetype
|
||||
|
||||
33
.vscode/settings.json
vendored
Normal file
33
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"functional": "cpp",
|
||||
"array": "cpp",
|
||||
"utility": "cpp",
|
||||
"xutility": "cpp",
|
||||
"compare": "cpp",
|
||||
"memory": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"chrono": "cpp",
|
||||
"iterator": "cpp",
|
||||
"list": "cpp",
|
||||
"vector": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xtree": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"random": "cpp",
|
||||
"span": "cpp",
|
||||
"xstring": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"expected": "cpp",
|
||||
"optional": "cpp",
|
||||
"regex": "cpp",
|
||||
"system_error": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"map": "cpp"
|
||||
}
|
||||
}
|
||||
@ -9,10 +9,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
project(IAEngine)
|
||||
|
||||
add_compile_definitions("__IA_DEBUG=1")
|
||||
|
||||
add_subdirectory(Vendor/)
|
||||
|
||||
add_subdirectory(Dependencies/IACore)
|
||||
add_subdirectory(Dependencies/IAMath)
|
||||
|
||||
add_subdirectory(Src/IAEngine)
|
||||
add_subdirectory(Src/IAESandbox)
|
||||
|
||||
2
Dependencies/IACore
vendored
2
Dependencies/IACore
vendored
Submodule Dependencies/IACore updated: 0fd33d958e...8e2e118dd5
1
Dependencies/IAMath
vendored
1
Dependencies/IAMath
vendored
Submodule Dependencies/IAMath deleted from 450d6b4ecc
@ -2,9 +2,6 @@
|
||||
set(IAESandbox_Sources
|
||||
imp/cpp/Main.cpp
|
||||
imp/cpp/Game.cpp
|
||||
imp/cpp/Map.cpp
|
||||
imp/cpp/Ground.cpp
|
||||
imp/cpp/Player.cpp
|
||||
)
|
||||
|
||||
add_executable(IAESandbox ${IAESandbox_Sources})
|
||||
|
||||
@ -1,38 +1,94 @@
|
||||
#include <Game.hpp>
|
||||
#include <Player.hpp>
|
||||
#include <Ground.hpp>
|
||||
|
||||
#include <IAEngine/ResourceManager.hpp>
|
||||
#include <IAEngine/Input.hpp>
|
||||
#include <IAEngine/Rendering/Camera.hpp>
|
||||
#include <IAEngine/Rendering/DebugDraw.hpp>
|
||||
#include <IAEngine/Components/SpriteRenderer.hpp>
|
||||
#include <IAEngine/Components/Physics.hpp>
|
||||
|
||||
#include <IACore/File.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
RefPtr<iae::Scene> scene;
|
||||
RefPtr<Scene> scene;
|
||||
|
||||
ResourceManager* g_resourceManager{};
|
||||
RefPtr<Node> g_player;
|
||||
PhysicsComponent* g_playerPhysics;
|
||||
|
||||
VOID Game::Initialize()
|
||||
{
|
||||
g_resourceManager = m_engine->RegisterResourceManager<ResourceManager>();
|
||||
scene = Engine::CreateScene();
|
||||
scene->YSortingEnabled() = true;
|
||||
|
||||
scene = m_engine->CreateScene();
|
||||
m_engine->ChangeScene(scene);
|
||||
g_player = MakeRefPtr<Node>();
|
||||
{
|
||||
const auto t = g_player->AddComponent<SpriteRendererComponent>();
|
||||
t->AddAnimation({
|
||||
.ShouldLoop = true,
|
||||
.Keys = {
|
||||
SpriteRendererComponent::AnimationKeyFrame {
|
||||
.Scale = {0.25f, 0.25f},
|
||||
.ColorOverlay = {0.0f, 0.75f, 0.0f, 1.0f}
|
||||
}
|
||||
},
|
||||
});
|
||||
t->BakeAnimations();
|
||||
}
|
||||
g_playerPhysics = g_player->AddComponent<PhysicsComponent>();
|
||||
g_playerPhysics->IsDynamic() = true;
|
||||
g_playerPhysics->AddCollider({
|
||||
.IsTrigger = false,
|
||||
.Position = {
|
||||
0.0f, 0.0f,
|
||||
},
|
||||
.Size = {
|
||||
25.0f, 25.0f
|
||||
}
|
||||
});
|
||||
g_player->Tags() = NODE_TAG_PLAYER;
|
||||
g_player->SetLocalPosition({200, 300});
|
||||
|
||||
const auto player = MakeRefPtr<Player>(m_engine);
|
||||
player->SetLocalPosition({100.0f, 200.0f, 0.0f});
|
||||
scene->AddNode(player);
|
||||
const auto obstacle = MakeRefPtr<Node>();
|
||||
{
|
||||
const auto t = obstacle->AddComponent<SpriteRendererComponent>();
|
||||
t->AddAnimation({
|
||||
.ShouldLoop = true,
|
||||
.Keys = {
|
||||
SpriteRendererComponent::AnimationKeyFrame {
|
||||
.Scale = {1.0f, 0.5f},
|
||||
.ColorOverlay = {0.75f, 0.0f, 0.0f, 1.0f}
|
||||
}
|
||||
},
|
||||
});
|
||||
t->BakeAnimations();
|
||||
}
|
||||
const auto obstaclePhysics = obstacle->AddComponent<PhysicsComponent>();
|
||||
obstaclePhysics->AddCollider({
|
||||
.IsTrigger = false,
|
||||
.Position = {
|
||||
0.0f, 0.0f,
|
||||
},
|
||||
.Size = {
|
||||
100.0f, 50.0f
|
||||
}
|
||||
});
|
||||
obstacle->Tags() = NODE_TAG_GROUND;
|
||||
obstacle->SetLocalSortIndex(20);
|
||||
obstacle->SetLocalPosition({200, 400});
|
||||
|
||||
const auto ground = MakeRefPtr<Ground>(m_engine);
|
||||
ground->SetLocalPosition({50.0f, 500.0f, 0.0f});
|
||||
scene->AddNode(ground);
|
||||
scene->AddNode(g_player);
|
||||
scene->AddNode(obstacle);
|
||||
|
||||
Engine::ChangeScene(scene.get());
|
||||
}
|
||||
|
||||
VOID Game::Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID Game::Update()
|
||||
{
|
||||
|
||||
const auto d = Input::GetDirectionalInput();
|
||||
g_playerPhysics->Move(d);
|
||||
}
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
#include <Ground.hpp>
|
||||
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
|
||||
#include <IACore/File.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
extern ResourceManager* g_resourceManager;
|
||||
|
||||
Handle m_id2;
|
||||
|
||||
Ground::Ground(IN Engine *engine) : m_engine(engine)
|
||||
{
|
||||
m_spriteRenderer = AddComponent<SpriteRendererComponent>();
|
||||
}
|
||||
|
||||
VOID Ground::OnAdded(IN Scene *scene)
|
||||
{
|
||||
Node::OnAdded(scene);
|
||||
|
||||
iae::SpriteRendererComponent::AnimationKeyFrame keyFrame{};
|
||||
const auto d = File::ReadToVector("Graphics/red.png");
|
||||
keyFrame.Texture = g_resourceManager->CreateTexture(d.data(), d.size());
|
||||
keyFrame.Scale = {3.0f, 0.25f, 1.0f};
|
||||
|
||||
m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}});
|
||||
m_spriteRenderer->BakeAnimations();
|
||||
|
||||
m_id2 = Physics::CreateStaticBody({GetPosition().X + 300, GetPosition().Y + 25});
|
||||
Physics::AddBoxCollider(m_id2, {600.0f, 50.0f});
|
||||
}
|
||||
|
||||
VOID Ground::OnRemoved()
|
||||
{
|
||||
|
||||
Node::OnRemoved();
|
||||
}
|
||||
|
||||
VOID Ground::Draw()
|
||||
{
|
||||
Node::Draw();
|
||||
}
|
||||
|
||||
VOID Ground::Update()
|
||||
{
|
||||
Node::Update();
|
||||
}
|
||||
} // namespace ia::iae::game
|
||||
@ -1,20 +1,18 @@
|
||||
#include <Game.hpp>
|
||||
|
||||
ia::iae::Engine g_engine;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_engine.Initialize({.GameName = "IAE Sandbox", .WindowWidth = 800, .WindowHeight = 600});
|
||||
const auto game = new ia::iae::game::Game(&g_engine);
|
||||
ia::iae::Engine::Initialize({.GameName = "IAE Sandbox", .WindowWidth = 800, .WindowHeight = 600});
|
||||
const auto game = new ia::iae::game::Game();
|
||||
game->Initialize();
|
||||
while (!g_engine.ShouldClose())
|
||||
while (!ia::iae::Engine::ShouldClose())
|
||||
{
|
||||
g_engine.BeginFrame();
|
||||
ia::iae::Engine::BeginFrame();
|
||||
game->Update();
|
||||
g_engine.EndFrame();
|
||||
ia::iae::Engine::EndFrame();
|
||||
}
|
||||
game->Terminate();
|
||||
delete game;
|
||||
g_engine.Terminate();
|
||||
ia::iae::Engine::Terminate();
|
||||
return 0;
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
#include <Map.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
TiledMap::TiledMap(IN Engine *engine) : m_engine(engine)
|
||||
{
|
||||
//m_musicEmitter = AddComponent<SoundEmitterComponent>();
|
||||
//m_atlasRenderer = AddComponent<AtlasRendererComponent>();
|
||||
}
|
||||
|
||||
VOID TiledMap::OnAdded(IN Scene *scene)
|
||||
{
|
||||
Node::OnAdded(scene);
|
||||
}
|
||||
|
||||
VOID TiledMap::OnRemoved()
|
||||
{
|
||||
Node::OnRemoved();
|
||||
}
|
||||
|
||||
VOID TiledMap::Draw()
|
||||
{
|
||||
Node::Draw();
|
||||
}
|
||||
|
||||
VOID TiledMap::Update()
|
||||
{
|
||||
Node::Update();
|
||||
}
|
||||
} // namespace ia::iae::game
|
||||
@ -1,51 +0,0 @@
|
||||
#include <Player.hpp>
|
||||
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
#include <IAEngine/Input.hpp>
|
||||
|
||||
#include <IACore/File.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
extern ResourceManager* g_resourceManager;
|
||||
|
||||
Handle m_id;
|
||||
|
||||
Player::Player(IN Engine *engine) : m_engine(engine)
|
||||
{
|
||||
m_spriteRenderer = AddComponent<SpriteRendererComponent>();
|
||||
}
|
||||
|
||||
VOID Player::OnAdded(IN Scene *scene)
|
||||
{
|
||||
Node::OnAdded(scene);
|
||||
|
||||
iae::SpriteRendererComponent::AnimationKeyFrame keyFrame{};
|
||||
const auto d = File::ReadToVector("Graphics/green.png");
|
||||
keyFrame.Texture = g_resourceManager->CreateTexture(d.data(), d.size());
|
||||
keyFrame.Scale = {0.2f, 0.2f, 1.0f};
|
||||
|
||||
m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}});
|
||||
m_spriteRenderer->BakeAnimations();
|
||||
|
||||
m_id = Physics::CreateDynamicBody({GetPosition().X + 20, GetPosition().Y + 20});
|
||||
Physics::AddBoxCollider(m_id, {40.0f, 40.0f});
|
||||
}
|
||||
|
||||
VOID Player::OnRemoved()
|
||||
{
|
||||
|
||||
Node::OnRemoved();
|
||||
}
|
||||
|
||||
VOID Player::Draw()
|
||||
{
|
||||
Node::Draw();
|
||||
}
|
||||
|
||||
VOID Player::Update()
|
||||
{
|
||||
Node::Update();
|
||||
SetLocalPosition(Physics::GetBodyPosition(m_id) - iam::Vec3f{20.0f, 20.0f, 0.0f});
|
||||
}
|
||||
} // namespace ia::iae::game
|
||||
@ -7,13 +7,8 @@ namespace ia::iae::game
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
Game(IN Engine* engine): m_engine(engine) {}
|
||||
|
||||
VOID Initialize();
|
||||
VOID Terminate();
|
||||
VOID Update();
|
||||
|
||||
private:
|
||||
Engine* CONST m_engine;
|
||||
};
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/SoundEmitter.hpp>
|
||||
#include <IAEngine/Components/SpriteRenderer.hpp>
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
class Ground : public Node
|
||||
{
|
||||
public:
|
||||
Ground(IN Engine *engine);
|
||||
|
||||
VIRTUAL VOID OnAdded(IN Scene *scene) OVERRIDE;
|
||||
VIRTUAL VOID OnRemoved() OVERRIDE;
|
||||
VIRTUAL VOID Draw() OVERRIDE;
|
||||
VIRTUAL VOID Update() OVERRIDE;
|
||||
|
||||
private:
|
||||
INT32 m_speed{};
|
||||
UINT8 m_direction{};
|
||||
|
||||
private:
|
||||
Engine *CONST m_engine;
|
||||
SpriteRendererComponent* m_spriteRenderer;
|
||||
};
|
||||
} // namespace ia::iae::game
|
||||
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/SoundEmitter.hpp>
|
||||
#include <IAEngine/Components/AtlasRenderer.hpp>
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
class TiledMap : public Node
|
||||
{
|
||||
public:
|
||||
TiledMap(IN Engine* engine);
|
||||
|
||||
VIRTUAL VOID OnAdded(IN Scene *scene) OVERRIDE;
|
||||
VIRTUAL VOID OnRemoved() OVERRIDE;
|
||||
VIRTUAL VOID Draw() OVERRIDE;
|
||||
VIRTUAL VOID Update() OVERRIDE;
|
||||
|
||||
private:
|
||||
Engine* CONST m_engine;
|
||||
RefPtr<SoundEmitterComponent> m_musicEmitter;
|
||||
RefPtr<AtlasRendererComponent> m_atlasRenderer;
|
||||
};
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/SoundEmitter.hpp>
|
||||
#include <IAEngine/Components/SpriteRenderer.hpp>
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
|
||||
namespace ia::iae::game
|
||||
{
|
||||
class Player : public Node
|
||||
{
|
||||
public:
|
||||
Player(IN Engine *engine);
|
||||
|
||||
VIRTUAL VOID OnAdded(IN Scene *scene) OVERRIDE;
|
||||
VIRTUAL VOID OnRemoved() OVERRIDE;
|
||||
VIRTUAL VOID Draw() OVERRIDE;
|
||||
VIRTUAL VOID Update() OVERRIDE;
|
||||
|
||||
private:
|
||||
INT32 m_speed{};
|
||||
UINT8 m_direction{};
|
||||
|
||||
private:
|
||||
Engine *CONST m_engine;
|
||||
SpriteRendererComponent* m_spriteRenderer;
|
||||
};
|
||||
} // namespace ia::iae::game
|
||||
@ -3,12 +3,21 @@ set(IAEngine_Sources
|
||||
imp/cpp/IAEngine.cpp
|
||||
imp/cpp/Time.cpp
|
||||
imp/cpp/Audio.cpp
|
||||
imp/cpp/Texture.cpp
|
||||
imp/cpp/Input.cpp
|
||||
imp/cpp/Scene.cpp
|
||||
imp/cpp/Random.cpp
|
||||
imp/cpp/Texture.cpp
|
||||
imp/cpp/UI.cpp
|
||||
|
||||
imp/cpp/ResourceManager.cpp
|
||||
imp/cpp/Rendering/Camera.cpp
|
||||
imp/cpp/Rendering/Renderer.cpp
|
||||
imp/cpp/Rendering/GPUBuffer.cpp
|
||||
imp/cpp/Rendering/GPUTexture.cpp
|
||||
imp/cpp/Rendering/DebugDraw.cpp
|
||||
|
||||
imp/cpp/Rendering/Pipeline/Pipeline.cpp
|
||||
imp/cpp/Rendering/Pipeline/UnlitMesh.cpp
|
||||
imp/cpp/Rendering/Pipeline/PostProcess.cpp
|
||||
|
||||
imp/cpp/Physics/Physics.cpp
|
||||
|
||||
@ -21,8 +30,8 @@ set(IAEngine_Sources
|
||||
imp/cpp/Components/SpriteRenderer.cpp
|
||||
imp/cpp/Components/SoundEmitter.cpp
|
||||
imp/cpp/Components/ParticleEmitter.cpp
|
||||
imp/cpp/Components/PhysicsBody.cpp
|
||||
imp/cpp/Components/TextureRenderer.cpp
|
||||
imp/cpp/Components/Physics.cpp
|
||||
)
|
||||
|
||||
add_library(IAEngine STATIC ${IAEngine_Sources})
|
||||
@ -30,5 +39,5 @@ add_library(IAEngine STATIC ${IAEngine_Sources})
|
||||
target_include_directories(IAEngine PUBLIC inc/)
|
||||
target_include_directories(IAEngine PRIVATE imp/hpp)
|
||||
|
||||
target_link_libraries(IAEngine PUBLIC IACore IAMath ImGui)
|
||||
target_link_libraries(IAEngine PRIVATE SDL3::SDL3 SDL3_mixer::SDL3_mixer)
|
||||
target_link_libraries(IAEngine PUBLIC IACore ImGui glm::glm)
|
||||
target_link_libraries(IAEngine PRIVATE SDL3::SDL3 SDL3_mixer::SDL3_mixer RmlUi::RmlUi)
|
||||
|
||||
@ -1,14 +1,44 @@
|
||||
// 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/Audio.hpp>
|
||||
|
||||
#include <SDL3/SDL_iostream.h>
|
||||
#include <SDL3_mixer/SDL_mixer.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
struct TrackData
|
||||
{
|
||||
BOOL IsActive{};
|
||||
MIX_Track *Track{};
|
||||
INT32 LoopTimes{};
|
||||
TimePeriod LoopDelay{};
|
||||
std::thread *PlaybackThread;
|
||||
|
||||
std::mutex Mutex;
|
||||
std::condition_variable CV;
|
||||
};
|
||||
|
||||
MIX_Mixer *g_mixer{};
|
||||
Vector<MIX_Track *> g_tracks;
|
||||
Vector<TrackData*> g_tracks;
|
||||
Vector<INT64> g_destroyQueue;
|
||||
Vector<MIX_Audio *> g_audioData;
|
||||
|
||||
VOID Audio::Initialize()
|
||||
@ -22,7 +52,48 @@ namespace ia::iae
|
||||
|
||||
VOID Audio::Terminate()
|
||||
{
|
||||
for (SIZE_T i = 0; i < g_tracks.size(); i++)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_tracks[i]->Mutex);
|
||||
g_tracks[i]->IsActive = false;
|
||||
}
|
||||
g_tracks[i]->CV.notify_one();
|
||||
g_tracks[i]->PlaybackThread->join();
|
||||
delete g_tracks[i];
|
||||
}
|
||||
MIX_StopAllTracks(g_mixer, 0);
|
||||
g_audioData.clear();
|
||||
g_tracks.clear();
|
||||
}
|
||||
|
||||
VOID Audio::Update()
|
||||
{
|
||||
for (SIZE_T i = 0; i < g_tracks.size(); i++)
|
||||
{
|
||||
auto &t = g_tracks[i];
|
||||
if (!t->IsActive && !MIX_TrackPlaying(t->Track))
|
||||
DestroyTrack(i);
|
||||
}
|
||||
|
||||
// [IATODO]: IMPL: Destroy queue
|
||||
}
|
||||
|
||||
INT64 Audio::CreateTrack()
|
||||
{
|
||||
g_tracks.pushBack(new TrackData{true, MIX_CreateTrack(g_mixer)});
|
||||
return g_tracks.size() - 1;
|
||||
}
|
||||
|
||||
VOID Audio::DestroyTrack(IN INT64 trackHandle)
|
||||
{
|
||||
if(trackHandle >= g_tracks.size())
|
||||
return;
|
||||
auto& t = g_tracks[trackHandle];
|
||||
ClearTrack(trackHandle);
|
||||
MIX_StopTrack(t->Track, 0);
|
||||
t->IsActive = false;
|
||||
g_destroyQueue.pushBack(trackHandle);
|
||||
}
|
||||
|
||||
Sound Audio::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
|
||||
@ -31,62 +102,55 @@ namespace ia::iae
|
||||
return Sound(g_audioData.size() - 1);
|
||||
}
|
||||
|
||||
INT64 Audio::CreateTrack()
|
||||
{
|
||||
g_tracks.pushBack(MIX_CreateTrack(g_mixer));
|
||||
return g_tracks.size() - 1;
|
||||
}
|
||||
|
||||
VOID Audio::DestroyTrack(IN INT64 trackHandle)
|
||||
{
|
||||
ClearTrack(trackHandle);
|
||||
}
|
||||
|
||||
VOID Audio::QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle)
|
||||
{
|
||||
MIX_SetTrackAudio(g_tracks[trackHandle], g_audioData[dataHandle]);
|
||||
MIX_SetTrackAudio(g_tracks[trackHandle]->Track, g_audioData[dataHandle]);
|
||||
}
|
||||
|
||||
VOID Audio::PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay)
|
||||
{
|
||||
struct __callback_data
|
||||
{
|
||||
INT32 loopTimes;
|
||||
TimePeriod loopDelay;
|
||||
};
|
||||
|
||||
const auto callbackData = new __callback_data{.loopTimes = loopTimes, .loopDelay = loopDelay};
|
||||
|
||||
MIX_PlayTrack(g_tracks[trackHandle], 0);
|
||||
MIX_SetTrackStoppedCallback(
|
||||
g_tracks[trackHandle],
|
||||
[](PVOID _callbackData, MIX_Track *track) {
|
||||
const auto callbackData = (__callback_data *) _callbackData;
|
||||
if (callbackData->loopTimes < 0)
|
||||
goto loop_next_iteration;
|
||||
else if (callbackData->loopTimes == 0)
|
||||
return;
|
||||
else
|
||||
callbackData->loopTimes -= 1;
|
||||
loop_next_iteration:
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds((INT32) (callbackData->loopDelay.GetValue() * 1000)));
|
||||
MIX_PlayTrack(track, 0);
|
||||
},
|
||||
callbackData);
|
||||
auto &t = g_tracks[trackHandle];
|
||||
t->LoopTimes = loopTimes;
|
||||
t->LoopDelay = loopDelay;
|
||||
if (t->LoopTimes == 0)
|
||||
t->IsActive = false;
|
||||
else
|
||||
t->PlaybackThread = new std::thread([trackHandle]() {
|
||||
auto &t = g_tracks[trackHandle];
|
||||
while (t->IsActive)
|
||||
{
|
||||
if (MIX_TrackPlaying(t->Track))
|
||||
continue;
|
||||
if (t->LoopTimes < 0)
|
||||
goto loop_next_iteration;
|
||||
else if (!t->LoopTimes)
|
||||
{
|
||||
t->IsActive = false;
|
||||
return;
|
||||
}
|
||||
t->LoopTimes--;
|
||||
loop_next_iteration:
|
||||
std::unique_lock<std::mutex> lock(t->Mutex);
|
||||
t->CV.wait_for(lock, std::chrono::milliseconds((INT32) (t->LoopDelay.GetValue() * 1000)),
|
||||
[t]() { return !t->IsActive; });
|
||||
MIX_PlayTrack(t->Track, 0);
|
||||
}
|
||||
});
|
||||
MIX_PlayTrack(t->Track, 0);
|
||||
}
|
||||
|
||||
VOID Audio::ClearTrack(IN INT64 trackHandle)
|
||||
{
|
||||
MIX_StopTrack(g_tracks[trackHandle], 0);
|
||||
MIX_StopTrack(g_tracks[trackHandle]->Track, 0);
|
||||
}
|
||||
|
||||
VOID Audio::PauseTrack(IN INT64 trackHandle)
|
||||
{
|
||||
MIX_PauseTrack(g_tracks[trackHandle]);
|
||||
MIX_PauseTrack(g_tracks[trackHandle]->Track);
|
||||
}
|
||||
|
||||
VOID Audio::ResumeTrack(IN INT64 trackHandle)
|
||||
{
|
||||
MIX_ResumeTrack(g_tracks[trackHandle]);
|
||||
MIX_ResumeTrack(g_tracks[trackHandle]->Track);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,30 +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/AtlasRenderer.hpp>
|
||||
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
AtlasRendererComponent::AtlasRendererComponent(IN Node *node) : IComponent(node)
|
||||
AtlasRendererComponent::AtlasRendererComponent(IN Node *node) : TextureRendererComponent(node)
|
||||
{
|
||||
}
|
||||
|
||||
Handle AtlasRendererComponent::AddTexture(IN RefPtr<Texture> texture)
|
||||
AtlasRendererComponent::~AtlasRendererComponent()
|
||||
{
|
||||
m_textures.pushBack(texture);
|
||||
return m_textures.size() - 1;
|
||||
m_bakedGPUTexture.reset();
|
||||
}
|
||||
|
||||
VOID AtlasRendererComponent::SetGrid(IN CONST TileGrid &grid)
|
||||
VOID AtlasRendererComponent::SetGrid(IN INT32 tileWidth, IN INT32 tileHeight, IN INT32 tileCountX,
|
||||
IN INT32 tileCountY)
|
||||
{
|
||||
m_tileGrid = grid;
|
||||
m_tileGrid.m_tileTextures.resize(grid.TileCountX * grid.TileCountY);
|
||||
for (auto &t : m_tileGrid.m_tileTextures)
|
||||
t = INVALID_HANDLE;
|
||||
m_tileGrid = {};
|
||||
m_tileGrid.TileWidth = tileWidth;
|
||||
m_tileGrid.TileHeight = tileHeight;
|
||||
m_tileGrid.TileCountX = tileCountX;
|
||||
m_tileGrid.TileCountY = tileCountY;
|
||||
m_tileGrid.m_tileTextures.resize(m_tileGrid.TileCountX * m_tileGrid.TileCountY);
|
||||
}
|
||||
|
||||
VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 x, IN INT32 y, IN Handle textureHandle)
|
||||
VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 index, IN class Texture texture)
|
||||
{
|
||||
m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)] = textureHandle;
|
||||
m_tileGrid.m_tileTextures[index] = texture;
|
||||
}
|
||||
|
||||
VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 x, IN INT32 y, IN class Texture texture)
|
||||
{
|
||||
m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)] = texture;
|
||||
}
|
||||
|
||||
VOID AtlasRendererComponent::BakeGrid()
|
||||
{
|
||||
CONST INT32 w = m_tileGrid.TileWidth * m_tileGrid.TileCountX, h = m_tileGrid.TileHeight * m_tileGrid.TileCountY;
|
||||
Vector<Handle> handles;
|
||||
handles.resize(m_tileGrid.TileCountX * m_tileGrid.TileCountY);
|
||||
for (SIZE_T i = 0; i < handles.size(); i++)
|
||||
handles[i] = m_tileGrid.m_tileTextures[i].GetHandle();
|
||||
m_bakedGPUTexture = GPUTexture::GridCombine(handles.data(), m_tileGrid.TileCountX, m_tileGrid.TileCountY,
|
||||
m_tileGrid.TileWidth, m_tileGrid.TileHeight);
|
||||
m_node->DrawnSize() = {w, h};
|
||||
CurrentTexture() = Texture(m_bakedGPUTexture->GetHandle(), w, h);
|
||||
}
|
||||
|
||||
VOID AtlasRendererComponent::Update()
|
||||
@ -33,18 +69,9 @@ namespace ia::iae
|
||||
|
||||
VOID AtlasRendererComponent::Draw()
|
||||
{
|
||||
iam::Vec3f p{m_node->GetPosition().X, m_node->GetPosition().Y, m_node->GetPosition().Z};
|
||||
for (INT32 y = 0; y < m_tileGrid.TileCountY; y++)
|
||||
{
|
||||
for (INT32 x = 0; x < m_tileGrid.TileCountX; x++)
|
||||
{
|
||||
const auto t = m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)];
|
||||
if (t != INVALID_HANDLE)
|
||||
m_textures[t]->Draw(p + m_tileGrid.Position, {1.0f, 1.0f, 1.0f}, 0.0f, false, false, {1.0f, 1.0f, 1.0f, 1.0f});
|
||||
p.X += m_tileGrid.TileWidth;
|
||||
}
|
||||
p.X = m_node->GetPosition().X;
|
||||
p.Y += m_tileGrid.TileHeight;
|
||||
}
|
||||
PositionOffset() = m_tileGrid.Position;
|
||||
ScaleOffset() = {1.0f, 1.0f};
|
||||
IsCameraRelative() = true;
|
||||
TextureRendererComponent::Draw();
|
||||
}
|
||||
} // namespace ia::iae
|
||||
} // namespace ia::iae
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/ParticleEmitter.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
|
||||
78
Src/IAEngine/imp/cpp/Components/Physics.cpp
Normal file
78
Src/IAEngine/imp/cpp/Components/Physics.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
// 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/Physics.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
PhysicsComponent::PhysicsComponent(IN Node *node) : IComponent(node)
|
||||
{
|
||||
m_physicsHandle = Physics::RegisterComponent(this);
|
||||
}
|
||||
|
||||
PhysicsComponent::~PhysicsComponent()
|
||||
{
|
||||
}
|
||||
|
||||
VOID PhysicsComponent::Draw()
|
||||
{
|
||||
}
|
||||
|
||||
VOID PhysicsComponent::Update()
|
||||
{
|
||||
m_velocity = {};
|
||||
}
|
||||
|
||||
Handle PhysicsComponent::CreateCollider()
|
||||
{
|
||||
m_colliders.pushBack({});
|
||||
return m_colliders.size() - 1;
|
||||
}
|
||||
|
||||
Handle PhysicsComponent::AddCollider(IN Collider collider)
|
||||
{
|
||||
m_colliders.pushBack(collider);
|
||||
return m_colliders.size() - 1;
|
||||
}
|
||||
|
||||
PhysicsComponent::Collider &PhysicsComponent::GetCollider(IN Handle handle)
|
||||
{
|
||||
return m_colliders[handle];
|
||||
}
|
||||
|
||||
VOID PhysicsComponent::Move(IN glm::vec2 direction)
|
||||
{
|
||||
IA_ASSERT(m_isDynamic);
|
||||
const auto v = direction * m_movementSpeed;
|
||||
m_velocity += v;
|
||||
for(const auto& t: m_colliders)
|
||||
{
|
||||
if(!Physics::CanMove(m_physicsHandle, t, v))
|
||||
return;
|
||||
}
|
||||
m_node->SetLocalPosition(m_node->GetLocalPosition() + v);
|
||||
}
|
||||
|
||||
VOID PhysicsComponent::Jump(IN FLOAT32 force)
|
||||
{
|
||||
}
|
||||
|
||||
VOID PhysicsComponent::OnCollision(IN PhysicsComponent *other)
|
||||
{
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,6 +0,0 @@
|
||||
#include <IAEngine/Components/PhysicsBody.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/SoundEmitter.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
|
||||
@ -1,20 +1,42 @@
|
||||
// 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/SpriteRenderer.hpp>
|
||||
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
#include <IAEngine/Time.hpp>
|
||||
|
||||
#include <IAMath/Lerp.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
SpriteRendererComponent::SpriteRendererComponent(IN Node *node) : IComponent(node)
|
||||
SpriteRendererComponent::AnimationKeyFrame SpriteRendererComponent::GetKeyFrame(IN INT32 index)
|
||||
{
|
||||
index %= m_activeAnimation.Keys.size();
|
||||
return m_reverseAnimation ? m_activeAnimation.Keys[m_activeAnimation.Keys.size() - 1 - index]
|
||||
: m_activeAnimation.Keys[index];
|
||||
}
|
||||
|
||||
SpriteRendererComponent::SpriteRendererComponent(IN Node *node) : TextureRendererComponent(node)
|
||||
{
|
||||
}
|
||||
|
||||
Handle SpriteRendererComponent::AddAnimation(IN CONST Animation &animation)
|
||||
{
|
||||
if(animation.Keys.empty())
|
||||
if (animation.Keys.empty())
|
||||
return INVALID_HANDLE;
|
||||
m_animations.pushBack(animation);
|
||||
return m_animations.size() - 1;
|
||||
@ -22,26 +44,38 @@ namespace ia::iae
|
||||
|
||||
VOID SpriteRendererComponent::BakeAnimations()
|
||||
{
|
||||
for (auto &anim : m_animations)
|
||||
{
|
||||
auto t = anim.Keys.back();
|
||||
t.Duration = 0;
|
||||
anim.Keys.pushBack(t);
|
||||
}
|
||||
if (m_animations.size())
|
||||
SetActiveAnimation(0);
|
||||
ForceSetActiveAnimation(0);
|
||||
}
|
||||
|
||||
VOID SpriteRendererComponent::SetAnimationFrame(IN INT32 animation, IN INT32 frame)
|
||||
{
|
||||
m_activeAnimation = {};
|
||||
m_currentAnimationState = m_animations[animation].Keys[frame];
|
||||
}
|
||||
|
||||
VOID SpriteRendererComponent::SetActiveAnimation(IN Handle animation)
|
||||
{
|
||||
if(animation == m_activeAnimationHandle) return;
|
||||
if (animation == m_activeAnimationHandle)
|
||||
return;
|
||||
ForceSetActiveAnimation(animation);
|
||||
}
|
||||
|
||||
VOID SpriteRendererComponent::ForceSetActiveAnimation(IN Handle animation)
|
||||
{
|
||||
IA_RELEASE_ASSERT((animation != INVALID_HANDLE) && (animation < m_animations.size()));
|
||||
m_prevAnimationKeyFrameIndex = 0;
|
||||
m_activeAnimation = m_animations[animation];
|
||||
m_prevAnimationKeyFrame = m_activeAnimation.Keys[m_prevAnimationKeyFrameIndex + 0];
|
||||
m_nextAnimationKeyFrame = m_activeAnimation.Keys[m_prevAnimationKeyFrameIndex + 1];
|
||||
|
||||
m_prevAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 0);
|
||||
m_nextAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 1);
|
||||
|
||||
m_currentAnimationState = m_prevAnimationKeyFrame;
|
||||
m_activeAnimationHandle = animation;
|
||||
|
||||
CurrentTexture() = m_currentAnimationState.Texture;
|
||||
m_node->DrawnSize() =
|
||||
m_node->GetScale() * m_currentAnimationState.Texture.GetExtent() * m_currentAnimationState.Scale;
|
||||
}
|
||||
|
||||
VOID SpriteRendererComponent::Update()
|
||||
@ -52,23 +86,26 @@ namespace ia::iae
|
||||
VOID SpriteRendererComponent::Draw()
|
||||
{
|
||||
const auto &animFrame = m_currentAnimationState;
|
||||
if(!animFrame.Texture) return;
|
||||
animFrame.Texture->Draw(
|
||||
m_node->GetPosition() + animFrame.Position, m_node->GetScale() * animFrame.Scale,
|
||||
m_node->GetRotation().Z + animFrame.Rotation.Z, m_isFlippedH, m_isFlippedV, animFrame.ColorOverlay);
|
||||
PositionOffset() = animFrame.Position;
|
||||
ScaleOffset() = animFrame.Scale;
|
||||
RotationOffset() = animFrame.Rotation;
|
||||
ColorOverlay() = animFrame.ColorOverlay;
|
||||
CurrentTexture() = animFrame.Texture;
|
||||
TextureRendererComponent::Draw();
|
||||
}
|
||||
|
||||
VOID SpriteRendererComponent::UpdateAnimation()
|
||||
{
|
||||
const auto keyCount = m_activeAnimation.Keys.size();
|
||||
if (!keyCount)
|
||||
if (keyCount <= 1)
|
||||
return;
|
||||
|
||||
if (m_currentAnimationState.ShouldInterpolate)
|
||||
{
|
||||
const auto t = m_timelinePosition / m_prevAnimationKeyFrame.Duration;
|
||||
#define INTERP_PROPERTY(name) \
|
||||
m_currentAnimationState.name = iam::Lerp(m_prevAnimationKeyFrame.name, m_nextAnimationKeyFrame.name, t);
|
||||
m_currentAnimationState.name = \
|
||||
m_prevAnimationKeyFrame.name + (m_nextAnimationKeyFrame.name - m_prevAnimationKeyFrame.name) * t;
|
||||
|
||||
INTERP_PROPERTY(Position);
|
||||
INTERP_PROPERTY(Rotation);
|
||||
@ -78,19 +115,19 @@ namespace ia::iae
|
||||
#undef INTERP_PROPERTY
|
||||
}
|
||||
|
||||
m_timelinePosition += Time::GetFrameDeltaTime();
|
||||
if (m_timelinePosition >= m_prevAnimationKeyFrame.Duration)
|
||||
{
|
||||
m_prevAnimationKeyFrameIndex = (m_prevAnimationKeyFrameIndex + 1) % (keyCount - 1);
|
||||
m_prevAnimationKeyFrameIndex = (m_prevAnimationKeyFrameIndex + 1) % keyCount;
|
||||
if (!m_prevAnimationKeyFrameIndex && !m_activeAnimation.ShouldLoop)
|
||||
{
|
||||
m_activeAnimation = {};
|
||||
return;
|
||||
}
|
||||
m_prevAnimationKeyFrame = m_activeAnimation.Keys[m_prevAnimationKeyFrameIndex + 0];
|
||||
m_nextAnimationKeyFrame = m_activeAnimation.Keys[m_prevAnimationKeyFrameIndex + 1];
|
||||
m_prevAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 0);
|
||||
m_nextAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 1);
|
||||
m_currentAnimationState = m_prevAnimationKeyFrame;
|
||||
m_timelinePosition = 0;
|
||||
}
|
||||
m_timelinePosition += Time::GetFrameDeltaTime();
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,22 +1,54 @@
|
||||
// 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/TextureRenderer.hpp>
|
||||
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN Texture g_whiteStrokeTexture;
|
||||
|
||||
TextureRendererComponent::TextureRendererComponent(IN Node *node) : IComponent(node)
|
||||
{
|
||||
}
|
||||
|
||||
VOID TextureRendererComponent::Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID TextureRendererComponent::Draw()
|
||||
{
|
||||
m_texture->Draw(
|
||||
m_node->GetPosition() + m_position, m_node->GetScale(),
|
||||
m_node->GetRotation().Z, false, false, iam::Vec4f{1.0f, 1.0f, 1.0f, 1.0f});
|
||||
m_node->DrawnSize() = m_node->GetScale() * m_texture.GetExtent() * m_scaleOffset;
|
||||
|
||||
Renderer::SetState_FlippedH(m_isFlippedH);
|
||||
Renderer::SetState_FlippedV(m_isFlippedV);
|
||||
Renderer::SetState_CameraRelative(m_isCameraRelative);
|
||||
Renderer::SetState_TextureOffset(m_textureOffset.x, m_textureOffset.y);
|
||||
|
||||
Renderer::Draw(Renderer::GetMesh_Quad(), m_texture.GetHandle(), m_node->GetPosition() + m_positionOffset,
|
||||
m_node->DrawnSize(), m_node->GetRotation() + m_rotationOffset, m_node->LayerIndex(),
|
||||
m_node->GetSortIndex(), m_colorOverlay);
|
||||
|
||||
//if (m_shouldDrawOutline)
|
||||
//{
|
||||
// Renderer::Draw(Renderer::GetMesh_Quad(), g_whiteStrokeTexture.GetHandle(), m_node->GetPosition() + m_positionOffset,
|
||||
// m_node->DrawnSize(), m_node->GetRotation() + m_rotationOffset, Renderer::MAX_LAYER_INDEX,
|
||||
// m_node->GetSortIndex(), m_outlineColor);
|
||||
//}
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/Events/Event.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
|
||||
@ -1,40 +1,50 @@
|
||||
// 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/Rendering/GPUTexture.hpp>
|
||||
|
||||
#include <IAEngine/Audio.hpp>
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
#include <IAEngine/Input.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
#include <IAEngine/Random.hpp>
|
||||
#include <IAEngine/Time.hpp>
|
||||
#include <IAEngine/UI.hpp>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <backends/imgui_impl_sdl3.h>
|
||||
#include <backends/imgui_impl_sdlrenderer3.h>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
struct EngineContext
|
||||
{
|
||||
SDL_Renderer *Renderer{};
|
||||
SDL_Window *Window{};
|
||||
SDL_Event Event{};
|
||||
ImGuiIO ImGUIIO{};
|
||||
|
||||
BOOL ShouldClose{false};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
CONSTEXPR FLOAT32 GAME_UPDATE_INTERVAL = 1000.0f / 60.0f;
|
||||
|
||||
Engine::Engine() : m_context(MakeRefPtr<EngineContext>())
|
||||
{
|
||||
}
|
||||
EXTERN BOOL g_physicsDebugDrawEnabled;
|
||||
|
||||
Engine::~Engine()
|
||||
{
|
||||
}
|
||||
SDL_Event g_event{};
|
||||
FLOAT32 g_updateTimer{};
|
||||
BOOL g_shouldClose{false};
|
||||
SDL_Window *g_windowHandle{};
|
||||
Vector<RefPtr<GPUTexture>> g_gpuTextureRefs;
|
||||
|
||||
Scene *g_activeScene;
|
||||
|
||||
BOOL Engine::Initialize(IN CONST InitConfig &config)
|
||||
{
|
||||
@ -46,39 +56,25 @@ namespace ia::iae
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer(config.GameName.c_str(), config.WindowWidth, config.WindowHeight,
|
||||
SDL_WINDOW_RESIZABLE, &m_context->Window, &m_context->Renderer))
|
||||
if (!(g_windowHandle = SDL_CreateWindow(config.GameName.c_str(), config.WindowWidth, config.WindowHeight,
|
||||
SDL_WINDOW_RESIZABLE)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't create SDL3 window and renderer: ", SDL_GetError());
|
||||
IAE_LOG_ERROR("Couldn't create SDL3 window: ", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_SetWindowResizable(m_context->Window, false);
|
||||
SDL_SetRenderVSync(m_context->Renderer, 1);
|
||||
|
||||
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
m_context->ImGUIIO = ImGui::GetIO();
|
||||
(void) m_context->ImGUIIO;
|
||||
m_context->ImGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
m_context->ImGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
|
||||
ImGui::StyleColorsClassic();
|
||||
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(mainScale);
|
||||
style.FontScaleDpi = mainScale;
|
||||
|
||||
ImGui_ImplSDL3_InitForSDLRenderer(m_context->Window, m_context->Renderer);
|
||||
ImGui_ImplSDLRenderer3_Init(m_context->Renderer);
|
||||
SDL_SetWindowResizable(g_windowHandle, false);
|
||||
|
||||
Time::Initialize();
|
||||
|
||||
if (!Renderer::Initialize())
|
||||
return false;
|
||||
|
||||
Random::Initialize();
|
||||
|
||||
Input::Initialize();
|
||||
Audio::Initialize();
|
||||
Physics::Initialize();
|
||||
UI::Initialize(config.WindowWidth, config.WindowHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -87,105 +83,155 @@ namespace ia::iae
|
||||
{
|
||||
IAE_LOG_INFO("Shutting down IAEngine");
|
||||
|
||||
for (auto &t : g_gpuTextureRefs)
|
||||
t.reset();
|
||||
|
||||
UI::Terminate();
|
||||
Physics::Terminate();
|
||||
Audio::Terminate();
|
||||
Renderer::Terminate();
|
||||
|
||||
ImGui_ImplSDLRenderer3_Shutdown();
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_DestroyRenderer(m_context->Renderer);
|
||||
SDL_DestroyWindow(m_context->Window);
|
||||
SDL_DestroyWindow(g_windowHandle);
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
VOID Engine::BeginFrame()
|
||||
{
|
||||
SDL_PollEvent(&m_context->Event);
|
||||
if (m_context->Event.type == SDL_EVENT_QUIT)
|
||||
m_context->ShouldClose = true;
|
||||
SDL_PollEvent(&g_event);
|
||||
if (g_event.type == SDL_EVENT_QUIT)
|
||||
g_shouldClose = true;
|
||||
ProcessEvents();
|
||||
m_updateTimer += Time::GetFrameDeltaTime();
|
||||
if (m_updateTimer >= GAME_UPDATE_INTERVAL)
|
||||
g_updateTimer += Time::GetFrameDeltaTime();
|
||||
if (g_updateTimer >= GAME_UPDATE_INTERVAL)
|
||||
{
|
||||
UpdateGame();
|
||||
while (m_updateTimer >= GAME_UPDATE_INTERVAL)
|
||||
m_updateTimer -= GAME_UPDATE_INTERVAL;
|
||||
while (g_updateTimer >= GAME_UPDATE_INTERVAL)
|
||||
g_updateTimer -= GAME_UPDATE_INTERVAL;
|
||||
}
|
||||
ImGui_ImplSDLRenderer3_NewFrame();
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
RenderDebugUI();
|
||||
ImGui::Render();
|
||||
SDL_SetRenderScale(m_context->Renderer, m_context->ImGUIIO.DisplayFramebufferScale.x,
|
||||
m_context->ImGUIIO.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColorFloat(m_context->Renderer, 0.33f, 0.33f, 0.33f, 1.0f);
|
||||
SDL_RenderClear(m_context->Renderer);
|
||||
Renderer::BeginFrame();
|
||||
RenderGame();
|
||||
UI::Draw();
|
||||
}
|
||||
|
||||
VOID Engine::EndFrame()
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), m_context->Renderer);
|
||||
SDL_RenderPresent(m_context->Renderer);
|
||||
Renderer::EndFrame();
|
||||
Time::NextFrame();
|
||||
}
|
||||
|
||||
VOID Engine::AddDebugUIWindow(IN PCCHAR title, IN CONST iam::Vec2f &position, IN CONST iam::Vec2f &size,
|
||||
IN std::function<VOID()> contentDrawCallback)
|
||||
{
|
||||
m_debugUIWindows.pushBack(DebugUIWindow{title, position, size, contentDrawCallback});
|
||||
}
|
||||
|
||||
BOOL Engine::ShouldClose()
|
||||
{
|
||||
return m_context->ShouldClose;
|
||||
}
|
||||
|
||||
VOID Engine::RenderDebugUI()
|
||||
{
|
||||
for (const auto &w : m_debugUIWindows) {
|
||||
ImGui::Begin(w.Title);
|
||||
ImGui::SetWindowPos({w.Position.X, w.Position.Y});
|
||||
ImGui::SetWindowSize({w.Size.X, w.Size.Y});
|
||||
w.ContentDrawCallback();
|
||||
ImGui::End();
|
||||
}
|
||||
return g_shouldClose;
|
||||
}
|
||||
|
||||
VOID Engine::ProcessEvents()
|
||||
{
|
||||
ImGui_ImplSDL3_ProcessEvent(&m_context->Event);
|
||||
Input::OnEvent(&m_context->Event);
|
||||
ImGui_ImplSDL3_ProcessEvent(&g_event);
|
||||
Input::OnEvent(&g_event);
|
||||
UI::OnEvent(&g_event);
|
||||
}
|
||||
|
||||
VOID Engine::UpdateGame()
|
||||
{
|
||||
Physics::Update();
|
||||
if(Input::WasKeyPressed(Input::KEY_F6))
|
||||
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
|
||||
|
||||
if B_LIKELY (m_activeScene)
|
||||
m_activeScene->Update();
|
||||
Physics::Update();
|
||||
Audio::Update();
|
||||
|
||||
if B_LIKELY (g_activeScene)
|
||||
g_activeScene->Update();
|
||||
|
||||
UI::Update();
|
||||
}
|
||||
|
||||
VOID Engine::RenderGame()
|
||||
{
|
||||
if B_LIKELY (m_activeScene)
|
||||
m_activeScene->Draw();
|
||||
if B_LIKELY (g_activeScene)
|
||||
g_activeScene->Draw();
|
||||
}
|
||||
|
||||
VOID Engine::ChangeScene(IN RefPtr<Scene> scene)
|
||||
VOID Engine::ChangeScene(IN Scene *scene)
|
||||
{
|
||||
m_activeScene = scene;
|
||||
if(g_activeScene)
|
||||
g_activeScene->OnDeactivate();
|
||||
g_activeScene = scene;
|
||||
g_activeScene->OnActivate();
|
||||
}
|
||||
|
||||
RefPtr<Scene> Engine::CreateScene()
|
||||
Scene *Engine::GetActiveScene()
|
||||
{
|
||||
return MakeRefPtr<Scene>(this);
|
||||
}
|
||||
|
||||
PVOID Engine::GetRendererHandle() CONST
|
||||
{
|
||||
return m_context->Renderer;
|
||||
return g_activeScene;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
RefPtr<Scene> Engine::CreateScene()
|
||||
{
|
||||
return MakeRefPtr<Scene>();
|
||||
}
|
||||
|
||||
Texture Engine::CreateTexture(IN CONST Vector<UINT8> &encodedData)
|
||||
{
|
||||
return CreateTexture(encodedData.data(), encodedData.size());
|
||||
}
|
||||
|
||||
Texture Engine::CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize)
|
||||
{
|
||||
INT32 w, h, nrChannels;
|
||||
const auto pixels = stbi_load_from_memory(encodedData, encodedDataSize, &w, &h, &nrChannels, STBI_rgb_alpha);
|
||||
if (!pixels)
|
||||
THROW_INVALID_DATA("Failed to decode the provided image data");
|
||||
const auto result = CreateTexture((PCUINT8) pixels, w, h);
|
||||
STBI_FREE(pixels);
|
||||
return result;
|
||||
}
|
||||
|
||||
Texture Engine::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
|
||||
{
|
||||
const auto t = GPUTexture::Create(rgbaData, width, height);
|
||||
g_gpuTextureRefs.pushBack(t);
|
||||
return Texture(t->GetHandle(), width, height);
|
||||
}
|
||||
|
||||
Vector<Texture> Engine::CreateTextures(IN CONST Vector<UINT8> &encodedData, IN INT32 textureCount)
|
||||
{
|
||||
return CreateTextures(encodedData.data(), encodedData.size(), textureCount);
|
||||
}
|
||||
|
||||
Vector<Texture> Engine::CreateTextures(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize, IN INT32 textureCount)
|
||||
{
|
||||
SIZE_T offset{0};
|
||||
Vector<Texture> result;
|
||||
INT32 w, h, nrChannels;
|
||||
for (INT32 i = 0; i < textureCount; i++)
|
||||
{
|
||||
SIZE_T readSize{};
|
||||
const auto pixels = stbi_load_from_memory(&encodedData[offset], encodedDataSize - offset, &w, &h,
|
||||
&nrChannels, STBI_rgb_alpha, readSize);
|
||||
if (!pixels)
|
||||
THROW_INVALID_DATA("Failed to decode the provided image data");
|
||||
result.pushBack(CreateTexture((PCUINT8) pixels, w, h));
|
||||
STBI_FREE(pixels);
|
||||
offset += readSize;
|
||||
if (offset >= encodedDataSize)
|
||||
{
|
||||
IA_RELEASE_ASSERT(i == (textureCount - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Sound Engine::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
|
||||
{
|
||||
return Audio::CreateSound(audioData, audioDataSize);
|
||||
}
|
||||
|
||||
Sound Engine::CreateSound(IN CONST Vector<UINT8> &audioData)
|
||||
{
|
||||
return CreateSound(audioData.data(), audioData.size());
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,32 +1,50 @@
|
||||
// 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/Input.hpp>
|
||||
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_Window *g_windowHandle;
|
||||
|
||||
struct InputDirection
|
||||
{
|
||||
iam::Vec2f Velocity{};
|
||||
glm::vec2 Velocity{};
|
||||
Input::DirectionalInput Direction{Input::DirectionalInput::NONE};
|
||||
};
|
||||
|
||||
STATIC CONSTEXPR InputDirection INPUT_TO_DIRECTION_MAP[] = {
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* 0 */
|
||||
{iam::Vec2f{1.0f, 0.0f}, Input::DirectionalInput::RIGHT}, /* D */
|
||||
{iam::Vec2f{-1.0f, 0.0f}, Input::DirectionalInput::LEFT}, /* A */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* A, D */
|
||||
{iam::Vec2f{0.0f, 1.0f}, Input::DirectionalInput::DOWN}, /* S */
|
||||
{iam::Vec2f{1.0f, 1.0f}, Input::DirectionalInput::DOWN_RIGHT}, /* S, D */
|
||||
{iam::Vec2f{-1.0f, 1.0f}, Input::DirectionalInput::DOWN_LEFT}, /* S, A */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* S, A, D */
|
||||
{iam::Vec2f{0.0f, -1.0f}, Input::DirectionalInput::UP}, /* W */
|
||||
{iam::Vec2f{1.0f, -1.0f}, Input::DirectionalInput::UP_RIGHT}, /* W, D */
|
||||
{iam::Vec2f{-1.0f, -1.0f}, Input::DirectionalInput::UP_LEFT}, /* W, A */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, A, D */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, D */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A */
|
||||
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A, D */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* 0 */
|
||||
{glm::vec2{1.0f, 0.0f}, Input::DirectionalInput::RIGHT}, /* D */
|
||||
{glm::vec2{-1.0f, 0.0f}, Input::DirectionalInput::LEFT}, /* A */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* A, D */
|
||||
{glm::vec2{0.0f, 1.0f}, Input::DirectionalInput::DOWN}, /* S */
|
||||
{glm::vec2{1.0f, 1.0f}, Input::DirectionalInput::DOWN_RIGHT}, /* S, D */
|
||||
{glm::vec2{-1.0f, 1.0f}, Input::DirectionalInput::DOWN_LEFT}, /* S, A */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* S, A, D */
|
||||
{glm::vec2{0.0f, -1.0f}, Input::DirectionalInput::UP}, /* W */
|
||||
{glm::vec2{1.0f, -1.0f}, Input::DirectionalInput::UP_RIGHT}, /* W, D */
|
||||
{glm::vec2{-1.0f, -1.0f}, Input::DirectionalInput::UP_LEFT}, /* W, A */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, A, D */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, D */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A */
|
||||
{glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A, D */
|
||||
};
|
||||
|
||||
BOOL Input::s_keys[256];
|
||||
@ -40,6 +58,7 @@ namespace ia::iae
|
||||
|
||||
VOID Input::OnEvent(IN PVOID _event)
|
||||
{
|
||||
memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys));
|
||||
const auto event = (SDL_Event *) _event;
|
||||
if (event->type == SDL_EVENT_KEY_DOWN)
|
||||
{
|
||||
@ -49,21 +68,30 @@ namespace ia::iae
|
||||
{
|
||||
s_keys[event->key.scancode] = false;
|
||||
}
|
||||
memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys));
|
||||
}
|
||||
|
||||
iam::Vec2f Input::GetDirectionalInput()
|
||||
glm::vec2 Input::GetDirectionalInput()
|
||||
{
|
||||
return INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) |
|
||||
(IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)]
|
||||
return INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_UP) << 3) | (IsKeyDown(Input::KEY_DOWN) << 2) |
|
||||
(IsKeyDown(Input::KEY_LEFT) << 1) | (IsKeyDown(Input::KEY_RIGHT) << 0)]
|
||||
.Velocity;
|
||||
}
|
||||
|
||||
iam::Vec2f Input::GetDirectionalInput(OUT DirectionalInput &direction)
|
||||
glm::vec2 Input::GetDirectionalInput(OUT DirectionalInput &direction)
|
||||
{
|
||||
const auto dir = INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) |
|
||||
(IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)];
|
||||
const auto dir = INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_UP) << 3) | (IsKeyDown(Input::KEY_DOWN) << 2) |
|
||||
(IsKeyDown(Input::KEY_LEFT) << 1) | (IsKeyDown(Input::KEY_RIGHT) << 0)];
|
||||
direction = dir.Direction;
|
||||
return dir.Velocity;
|
||||
}
|
||||
|
||||
VOID Input::StartTextInput()
|
||||
{
|
||||
SDL_StartTextInput(g_windowHandle);
|
||||
}
|
||||
|
||||
VOID Input::StopTextInput()
|
||||
{
|
||||
SDL_StopTextInput(g_windowHandle);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,9 +1,31 @@
|
||||
// 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/Nodes/Node.hpp>
|
||||
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Node::~Node()
|
||||
{
|
||||
for (auto &c : m_components)
|
||||
c.reset();
|
||||
}
|
||||
|
||||
VOID Node::OnAdded(IN Scene *scene)
|
||||
{
|
||||
m_scene = scene;
|
||||
@ -20,47 +42,11 @@ namespace ia::iae
|
||||
|
||||
VOID Node::Draw()
|
||||
{
|
||||
BOOL drew = false;
|
||||
for (auto &n : m_children)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) >= 0)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
|
||||
if(((INT32) GetPosition().Z) < 0)
|
||||
{
|
||||
for (auto &c : m_components)
|
||||
c->Draw();
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < 8; i++) // [IATODO]
|
||||
{
|
||||
for (auto &n : m_children)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) != i)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
if (((INT32) GetPosition().Z) == i)
|
||||
{
|
||||
for (auto &c : m_components)
|
||||
c->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &n : m_children)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) < 8)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
|
||||
if(((INT32) GetPosition().Z) > 8)
|
||||
{
|
||||
for (auto &c : m_components)
|
||||
c->Draw();
|
||||
}
|
||||
for (auto &c : m_components)
|
||||
c->Draw();
|
||||
}
|
||||
|
||||
VOID Node::Update()
|
||||
@ -86,9 +72,10 @@ namespace ia::iae
|
||||
c->Disable();
|
||||
}
|
||||
|
||||
VOID Node::AddChild(IN RefPtr<Node> node)
|
||||
Node* Node::AddChild(IN RefPtr<Node> node)
|
||||
{
|
||||
m_children.pushBack(node);
|
||||
return node.get();
|
||||
}
|
||||
|
||||
VOID Node::AddComponent(IN RefPtr<IComponent> component)
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/Nodes/Transform.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
|
||||
@ -1,8 +1,34 @@
|
||||
// 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/IAEngine.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
#include <IAEngine/Rendering/DebugDraw.hpp>
|
||||
#include <IAEngine/Rendering/Camera.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
|
||||
BOOL g_physicsDebugDrawEnabled = false;
|
||||
|
||||
Vector<PhysicsComponent *> g_physicsComponents;
|
||||
|
||||
VOID Physics::Initialize()
|
||||
{
|
||||
@ -16,22 +42,55 @@ namespace ia::iae
|
||||
{
|
||||
}
|
||||
|
||||
Handle Physics::CreateStaticBody(IN iam::Vec3f position)
|
||||
VOID Physics::DebugDraw()
|
||||
{
|
||||
return INVALID_HANDLE;
|
||||
if(!g_physicsDebugDrawEnabled)
|
||||
return;
|
||||
|
||||
for(const auto& t: g_physicsComponents)
|
||||
{
|
||||
for(const auto& c: t->Colliders())
|
||||
{
|
||||
auto color = glm::vec4{0.75f, 0.0f, 0.0f, 1.0f};
|
||||
if(c.IsTrigger)
|
||||
color = {0.25f, 0.45f, 0.75f, 0.75f};
|
||||
DebugDraw::DrawRect(t->GetNode()->GetPosition() + c.Position - Renderer::GetCamera()->Position(), c.Size, color, 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Handle Physics::CreateDynamicBody(IN iam::Vec3f position)
|
||||
Handle Physics::RegisterComponent(IN PhysicsComponent *component)
|
||||
{
|
||||
return INVALID_HANDLE;
|
||||
g_physicsComponents.pushBack(component);
|
||||
return g_physicsComponents.size() - 1;
|
||||
}
|
||||
|
||||
VOID Physics::AddBoxCollider(IN Handle body, IN iam::Vec3f size)
|
||||
BOOL Physics::CanMove(IN Handle handle, IN CONST PhysicsComponent::Collider &collider, IN glm::vec2 movement)
|
||||
{
|
||||
}
|
||||
const auto comp = g_physicsComponents[handle];
|
||||
const auto pos = comp->GetNode()->GetPosition() + movement + collider.Position;
|
||||
for (const auto &t : g_physicsComponents)
|
||||
{
|
||||
if (t == comp)
|
||||
continue;
|
||||
for (const auto &tc : t->Colliders())
|
||||
{
|
||||
const auto tPos = t->GetNode()->GetPosition() + tc.Position;
|
||||
const auto xColliding = ((pos.x + collider.Size.x) >= tPos.x) && ((tPos.x + tc.Size.x) >= pos.x);
|
||||
const auto yColliding = ((pos.y + collider.Size.y) >= tPos.y) && ((tPos.y + tc.Size.y) >= pos.y);
|
||||
if (xColliding && yColliding)
|
||||
{
|
||||
// Collision callback
|
||||
comp->OnCollision(t);
|
||||
t->OnCollision(comp);
|
||||
|
||||
iam::Vec3f Physics::GetBodyPosition(IN Handle body)
|
||||
{
|
||||
return {};
|
||||
// Overlap block
|
||||
if (tc.IsTrigger)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/Random.hpp>
|
||||
|
||||
#include <IAEngine/Time.hpp>
|
||||
|
||||
@ -14,9 +14,7 @@
|
||||
// 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>
|
||||
#include <IAEngine/Rendering/Camera.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
130
Src/IAEngine/imp/cpp/Rendering/DebugDraw.cpp
Normal file
130
Src/IAEngine/imp/cpp/Rendering/DebugDraw.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
// 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/IAEngine.hpp>
|
||||
#include <IAEngine/Rendering/Camera.hpp>
|
||||
#include <IAEngine/Rendering/DebugDraw.hpp>
|
||||
#include <IAEngine/Rendering/GPUBuffer.hpp>
|
||||
#include <IAEngine/Rendering/GPUTexture.hpp>
|
||||
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include <backends/imgui_impl_sdl3.h>
|
||||
#include <backends/imgui_impl_sdlgpu3.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_Window *g_windowHandle;
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
|
||||
ImGuiIO g_imGUIIO{};
|
||||
|
||||
struct UIWindow
|
||||
{
|
||||
PCCHAR Title{""};
|
||||
glm::vec2 Position{};
|
||||
glm::vec2 Size{};
|
||||
std::function<VOID()> ContentDrawCallback{};
|
||||
BOOL Visibility{true};
|
||||
};
|
||||
|
||||
Vector<UIWindow> g_debugUIWindows;
|
||||
|
||||
VOID DebugDraw::Initailize()
|
||||
{
|
||||
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
g_imGUIIO = ImGui::GetIO();
|
||||
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
|
||||
ImGui::StyleColorsClassic();
|
||||
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(mainScale);
|
||||
style.FontScaleDpi = mainScale;
|
||||
|
||||
ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = g_gpuDevice,
|
||||
.ColorTargetFormat =
|
||||
SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
|
||||
.PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
|
||||
ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
|
||||
ImGui_ImplSDLGPU3_Init(&initInfo);
|
||||
}
|
||||
|
||||
VOID DebugDraw::Terminate()
|
||||
{
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui_ImplSDLGPU3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
VOID DebugDraw::Draw()
|
||||
{
|
||||
for (const auto &w : g_debugUIWindows)
|
||||
{
|
||||
if (!w.Visibility)
|
||||
continue;
|
||||
ImGui::Begin(w.Title);
|
||||
ImGui::SetWindowPos({w.Position.x, w.Position.y});
|
||||
ImGui::SetWindowSize({w.Size.x, w.Size.y});
|
||||
w.ContentDrawCallback();
|
||||
ImGui::End();
|
||||
}
|
||||
Physics::DebugDraw();
|
||||
}
|
||||
|
||||
VOID DebugDraw::DrawLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color,
|
||||
IN FLOAT32 thickness)
|
||||
{
|
||||
const auto drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddLine(ImVec2(from.x, from.y), ImVec2(to.x, to.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255), thickness);
|
||||
}
|
||||
|
||||
VOID DebugDraw::DrawRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color, IN FLOAT32 thickness)
|
||||
{
|
||||
const auto drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddRect(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255), 0.0f, 0, thickness);
|
||||
}
|
||||
|
||||
VOID DebugDraw::DrawRectFilled(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color)
|
||||
{
|
||||
const auto drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddRectFilled(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255));
|
||||
}
|
||||
|
||||
Handle DebugDraw::AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
|
||||
IN std::function<VOID()> contentDrawCallback)
|
||||
{
|
||||
g_debugUIWindows.pushBack(UIWindow{title, position, size, contentDrawCallback});
|
||||
return g_debugUIWindows.size() - 1;
|
||||
}
|
||||
|
||||
VOID DebugDraw::SetUIWindowVisibility(IN Handle handle, IN BOOL visible)
|
||||
{
|
||||
g_debugUIWindows[handle].Visibility = visible;
|
||||
}
|
||||
|
||||
VOID DebugDraw::ToggleUIWindowVisibility(IN Handle handle)
|
||||
{
|
||||
g_debugUIWindows[handle].Visibility = !g_debugUIWindows[handle].Visibility;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
131
Src/IAEngine/imp/cpp/Rendering/GPUBuffer.cpp
Normal file
131
Src/IAEngine/imp/cpp/Rendering/GPUBuffer.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
// 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/Rendering/GPUBuffer.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
|
||||
UINT32 g_stagingBufferSize = 4096;
|
||||
SDL_GPUTransferBuffer *g_stagingBuffer{};
|
||||
|
||||
RefPtr<GPUBuffer> GPUBuffer::Create(IN Usage usage, IN PCVOID data, IN UINT32 dataSize)
|
||||
{
|
||||
const auto res = MakeRefPtr<GPUBuffer>();
|
||||
|
||||
SDL_GPUBufferUsageFlags _usage{};
|
||||
switch (usage)
|
||||
{
|
||||
case Usage::VERTEX:
|
||||
_usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
||||
break;
|
||||
|
||||
case Usage::INDEX:
|
||||
_usage = SDL_GPU_BUFFERUSAGE_INDEX;
|
||||
break;
|
||||
|
||||
case Usage::STORAGE:
|
||||
_usage = SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ;
|
||||
break;
|
||||
|
||||
default:
|
||||
THROW_INVALID_DATA("Invalid usage value for GPUBuffer");
|
||||
break;
|
||||
}
|
||||
res->m_usage = usage;
|
||||
|
||||
SDL_GPUBufferCreateInfo createInfo{.usage = _usage, .size = dataSize};
|
||||
SDL_GPUBuffer *handle{};
|
||||
if (!(handle = SDL_CreateGPUBuffer(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Buffer: ", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (data && dataSize)
|
||||
{
|
||||
if (!EnsureStagingBufferSize((UINT32) dataSize))
|
||||
return nullptr;
|
||||
|
||||
res->m_size = dataSize;
|
||||
|
||||
const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer, false);
|
||||
memcpy(mappedPtr, data, dataSize);
|
||||
SDL_UnmapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
||||
|
||||
const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice);
|
||||
const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer);
|
||||
|
||||
SDL_GPUTransferBufferLocation src{.transfer_buffer = g_stagingBuffer, .offset = 0};
|
||||
SDL_GPUBufferRegion dst{.buffer = handle, .offset = 0, .size = dataSize};
|
||||
SDL_UploadToGPUBuffer(copyPass, &src, &dst, false);
|
||||
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
SDL_SubmitGPUCommandBuffer(cmdBuffer);
|
||||
SDL_WaitForGPUIdle(g_gpuDevice);
|
||||
}
|
||||
|
||||
res->m_handle = (Handle) handle;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GPUBuffer::~GPUBuffer()
|
||||
{
|
||||
if (m_handle)
|
||||
SDL_ReleaseGPUBuffer(g_gpuDevice, (SDL_GPUBuffer *) m_handle);
|
||||
}
|
||||
|
||||
BOOL GPUBuffer::InitializeStagingBuffer()
|
||||
{
|
||||
SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
||||
.size = g_stagingBufferSize};
|
||||
if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VOID GPUBuffer::TerminateStagingBuffer()
|
||||
{
|
||||
if (!g_stagingBuffer)
|
||||
return;
|
||||
|
||||
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
||||
}
|
||||
|
||||
BOOL GPUBuffer::EnsureStagingBufferSize(IN UINT32 size)
|
||||
{
|
||||
if (!g_stagingBuffer)
|
||||
return false;
|
||||
if (size <= g_stagingBufferSize)
|
||||
return true;
|
||||
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
||||
SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
||||
.size = (g_stagingBufferSize = size)};
|
||||
if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
140
Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp
Normal file
140
Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
// 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/Rendering/GPUTexture.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
|
||||
SDL_GPUSampler *g_defaultSampler{};
|
||||
|
||||
VOID GPUTexture::Initialize()
|
||||
{
|
||||
if (g_defaultSampler)
|
||||
return;
|
||||
SDL_GPUSamplerCreateInfo createInfo{.min_filter = SDL_GPU_FILTER_LINEAR,
|
||||
.mag_filter = SDL_GPU_FILTER_LINEAR,
|
||||
.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR,
|
||||
.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
|
||||
.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
|
||||
.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
|
||||
.enable_anisotropy = false};
|
||||
g_defaultSampler = SDL_CreateGPUSampler(g_gpuDevice, &createInfo);
|
||||
}
|
||||
|
||||
VOID GPUTexture::Terminate()
|
||||
{
|
||||
if (g_defaultSampler)
|
||||
SDL_ReleaseGPUSampler(g_gpuDevice, g_defaultSampler);
|
||||
}
|
||||
|
||||
Handle GPUTexture::GetDefaultSampler()
|
||||
{
|
||||
return (Handle) g_defaultSampler;
|
||||
}
|
||||
|
||||
RefPtr<GPUTexture> GPUTexture::Create(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
|
||||
{
|
||||
const auto res = MakeRefPtr<GPUTexture>();
|
||||
|
||||
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
|
||||
.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
|
||||
.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER,
|
||||
.width = (UINT32) width,
|
||||
.height = (UINT32) height,
|
||||
.layer_count_or_depth = 1,
|
||||
.num_levels = 1};
|
||||
|
||||
SDL_GPUTexture *handle{};
|
||||
if (!(handle = SDL_CreateGPUTexture(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Failed to create a SDL GPU Texture");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo stagingBufferCreateInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
||||
.size = (UINT32) width * (UINT32) height * 4};
|
||||
const auto stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &stagingBufferCreateInfo);
|
||||
const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, stagingBuffer, false);
|
||||
SDL_memcpy(mappedPtr, rgbaData, width * height * 4);
|
||||
SDL_UnmapGPUTransferBuffer(g_gpuDevice, stagingBuffer);
|
||||
|
||||
const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice);
|
||||
const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer);
|
||||
SDL_GPUTextureTransferInfo transferInfo{.transfer_buffer = stagingBuffer, .offset = 0};
|
||||
SDL_GPUTextureRegion region{.texture = handle, .w = (UINT32) width, .h = (UINT32) height, .d = 1};
|
||||
SDL_UploadToGPUTexture(copyPass, &transferInfo, ®ion, false);
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
SDL_SubmitGPUCommandBuffer(cmdBuffer);
|
||||
SDL_WaitForGPUIdle(g_gpuDevice);
|
||||
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, stagingBuffer);
|
||||
|
||||
res->m_handle = (Handle) handle;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
RefPtr<GPUTexture> GPUTexture::GridCombine(IN Handle *handles, IN INT32 unitCountX, IN INT32 unitCountY,
|
||||
IN INT32 unitSizeX, IN INT32 unitSizeY)
|
||||
{
|
||||
const auto res = MakeRefPtr<GPUTexture>();
|
||||
|
||||
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
|
||||
.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
|
||||
.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER,
|
||||
.width = (UINT32) unitCountX * unitSizeX,
|
||||
.height = (UINT32) unitCountY * unitSizeY,
|
||||
.layer_count_or_depth = 1,
|
||||
.num_levels = 1};
|
||||
|
||||
SDL_GPUTexture *handle{};
|
||||
if (!(handle = SDL_CreateGPUTexture(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Failed to create a SDL GPU Texture");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice);
|
||||
const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer);
|
||||
|
||||
for (INT32 y = 0; y < unitCountY; y++)
|
||||
{
|
||||
for (INT32 x = 0; x < unitCountX; x++)
|
||||
{
|
||||
SDL_GPUTextureLocation src{.texture = (SDL_GPUTexture *) handles[x + (y * unitCountX)], .x = 0, .y = 0};
|
||||
SDL_GPUTextureLocation dst{.texture = handle, .x = (UINT32)(x * unitSizeX), .y = (UINT32)(y * unitSizeY)};
|
||||
SDL_CopyGPUTextureToTexture(copyPass, &src, &dst, unitSizeX, unitSizeY, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
SDL_SubmitGPUCommandBuffer(cmdBuffer);
|
||||
SDL_WaitForGPUIdle(g_gpuDevice);
|
||||
|
||||
res->m_handle = (Handle) handle;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GPUTexture::~GPUTexture()
|
||||
{
|
||||
if (m_handle)
|
||||
SDL_ReleaseGPUTexture(g_gpuDevice, (SDL_GPUTexture *) m_handle);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
83
Src/IAEngine/imp/cpp/Rendering/Pipeline/Pipeline.cpp
Normal file
83
Src/IAEngine/imp/cpp/Rendering/Pipeline/Pipeline.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// 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/Rendering/Pipeline/Pipeline.hpp>
|
||||
|
||||
#include <IACore/File.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
|
||||
Handle IPipeline::LoadShaderFromMemory(IN ShaderStage _stage, IN PCUINT8 sourceData, IN SIZE_T sourceLength,
|
||||
IN UINT32 samplerCount, IN UINT32 uniformBufferCount,
|
||||
IN UINT32 storageBufferCount, IN UINT32 storageTextureCount)
|
||||
{
|
||||
SDL_GPUShader* res{};
|
||||
|
||||
SDL_GPUShaderStage stage{};
|
||||
switch (_stage)
|
||||
{
|
||||
case ShaderStage::VERTEX:
|
||||
stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
||||
break;
|
||||
|
||||
case ShaderStage::PIXEL:
|
||||
stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
THROW_INVALID_DATA("Unsupported shader stage");
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_GPUShaderCreateInfo createInfo = {
|
||||
.code_size = sourceLength,
|
||||
.code = sourceData,
|
||||
.entrypoint = "main",
|
||||
.format = SDL_GPU_SHADERFORMAT_SPIRV,
|
||||
.stage = stage,
|
||||
.num_samplers = samplerCount,
|
||||
.num_storage_textures = storageTextureCount,
|
||||
.num_storage_buffers = storageBufferCount,
|
||||
.num_uniform_buffers = uniformBufferCount,
|
||||
};
|
||||
|
||||
if(!(res = SDL_CreateGPUShader(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Failed to create a SDL shader: ", SDL_GetError());
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return (Handle)res;
|
||||
}
|
||||
|
||||
Handle IPipeline::LoadShaderFromFile(IN ShaderStage stage, IN PCCHAR fileName, IN UINT32 samplerCount,
|
||||
IN UINT32 uniformBufferCount, IN UINT32 storageBufferCount,
|
||||
IN UINT32 storageTextureCount)
|
||||
{
|
||||
const auto source = File::ReadToVector(fileName);
|
||||
return LoadShaderFromMemory(stage, source.data(), source.size(), samplerCount, uniformBufferCount,
|
||||
storageBufferCount, storageTextureCount);
|
||||
}
|
||||
|
||||
VOID IPipeline::UnloadShader(IN Handle handle)
|
||||
{
|
||||
SDL_ReleaseGPUShader(g_gpuDevice, (SDL_GPUShader *) handle);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
81
Src/IAEngine/imp/cpp/Rendering/Pipeline/PostProcess.cpp
Normal file
81
Src/IAEngine/imp/cpp/Rendering/Pipeline/PostProcess.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// 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/Rendering/Pipeline/PostProcess.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include <EmbeddedShaders.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
EXTERN SDL_Window *g_windowHandle;
|
||||
|
||||
Pipeline_PostProcess::~Pipeline_PostProcess()
|
||||
{
|
||||
if (m_handle)
|
||||
SDL_ReleaseGPUGraphicsPipeline(g_gpuDevice, (SDL_GPUGraphicsPipeline *) m_handle);
|
||||
}
|
||||
|
||||
RefPtr<Pipeline_PostProcess> Pipeline_PostProcess::Create()
|
||||
{
|
||||
const auto res = MakeRefPtr<Pipeline_PostProcess>();
|
||||
|
||||
const auto vertexShader = LoadShaderFromMemory(ShaderStage::VERTEX, SHADER_SOURCE_POSTPROCESS_VERT,
|
||||
sizeof(SHADER_SOURCE_POSTPROCESS_VERT), 0, 0, 0, 0);
|
||||
const auto pixelShader = LoadShaderFromMemory(ShaderStage::PIXEL, SHADER_SOURCE_POSTPROCESS_FRAG,
|
||||
sizeof(SHADER_SOURCE_POSTPROCESS_FRAG), 2, 0, 0, 0);
|
||||
|
||||
SDL_GPUColorTargetDescription colorTargets[] = {{
|
||||
.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
|
||||
}};
|
||||
SDL_GPUGraphicsPipelineCreateInfo createInfo = {
|
||||
.vertex_shader = (SDL_GPUShader *) vertexShader,
|
||||
.fragment_shader = (SDL_GPUShader *) pixelShader,
|
||||
.vertex_input_state = SDL_GPUVertexInputState{.vertex_buffer_descriptions = nullptr,
|
||||
.num_vertex_buffers = 0,
|
||||
.vertex_attributes = nullptr,
|
||||
.num_vertex_attributes = 0},
|
||||
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
|
||||
.rasterizer_state = SDL_GPURasterizerState{.fill_mode = SDL_GPU_FILLMODE_FILL,
|
||||
.cull_mode = SDL_GPU_CULLMODE_NONE,
|
||||
.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE},
|
||||
.target_info = {.color_target_descriptions = colorTargets,
|
||||
.num_color_targets = sizeof(colorTargets) / sizeof(colorTargets[0]),
|
||||
.has_depth_stencil_target = false},
|
||||
};
|
||||
|
||||
SDL_GPUGraphicsPipeline *handle{};
|
||||
if (!(handle = SDL_CreateGPUGraphicsPipeline(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Failed to create a SDL graphics pipeline: ", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnloadShader(pixelShader);
|
||||
UnloadShader(vertexShader);
|
||||
|
||||
res->m_handle = (Handle) handle;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
VOID Pipeline_PostProcess::Bind(IN Handle renderPassHandle)
|
||||
{
|
||||
SDL_BindGPUGraphicsPipeline((SDL_GPURenderPass *) renderPassHandle, (SDL_GPUGraphicsPipeline *) m_handle);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
106
Src/IAEngine/imp/cpp/Rendering/Pipeline/UnlitMesh.cpp
Normal file
106
Src/IAEngine/imp/cpp/Rendering/Pipeline/UnlitMesh.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
// 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/Rendering/Pipeline/UnlitMesh.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include <EmbeddedShaders.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_GPUDevice *g_gpuDevice;
|
||||
EXTERN SDL_Window *g_windowHandle;
|
||||
|
||||
Pipeline_UnlitMesh::~Pipeline_UnlitMesh()
|
||||
{
|
||||
if (m_handle)
|
||||
SDL_ReleaseGPUGraphicsPipeline(g_gpuDevice, (SDL_GPUGraphicsPipeline *) m_handle);
|
||||
}
|
||||
|
||||
RefPtr<Pipeline_UnlitMesh> Pipeline_UnlitMesh::Create()
|
||||
{
|
||||
const auto res = MakeRefPtr<Pipeline_UnlitMesh>();
|
||||
|
||||
const auto vertexShader = LoadShaderFromMemory(ShaderStage::VERTEX, SHADER_SOURCE_UNLITMESH_VERT,
|
||||
sizeof(SHADER_SOURCE_UNLITMESH_VERT), 0, 3, 0, 0);
|
||||
const auto pixelShader = LoadShaderFromMemory(ShaderStage::PIXEL, SHADER_SOURCE_UNLITMESH_FRAG,
|
||||
sizeof(SHADER_SOURCE_UNLITMESH_FRAG), 1, 1, 0, 0);
|
||||
|
||||
SDL_GPUColorTargetDescription colorTargets[] = {{
|
||||
.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
|
||||
}};
|
||||
SDL_GPUVertexBufferDescription vertexBuffers[] = {{
|
||||
.slot = 0,
|
||||
.pitch = sizeof(MeshVertex),
|
||||
.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
|
||||
.instance_step_rate = 0,
|
||||
}};
|
||||
SDL_GPUVertexAttribute vertexAttributes[] = {
|
||||
{.location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0},
|
||||
{.location = 1,
|
||||
.buffer_slot = 0,
|
||||
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
|
||||
.offset = sizeof(glm::vec3)},
|
||||
{.location = 2,
|
||||
.buffer_slot = 0,
|
||||
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4,
|
||||
.offset = sizeof(glm::vec3) + sizeof(glm::vec2)},
|
||||
};
|
||||
SDL_GPUGraphicsPipelineCreateInfo createInfo = {
|
||||
.vertex_shader = (SDL_GPUShader *) vertexShader,
|
||||
.fragment_shader = (SDL_GPUShader *) pixelShader,
|
||||
.vertex_input_state =
|
||||
SDL_GPUVertexInputState{.vertex_buffer_descriptions = vertexBuffers,
|
||||
.num_vertex_buffers = sizeof(vertexBuffers) / sizeof(vertexBuffers[0]),
|
||||
.vertex_attributes = vertexAttributes,
|
||||
.num_vertex_attributes =
|
||||
sizeof(vertexAttributes) / sizeof(vertexAttributes[0])},
|
||||
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
|
||||
.rasterizer_state = SDL_GPURasterizerState{.fill_mode = SDL_GPU_FILLMODE_FILL,
|
||||
.cull_mode = SDL_GPU_CULLMODE_NONE,
|
||||
.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE},
|
||||
.depth_stencil_state = SDL_GPUDepthStencilState{.compare_op = SDL_GPU_COMPAREOP_GREATER_OR_EQUAL,
|
||||
.write_mask = 0xFF,
|
||||
.enable_depth_test = true,
|
||||
.enable_depth_write = true,
|
||||
.enable_stencil_test = false},
|
||||
.target_info = {.color_target_descriptions = colorTargets,
|
||||
.num_color_targets = sizeof(colorTargets) / sizeof(colorTargets[0]),
|
||||
.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM,
|
||||
.has_depth_stencil_target = true},
|
||||
};
|
||||
|
||||
SDL_GPUGraphicsPipeline *handle{};
|
||||
if (!(handle = SDL_CreateGPUGraphicsPipeline(g_gpuDevice, &createInfo)))
|
||||
{
|
||||
IAE_LOG_ERROR("Failed to create a SDL graphics pipeline: ", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnloadShader(pixelShader);
|
||||
UnloadShader(vertexShader);
|
||||
|
||||
res->m_handle = (Handle) handle;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
VOID Pipeline_UnlitMesh::Bind(IN Handle renderPassHandle)
|
||||
{
|
||||
SDL_BindGPUGraphicsPipeline((SDL_GPURenderPass *) renderPassHandle, (SDL_GPUGraphicsPipeline *) m_handle);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
417
Src/IAEngine/imp/cpp/Rendering/Renderer.cpp
Normal file
417
Src/IAEngine/imp/cpp/Rendering/Renderer.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
// 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/IAEngine.hpp>
|
||||
#include <IAEngine/Rendering/Camera.hpp>
|
||||
#include <IAEngine/Rendering/DebugDraw.hpp>
|
||||
#include <IAEngine/Rendering/GPUBuffer.hpp>
|
||||
#include <IAEngine/Rendering/GPUTexture.hpp>
|
||||
#include <IAEngine/Rendering/Pipeline/PostProcess.hpp>
|
||||
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include <backends/imgui_impl_sdl3.h>
|
||||
#include <backends/imgui_impl_sdlgpu3.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
struct Mesh
|
||||
{
|
||||
INT32 IndexCount{};
|
||||
RefPtr<GPUBuffer> IndexBuffer;
|
||||
RefPtr<GPUBuffer> VertexBuffer;
|
||||
};
|
||||
|
||||
struct RenderState
|
||||
{
|
||||
BOOL FlippedH{false};
|
||||
BOOL FlippedV{false};
|
||||
BOOL CameraRelative{true};
|
||||
BOOL ScissorEnabled{false};
|
||||
glm::vec2 TextureOffset{0.0f, 0.0f};
|
||||
SDL_Rect Scissor{0, 0, 0, 0};
|
||||
};
|
||||
|
||||
Vector<Mesh *> g_meshes{};
|
||||
RenderState g_renderState{};
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
EXTERN SDL_Window *g_windowHandle;
|
||||
|
||||
INT32 Renderer::s_width{};
|
||||
INT32 Renderer::s_height{};
|
||||
|
||||
SDL_GPUDevice *g_gpuDevice{};
|
||||
|
||||
ImDrawData *g_imDrawData{};
|
||||
|
||||
// Render State
|
||||
SDL_GPUCommandBuffer *g_cmdBuffer{};
|
||||
SDL_GPURenderPass *g_renderPass{};
|
||||
SDL_GPUTexture *g_swpChainTexture{};
|
||||
SDL_GPUTexture *g_depthBufferTexture{};
|
||||
SDL_GPUTexture *g_sceneDrawBufferTexture{};
|
||||
SDL_GPUTexture *g_debugDrawBufferTexture{};
|
||||
|
||||
RefPtr<Pipeline_UnlitMesh> g_pipelineUnlitMesh;
|
||||
RefPtr<Pipeline_PostProcess> g_pipelinePostProcess;
|
||||
|
||||
Camera2D g_camera{};
|
||||
|
||||
glm::mat4 matProjection{1.0f};
|
||||
glm::mat4 matView{1.0f};
|
||||
glm::mat4 matModel{1.0f};
|
||||
|
||||
glm::mat4 matIdentity{1.0f};
|
||||
|
||||
SDL_Rect g_defaultScissor{};
|
||||
|
||||
Handle g_meshHandleQuad{};
|
||||
|
||||
Texture g_whiteFillTexture{};
|
||||
Texture g_whiteStrokeTexture{};
|
||||
|
||||
SDL_GPUColorTargetInfo colorTargetInfo = {0};
|
||||
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {0};
|
||||
|
||||
BOOL Renderer::Initialize()
|
||||
{
|
||||
SDL_GetWindowSizeInPixels(g_windowHandle, &s_width, &s_height);
|
||||
|
||||
if (!(g_gpuDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, Engine::IsDebugMode, nullptr)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't create SDL3 GPU Device: ", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SDL_ClaimWindowForGPUDevice(g_gpuDevice, g_windowHandle))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't initialize SDL3 GPU for the window: ", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
SDL_SetGPUSwapchainParameters(g_gpuDevice, g_windowHandle, SDL_GPU_SWAPCHAINCOMPOSITION_SDR,
|
||||
SDL_GPU_PRESENTMODE_VSYNC);
|
||||
|
||||
DebugDraw::Initailize();
|
||||
|
||||
if (!GPUBuffer::InitializeStagingBuffer())
|
||||
return false;
|
||||
|
||||
{
|
||||
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
|
||||
.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
|
||||
.usage =
|
||||
SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER,
|
||||
.width = (UINT32) s_width,
|
||||
.height = (UINT32) s_height,
|
||||
.layer_count_or_depth = 1,
|
||||
.num_levels = 1,
|
||||
.sample_count = SDL_GPU_SAMPLECOUNT_1};
|
||||
g_sceneDrawBufferTexture = SDL_CreateGPUTexture(g_gpuDevice, &createInfo);
|
||||
g_debugDrawBufferTexture = SDL_CreateGPUTexture(g_gpuDevice, &createInfo);
|
||||
}
|
||||
{
|
||||
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
|
||||
.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM,
|
||||
.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
|
||||
.width = (UINT32) s_width,
|
||||
.height = (UINT32) s_height,
|
||||
.layer_count_or_depth = 1,
|
||||
.num_levels = 1,
|
||||
.sample_count = SDL_GPU_SAMPLECOUNT_1};
|
||||
g_depthBufferTexture = SDL_CreateGPUTexture(g_gpuDevice, &createInfo);
|
||||
}
|
||||
|
||||
GPUTexture::Initialize();
|
||||
|
||||
g_pipelineUnlitMesh = Pipeline_UnlitMesh::Create();
|
||||
g_pipelinePostProcess = Pipeline_PostProcess::Create();
|
||||
|
||||
matProjection = glm::orthoLH(0.0f, (FLOAT32) s_width, (FLOAT32) s_height, 0.0f, -2097152.0f, 2097152.0f);
|
||||
|
||||
g_defaultScissor.x = 0;
|
||||
g_defaultScissor.y = 0;
|
||||
g_defaultScissor.w = s_width;
|
||||
g_defaultScissor.h = s_height;
|
||||
|
||||
{ // Generate default textures
|
||||
constexpr auto size = 100;
|
||||
constexpr auto strokeWeight = 2;
|
||||
const auto data = new UINT32[size * size];
|
||||
memset(data, 0, size * size * 4);
|
||||
for (SIZE_T i = 0; i < size; i++)
|
||||
{
|
||||
for (SIZE_T j = 0; j < strokeWeight; j++)
|
||||
{
|
||||
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;
|
||||
g_whiteFillTexture = Engine::CreateTexture((PCUINT8) data, size, size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
g_meshHandleQuad = CreateMesh(
|
||||
{
|
||||
{glm::vec3{0, 1, 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{1, 0, 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}},
|
||||
},
|
||||
{0, 1, 2, 2, 3, 0});
|
||||
|
||||
colorTargetInfo.clear_color = SDL_FColor{0.33f, 0.33f, 0.33f, 1.0f};
|
||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
depthStencilTargetInfo.cycle = true;
|
||||
depthStencilTargetInfo.clear_depth = 0;
|
||||
depthStencilTargetInfo.clear_stencil = 0;
|
||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||
depthStencilTargetInfo.stencil_load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
depthStencilTargetInfo.stencil_store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VOID Renderer::Terminate()
|
||||
{
|
||||
SDL_WaitForGPUIdle(g_gpuDevice);
|
||||
|
||||
for (auto &mesh : g_meshes)
|
||||
{
|
||||
mesh->VertexBuffer.reset();
|
||||
mesh->IndexBuffer.reset();
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
g_pipelineUnlitMesh.reset();
|
||||
g_pipelinePostProcess.reset();
|
||||
|
||||
GPUTexture::Terminate();
|
||||
|
||||
GPUBuffer::TerminateStagingBuffer();
|
||||
|
||||
SDL_ReleaseGPUTexture(g_gpuDevice, g_depthBufferTexture);
|
||||
SDL_ReleaseGPUTexture(g_gpuDevice, g_sceneDrawBufferTexture);
|
||||
SDL_ReleaseGPUTexture(g_gpuDevice, g_debugDrawBufferTexture);
|
||||
|
||||
DebugDraw::Terminate();
|
||||
|
||||
SDL_ReleaseWindowFromGPUDevice(g_gpuDevice, g_windowHandle);
|
||||
SDL_DestroyGPUDevice(g_gpuDevice);
|
||||
}
|
||||
|
||||
VOID Renderer::BeginFrame()
|
||||
{
|
||||
if (!(g_cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice)))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't acquire SDL3 GPU command buffer: ", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
colorTargetInfo.texture = g_sceneDrawBufferTexture;
|
||||
depthStencilTargetInfo.texture = g_depthBufferTexture;
|
||||
|
||||
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
||||
|
||||
g_pipelineUnlitMesh->Bind((Handle) g_renderPass);
|
||||
SDL_PushGPUVertexUniformData(g_cmdBuffer, 0, &matProjection, sizeof(matProjection));
|
||||
matView = g_camera.GetViewMatrix();
|
||||
SDL_PushGPUVertexUniformData(g_cmdBuffer, 1, &matView, sizeof(matView));
|
||||
}
|
||||
|
||||
VOID Renderer::EndFrame()
|
||||
{
|
||||
SDL_EndGPURenderPass(g_renderPass);
|
||||
|
||||
ImGui_ImplSDLGPU3_NewFrame();
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
DebugDraw::Draw();
|
||||
ImGui::Render();
|
||||
g_imDrawData = ImGui::GetDrawData();
|
||||
ImGui_ImplSDLGPU3_PrepareDrawData(g_imDrawData, g_cmdBuffer);
|
||||
colorTargetInfo.texture = g_debugDrawBufferTexture;
|
||||
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, nullptr);
|
||||
ImGui_ImplSDLGPU3_RenderDrawData(g_imDrawData, g_cmdBuffer, g_renderPass);
|
||||
SDL_EndGPURenderPass(g_renderPass);
|
||||
|
||||
if (!SDL_WaitAndAcquireGPUSwapchainTexture(g_cmdBuffer, g_windowHandle, &g_swpChainTexture, (PUINT32) &s_width,
|
||||
(PUINT32) &s_height))
|
||||
{
|
||||
IAE_LOG_ERROR("Couldn't acquire SDL3 GPU Swapchain texture: ", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_swpChainTexture)
|
||||
return;
|
||||
|
||||
colorTargetInfo.texture = g_swpChainTexture;
|
||||
|
||||
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, nullptr);
|
||||
g_pipelinePostProcess->Bind((Handle) g_renderPass);
|
||||
SDL_GPUTextureSamplerBinding textureBindings[2] = {
|
||||
{
|
||||
.texture = g_sceneDrawBufferTexture,
|
||||
.sampler = (SDL_GPUSampler*)GPUTexture::GetDefaultSampler()
|
||||
},
|
||||
{
|
||||
.texture = g_debugDrawBufferTexture,
|
||||
.sampler = (SDL_GPUSampler*)GPUTexture::GetDefaultSampler()
|
||||
},
|
||||
};
|
||||
SDL_BindGPUFragmentSamplers(g_renderPass, 0, textureBindings, 2);
|
||||
SDL_DrawGPUPrimitives(g_renderPass, 6, 1, 0, 0);
|
||||
SDL_EndGPURenderPass(g_renderPass);
|
||||
|
||||
SDL_SubmitGPUCommandBuffer(g_cmdBuffer);
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_FlippedH(IN BOOL value)
|
||||
{
|
||||
g_renderState.FlippedH = value;
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_FlippedV(IN BOOL value)
|
||||
{
|
||||
g_renderState.FlippedV = value;
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_CameraRelative(IN BOOL value)
|
||||
{
|
||||
g_renderState.CameraRelative = value;
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_ScissorEnabled(IN BOOL value)
|
||||
{
|
||||
g_renderState.ScissorEnabled = value;
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_Scissor(IN CONST glm::vec4 ®ion)
|
||||
{
|
||||
g_renderState.Scissor.x = region.x;
|
||||
g_renderState.Scissor.y = region.y;
|
||||
g_renderState.Scissor.w = region.z;
|
||||
g_renderState.Scissor.h = region.w;
|
||||
}
|
||||
|
||||
VOID Renderer::SetState_TextureOffset(IN FLOAT32 u, IN FLOAT32 v)
|
||||
{
|
||||
g_renderState.TextureOffset = {u, v};
|
||||
}
|
||||
|
||||
Camera2D *Renderer::GetCamera()
|
||||
{
|
||||
return &g_camera;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Handle Renderer::GetMesh_Quad()
|
||||
{
|
||||
return g_meshHandleQuad;
|
||||
}
|
||||
|
||||
Handle Renderer::CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices)
|
||||
{
|
||||
const auto mesh = CreateUnmanagedMesh(vertices, indices);
|
||||
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])));
|
||||
mesh->IndexBuffer = GPUBuffer::Create(GPUBuffer::Usage::INDEX, indices.data(),
|
||||
static_cast<UINT32>(indices.size() * sizeof(indices[0])));
|
||||
mesh->IndexCount = static_cast<UINT32>(indices.size());
|
||||
return (Handle) mesh;
|
||||
}
|
||||
|
||||
VOID Renderer::DestroyUnmanagedMesh(IN Handle handle)
|
||||
{
|
||||
delete ((Mesh *) handle);
|
||||
}
|
||||
|
||||
VOID Renderer::Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position,
|
||||
IN CONST glm::vec2 &scale, IN FLOAT32 rotation, IN UINT8 layerIndex, IN INT16 sortIndex,
|
||||
IN CONST glm::vec4 &colorOverlay)
|
||||
{
|
||||
IA_ASSERT(sortIndex <= 0x1FFF);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
STATIC struct
|
||||
{
|
||||
INT32 FlippedH{false};
|
||||
INT32 FlippedV{false};
|
||||
glm::vec2 TextureOffset{0.0f, 0.0f};
|
||||
glm::vec4 ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
} s_fragmentUniform{};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
if (g_renderState.CameraRelative)
|
||||
SDL_PushGPUVertexUniformData(g_cmdBuffer, 1, &matView, sizeof(matView));
|
||||
else
|
||||
SDL_PushGPUVertexUniformData(g_cmdBuffer, 1, &matIdentity, sizeof(matIdentity));
|
||||
if (Engine::GetActiveScene()->YSortingEnabled())
|
||||
sortIndex += static_cast<INT16>(position.y);
|
||||
matModel =
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y,
|
||||
static_cast<FLOAT32>((layerIndex << 13) | (sortIndex & 0x1FFF))});
|
||||
matModel = glm::rotate(matModel, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
matModel = glm::scale(matModel, glm::vec3{scale.x, scale.y, 1.0f});
|
||||
SDL_PushGPUVertexUniformData(g_cmdBuffer, 2, &matModel, sizeof(matModel));
|
||||
|
||||
s_fragmentUniform.ColorOverlay = colorOverlay;
|
||||
s_fragmentUniform.FlippedH = g_renderState.FlippedH;
|
||||
s_fragmentUniform.FlippedV = g_renderState.FlippedV;
|
||||
s_fragmentUniform.TextureOffset = g_renderState.TextureOffset;
|
||||
SDL_GPUTextureSamplerBinding textureBinding{
|
||||
.texture = (SDL_GPUTexture *) (textureHandle ? textureHandle : g_whiteFillTexture.GetHandle()),
|
||||
.sampler = (SDL_GPUSampler *) GPUTexture::GetDefaultSampler()};
|
||||
SDL_BindGPUFragmentSamplers(g_renderPass, 0, &textureBinding, 1);
|
||||
SDL_PushGPUFragmentUniformData(g_cmdBuffer, 0, &s_fragmentUniform, sizeof(s_fragmentUniform));
|
||||
|
||||
if (g_renderState.ScissorEnabled)
|
||||
SDL_SetGPUScissor(g_renderPass, &g_renderState.Scissor);
|
||||
else
|
||||
SDL_SetGPUScissor(g_renderPass, &g_defaultScissor);
|
||||
|
||||
const auto mesh = (Mesh *) meshHandle;
|
||||
SDL_GPUBufferBinding bufferBindings[] = {
|
||||
{.buffer = (SDL_GPUBuffer *) mesh->VertexBuffer->GetHandle(), .offset = 0},
|
||||
{.buffer = (SDL_GPUBuffer *) mesh->IndexBuffer->GetHandle(), .offset = 0}};
|
||||
SDL_BindGPUVertexBuffers(g_renderPass, 0, bufferBindings, 1);
|
||||
SDL_BindGPUIndexBuffer(g_renderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT);
|
||||
SDL_DrawGPUIndexedPrimitives(g_renderPass, mesh->IndexCount, 1, 0, 0, 0);
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,49 +0,0 @@
|
||||
#include <IAEngine/IAEngine.hpp>
|
||||
#include <IAEngine/ResourceManager.hpp>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
ResourceManager::ResourceManager(IN Engine *engine) : m_engine(engine)
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<Texture> ResourceManager::CreateTexture(IN CONST Span<CONST UINT8> &encodedData)
|
||||
{
|
||||
return CreateTexture(encodedData.data(), encodedData.size());
|
||||
}
|
||||
|
||||
RefPtr<Texture> ResourceManager::CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize)
|
||||
{
|
||||
INT32 w, h, nrChannels;
|
||||
const auto pixels = stbi_load_from_memory(encodedData, encodedDataSize, &w, &h, &nrChannels, STBI_rgb_alpha);
|
||||
if (!pixels)
|
||||
THROW_INVALID_DATA("Failed to decode the provided image data");
|
||||
const auto result = CreateTexture((PCUINT8) pixels, w, h);
|
||||
STBI_FREE(pixels);
|
||||
return result;
|
||||
}
|
||||
|
||||
RefPtr<Texture> ResourceManager::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
|
||||
{
|
||||
const auto result = MakeRefPtr<Texture>(m_engine);
|
||||
|
||||
result->m_width = width;
|
||||
result->m_height = height;
|
||||
|
||||
SDL_Surface *surface =
|
||||
SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_RGBA32, (void *) rgbaData, width << 2);
|
||||
if (!surface)
|
||||
THROW_UNKNOWN("Failed to create SDL surface: ", SDL_GetError());
|
||||
result->m_handle = SDL_CreateTextureFromSurface((SDL_Renderer *) m_engine->GetRendererHandle(), surface);
|
||||
if (!result->m_handle)
|
||||
THROW_UNKNOWN("Failed to create SDL Texture: ", SDL_GetError());
|
||||
SDL_DestroySurface(surface);
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,40 +1,42 @@
|
||||
// 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/Scene.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Scene::Scene(IN Engine *engine) : m_engine(engine)
|
||||
Scene::~Scene()
|
||||
{
|
||||
for (auto &n : m_nodes)
|
||||
n.reset();
|
||||
}
|
||||
|
||||
VOID Scene::OnActivate()
|
||||
{
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
VOID Scene::OnDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
VOID Scene::Draw()
|
||||
{
|
||||
for (auto &n : m_nodes)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) >= 0)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < 8; i++) // [IATODO]
|
||||
{
|
||||
for (auto &n : m_nodes)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) != i)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &n : m_nodes)
|
||||
{
|
||||
if (((INT32) n->GetPosition().Z) < 8)
|
||||
continue;
|
||||
n->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
VOID Scene::Update()
|
||||
|
||||
@ -1,31 +1,36 @@
|
||||
// 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/IAEngine.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#define TEXTURE_HANDLE (SDL_Texture *) m_handle
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Texture::Texture(IN Engine *engine) : m_engine(engine)
|
||||
Texture::Texture() : m_handle(0), m_extent({100.0f, 100.0f})
|
||||
{
|
||||
}
|
||||
|
||||
Texture::Texture(IN Handle handle, IN INT32 width, IN INT32 height)
|
||||
: m_handle(handle), m_extent({(FLOAT32) width, (FLOAT32) height})
|
||||
{
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
SDL_DestroyTexture(TEXTURE_HANDLE);
|
||||
}
|
||||
|
||||
VOID Texture::Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation, IN BOOL flipH,
|
||||
IN BOOL flipV, IN CONST iam::Vec4f &colorOverlay) CONST
|
||||
{
|
||||
SDL_FRect rect{.x = position.X, .y = position.Y, .w = m_width * scale.X, .h = m_height * scale.Y};
|
||||
|
||||
SDL_SetTextureColorModFloat(TEXTURE_HANDLE, colorOverlay.X, colorOverlay.Y, colorOverlay.Z);
|
||||
SDL_SetTextureAlphaModFloat(TEXTURE_HANDLE, colorOverlay.W);
|
||||
SDL_RenderTextureRotated((SDL_Renderer *) m_engine->GetRendererHandle(), TEXTURE_HANDLE, nullptr, &rect,
|
||||
rotation, nullptr,
|
||||
(SDL_FlipMode) (SDL_FLIP_NONE | (flipV ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE) |
|
||||
(flipH ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE)));
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -1,3 +1,19 @@
|
||||
// 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/Random.hpp>
|
||||
#include <IAEngine/Time.hpp>
|
||||
|
||||
|
||||
615
Src/IAEngine/imp/cpp/UI.cpp
Normal file
615
Src/IAEngine/imp/cpp/UI.cpp
Normal file
@ -0,0 +1,615 @@
|
||||
// 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/IAEngine.hpp>
|
||||
#include <IAEngine/Rendering/GPUTexture.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
#include <IAEngine/UI.hpp>
|
||||
|
||||
#include <RmlUi/Core.h>
|
||||
#include <RmlUi/Debugger.h>
|
||||
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
#include <IACore/File.hpp>
|
||||
|
||||
#include <IACore/Map.hpp>
|
||||
#include <map>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class RmlUIRenderInterface : public Rml::RenderInterface
|
||||
{
|
||||
public:
|
||||
Rml::CompiledGeometryHandle CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
|
||||
Rml::Span<const int> indices);
|
||||
void RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation,
|
||||
Rml::TextureHandle texture);
|
||||
void ReleaseGeometry(Rml::CompiledGeometryHandle geometry);
|
||||
Rml::TextureHandle LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source);
|
||||
Rml::TextureHandle GenerateTexture(Rml::Span<const Rml::byte> source, Rml::Vector2i source_dimensions);
|
||||
void ReleaseTexture(Rml::TextureHandle texture);
|
||||
void EnableScissorRegion(bool enable);
|
||||
void SetScissorRegion(Rml::Rectanglei region);
|
||||
};
|
||||
|
||||
Vector<Texture> g_textures;
|
||||
RmlUIRenderInterface g_rmlUIRenderInterface{};
|
||||
|
||||
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
|
||||
INT32 GetKeyModifierState()
|
||||
{
|
||||
SDL_Keymod sdl_mods = SDL_GetModState();
|
||||
INT32 keymods = 0;
|
||||
if (sdl_mods & SDL_KMOD_CTRL)
|
||||
keymods |= Rml::Input::KM_CTRL;
|
||||
if (sdl_mods & SDL_KMOD_SHIFT)
|
||||
keymods |= Rml::Input::KM_SHIFT;
|
||||
if (sdl_mods & SDL_KMOD_ALT)
|
||||
keymods |= Rml::Input::KM_ALT;
|
||||
if (sdl_mods & SDL_KMOD_NUM)
|
||||
keymods |= Rml::Input::KM_NUMLOCK;
|
||||
if (sdl_mods & SDL_KMOD_CAPS)
|
||||
keymods |= Rml::Input::KM_CAPSLOCK;
|
||||
return keymods;
|
||||
}
|
||||
|
||||
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
|
||||
INT32 SDLMouseButtonToRml(IN INT32 button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case SDL_BUTTON_LEFT:
|
||||
return 0;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
return 1;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
|
||||
Rml::Input::KeyIdentifier SDLKeyToRml(int sdlkey)
|
||||
{
|
||||
switch (sdlkey)
|
||||
{
|
||||
case SDLK_UNKNOWN:
|
||||
return Rml::Input::KI_UNKNOWN;
|
||||
case SDLK_ESCAPE:
|
||||
return Rml::Input::KI_ESCAPE;
|
||||
case SDLK_SPACE:
|
||||
return Rml::Input::KI_SPACE;
|
||||
case SDLK_0:
|
||||
return Rml::Input::KI_0;
|
||||
case SDLK_1:
|
||||
return Rml::Input::KI_1;
|
||||
case SDLK_2:
|
||||
return Rml::Input::KI_2;
|
||||
case SDLK_3:
|
||||
return Rml::Input::KI_3;
|
||||
case SDLK_4:
|
||||
return Rml::Input::KI_4;
|
||||
case SDLK_5:
|
||||
return Rml::Input::KI_5;
|
||||
case SDLK_6:
|
||||
return Rml::Input::KI_6;
|
||||
case SDLK_7:
|
||||
return Rml::Input::KI_7;
|
||||
case SDLK_8:
|
||||
return Rml::Input::KI_8;
|
||||
case SDLK_9:
|
||||
return Rml::Input::KI_9;
|
||||
case SDLK_A:
|
||||
return Rml::Input::KI_A;
|
||||
case SDLK_B:
|
||||
return Rml::Input::KI_B;
|
||||
case SDLK_C:
|
||||
return Rml::Input::KI_C;
|
||||
case SDLK_D:
|
||||
return Rml::Input::KI_D;
|
||||
case SDLK_E:
|
||||
return Rml::Input::KI_E;
|
||||
case SDLK_F:
|
||||
return Rml::Input::KI_F;
|
||||
case SDLK_G:
|
||||
return Rml::Input::KI_G;
|
||||
case SDLK_H:
|
||||
return Rml::Input::KI_H;
|
||||
case SDLK_I:
|
||||
return Rml::Input::KI_I;
|
||||
case SDLK_J:
|
||||
return Rml::Input::KI_J;
|
||||
case SDLK_K:
|
||||
return Rml::Input::KI_K;
|
||||
case SDLK_L:
|
||||
return Rml::Input::KI_L;
|
||||
case SDLK_M:
|
||||
return Rml::Input::KI_M;
|
||||
case SDLK_N:
|
||||
return Rml::Input::KI_N;
|
||||
case SDLK_O:
|
||||
return Rml::Input::KI_O;
|
||||
case SDLK_P:
|
||||
return Rml::Input::KI_P;
|
||||
case SDLK_Q:
|
||||
return Rml::Input::KI_Q;
|
||||
case SDLK_R:
|
||||
return Rml::Input::KI_R;
|
||||
case SDLK_S:
|
||||
return Rml::Input::KI_S;
|
||||
case SDLK_T:
|
||||
return Rml::Input::KI_T;
|
||||
case SDLK_U:
|
||||
return Rml::Input::KI_U;
|
||||
case SDLK_V:
|
||||
return Rml::Input::KI_V;
|
||||
case SDLK_W:
|
||||
return Rml::Input::KI_W;
|
||||
case SDLK_X:
|
||||
return Rml::Input::KI_X;
|
||||
case SDLK_Y:
|
||||
return Rml::Input::KI_Y;
|
||||
case SDLK_Z:
|
||||
return Rml::Input::KI_Z;
|
||||
case SDLK_SEMICOLON:
|
||||
return Rml::Input::KI_OEM_1;
|
||||
case SDLK_PLUS:
|
||||
return Rml::Input::KI_OEM_PLUS;
|
||||
case SDLK_COMMA:
|
||||
return Rml::Input::KI_OEM_COMMA;
|
||||
case SDLK_MINUS:
|
||||
return Rml::Input::KI_OEM_MINUS;
|
||||
case SDLK_PERIOD:
|
||||
return Rml::Input::KI_OEM_PERIOD;
|
||||
case SDLK_SLASH:
|
||||
return Rml::Input::KI_OEM_2;
|
||||
case SDLK_GRAVE:
|
||||
return Rml::Input::KI_OEM_3;
|
||||
case SDLK_LEFTBRACKET:
|
||||
return Rml::Input::KI_OEM_4;
|
||||
case SDLK_BACKSLASH:
|
||||
return Rml::Input::KI_OEM_5;
|
||||
case SDLK_RIGHTBRACKET:
|
||||
return Rml::Input::KI_OEM_6;
|
||||
case SDLK_DBLAPOSTROPHE:
|
||||
return Rml::Input::KI_OEM_7;
|
||||
case SDLK_KP_0:
|
||||
return Rml::Input::KI_NUMPAD0;
|
||||
case SDLK_KP_1:
|
||||
return Rml::Input::KI_NUMPAD1;
|
||||
case SDLK_KP_2:
|
||||
return Rml::Input::KI_NUMPAD2;
|
||||
case SDLK_KP_3:
|
||||
return Rml::Input::KI_NUMPAD3;
|
||||
case SDLK_KP_4:
|
||||
return Rml::Input::KI_NUMPAD4;
|
||||
case SDLK_KP_5:
|
||||
return Rml::Input::KI_NUMPAD5;
|
||||
case SDLK_KP_6:
|
||||
return Rml::Input::KI_NUMPAD6;
|
||||
case SDLK_KP_7:
|
||||
return Rml::Input::KI_NUMPAD7;
|
||||
case SDLK_KP_8:
|
||||
return Rml::Input::KI_NUMPAD8;
|
||||
case SDLK_KP_9:
|
||||
return Rml::Input::KI_NUMPAD9;
|
||||
case SDLK_KP_ENTER:
|
||||
return Rml::Input::KI_NUMPADENTER;
|
||||
case SDLK_KP_MULTIPLY:
|
||||
return Rml::Input::KI_MULTIPLY;
|
||||
case SDLK_KP_PLUS:
|
||||
return Rml::Input::KI_ADD;
|
||||
case SDLK_KP_MINUS:
|
||||
return Rml::Input::KI_SUBTRACT;
|
||||
case SDLK_KP_PERIOD:
|
||||
return Rml::Input::KI_DECIMAL;
|
||||
case SDLK_KP_DIVIDE:
|
||||
return Rml::Input::KI_DIVIDE;
|
||||
case SDLK_KP_EQUALS:
|
||||
return Rml::Input::KI_OEM_NEC_EQUAL;
|
||||
case SDLK_BACKSPACE:
|
||||
return Rml::Input::KI_BACK;
|
||||
case SDLK_TAB:
|
||||
return Rml::Input::KI_TAB;
|
||||
case SDLK_CLEAR:
|
||||
return Rml::Input::KI_CLEAR;
|
||||
case SDLK_RETURN:
|
||||
return Rml::Input::KI_RETURN;
|
||||
case SDLK_PAUSE:
|
||||
return Rml::Input::KI_PAUSE;
|
||||
case SDLK_CAPSLOCK:
|
||||
return Rml::Input::KI_CAPITAL;
|
||||
case SDLK_PAGEUP:
|
||||
return Rml::Input::KI_PRIOR;
|
||||
case SDLK_PAGEDOWN:
|
||||
return Rml::Input::KI_NEXT;
|
||||
case SDLK_END:
|
||||
return Rml::Input::KI_END;
|
||||
case SDLK_HOME:
|
||||
return Rml::Input::KI_HOME;
|
||||
case SDLK_LEFT:
|
||||
return Rml::Input::KI_LEFT;
|
||||
case SDLK_UP:
|
||||
return Rml::Input::KI_UP;
|
||||
case SDLK_RIGHT:
|
||||
return Rml::Input::KI_RIGHT;
|
||||
case SDLK_DOWN:
|
||||
return Rml::Input::KI_DOWN;
|
||||
case SDLK_INSERT:
|
||||
return Rml::Input::KI_INSERT;
|
||||
case SDLK_DELETE:
|
||||
return Rml::Input::KI_DELETE;
|
||||
case SDLK_HELP:
|
||||
return Rml::Input::KI_HELP;
|
||||
case SDLK_F1:
|
||||
return Rml::Input::KI_F1;
|
||||
case SDLK_F2:
|
||||
return Rml::Input::KI_F2;
|
||||
case SDLK_F3:
|
||||
return Rml::Input::KI_F3;
|
||||
case SDLK_F4:
|
||||
return Rml::Input::KI_F4;
|
||||
case SDLK_F5:
|
||||
return Rml::Input::KI_F5;
|
||||
case SDLK_F6:
|
||||
return Rml::Input::KI_F6;
|
||||
case SDLK_F7:
|
||||
return Rml::Input::KI_F7;
|
||||
case SDLK_F8:
|
||||
return Rml::Input::KI_F8;
|
||||
case SDLK_F9:
|
||||
return Rml::Input::KI_F9;
|
||||
case SDLK_F10:
|
||||
return Rml::Input::KI_F10;
|
||||
case SDLK_F11:
|
||||
return Rml::Input::KI_F11;
|
||||
case SDLK_F12:
|
||||
return Rml::Input::KI_F12;
|
||||
case SDLK_F13:
|
||||
return Rml::Input::KI_F13;
|
||||
case SDLK_F14:
|
||||
return Rml::Input::KI_F14;
|
||||
case SDLK_F15:
|
||||
return Rml::Input::KI_F15;
|
||||
case SDLK_NUMLOCKCLEAR:
|
||||
return Rml::Input::KI_NUMLOCK;
|
||||
case SDLK_SCROLLLOCK:
|
||||
return Rml::Input::KI_SCROLL;
|
||||
case SDLK_LSHIFT:
|
||||
return Rml::Input::KI_LSHIFT;
|
||||
case SDLK_RSHIFT:
|
||||
return Rml::Input::KI_RSHIFT;
|
||||
case SDLK_LCTRL:
|
||||
return Rml::Input::KI_LCONTROL;
|
||||
case SDLK_RCTRL:
|
||||
return Rml::Input::KI_RCONTROL;
|
||||
case SDLK_LALT:
|
||||
return Rml::Input::KI_LMENU;
|
||||
case SDLK_RALT:
|
||||
return Rml::Input::KI_RMENU;
|
||||
case SDLK_LGUI:
|
||||
return Rml::Input::KI_LMETA;
|
||||
case SDLK_RGUI:
|
||||
return Rml::Input::KI_RMETA;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Rml::Input::KI_UNKNOWN;
|
||||
}
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class EventListener : public Rml::EventListener
|
||||
{
|
||||
public:
|
||||
EventListener(IN Rml::ElementDocument *document) : m_document(document)
|
||||
{
|
||||
}
|
||||
|
||||
VOID AddClickListener(IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
m_document->GetElementById(elementId)->AddEventListener("click", this);
|
||||
m_clickCallbacks[elementId] = callback;
|
||||
}
|
||||
|
||||
VOID AddHoverEnterListener(IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
m_document->GetElementById(elementId)->AddEventListener("mouseover", this);
|
||||
m_hoverEnterCallbacks[elementId] = callback;
|
||||
}
|
||||
|
||||
VOID AddHoverExitListener(IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
m_document->GetElementById(elementId)->AddEventListener("mouseout", this);
|
||||
m_hoverExitCallbacks[elementId] = callback;
|
||||
}
|
||||
|
||||
VOID AddPointerDownListener(IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
m_document->GetElementById(elementId)->AddEventListener("mousedown", this);
|
||||
m_pointerDownCallbacks[elementId] = callback;
|
||||
}
|
||||
|
||||
VOID AddPointerUpListener(IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
m_document->GetElementById(elementId)->AddEventListener("mouseup", this);
|
||||
m_pointerUpCallbacks[elementId] = callback;
|
||||
}
|
||||
|
||||
VOID ProcessEvent(IN Rml::Event &event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case Rml::EventId::Click:
|
||||
m_clickCallbacks[event.GetTargetElement()->GetId().c_str()]();
|
||||
break;
|
||||
|
||||
case Rml::EventId::Mouseover:
|
||||
m_hoverEnterCallbacks[event.GetTargetElement()->GetId().c_str()]();
|
||||
break;
|
||||
|
||||
case Rml::EventId::Mouseout:
|
||||
m_hoverExitCallbacks[event.GetTargetElement()->GetId().c_str()]();
|
||||
break;
|
||||
|
||||
case Rml::EventId::Mousedown:
|
||||
m_pointerDownCallbacks[event.GetTargetElement()->GetId().c_str()]();
|
||||
break;
|
||||
|
||||
case Rml::EventId::Mouseup:
|
||||
m_pointerUpCallbacks[event.GetTargetElement()->GetId().c_str()]();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Rml::ElementDocument *CONST m_document;
|
||||
Map<String, std::function<VOID()>> m_clickCallbacks;
|
||||
Map<String, std::function<VOID()>> m_hoverEnterCallbacks;
|
||||
Map<String, std::function<VOID()>> m_hoverExitCallbacks;
|
||||
Map<String, std::function<VOID()>> m_pointerDownCallbacks;
|
||||
Map<String, std::function<VOID()>> m_pointerUpCallbacks;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Rml::Context *g_context{};
|
||||
BOOL g_debuggerEnabled{false};
|
||||
|
||||
std::map<Handle, EventListener *> g_eventListeners;
|
||||
|
||||
struct MainDataModel
|
||||
{
|
||||
Rml::String InputValues[10];
|
||||
} g_mainDataModel;
|
||||
|
||||
VOID UI::Initialize(IN INT32 width, IN INT32 height)
|
||||
{
|
||||
Rml::SetRenderInterface(&g_rmlUIRenderInterface);
|
||||
Rml::Initialise();
|
||||
g_context = Rml::CreateContext("main", Rml::Vector2i(width, height));
|
||||
Rml::Debugger::Initialise(g_context);
|
||||
DisableDebugger();
|
||||
|
||||
if (auto dataModel = g_context->CreateDataModel("main"))
|
||||
{
|
||||
for (INT32 i = 0; i < ((sizeof(MainDataModel::InputValues) / sizeof(MainDataModel::InputValues[0]))); i++)
|
||||
dataModel.Bind(BuildString("InputValue", i).c_str(), &g_mainDataModel.InputValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
VOID UI::Terminate()
|
||||
{
|
||||
Rml::Shutdown();
|
||||
}
|
||||
|
||||
VOID UI::Update()
|
||||
{
|
||||
g_context->Update();
|
||||
}
|
||||
|
||||
VOID UI::Draw()
|
||||
{
|
||||
g_context->Render();
|
||||
}
|
||||
|
||||
VOID UI::OnEvent(IN PVOID _event)
|
||||
{
|
||||
const auto keymods = GetKeyModifierState();
|
||||
const auto event = (SDL_Event *) _event;
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_EventType::SDL_EVENT_MOUSE_MOTION:
|
||||
g_context->ProcessMouseMove(event->motion.x, event->motion.y, keymods);
|
||||
break;
|
||||
case SDL_EventType::SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
g_context->ProcessMouseButtonUp(SDLMouseButtonToRml(event->button.button), keymods);
|
||||
break;
|
||||
case SDL_EventType::SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
g_context->ProcessMouseButtonDown(SDLMouseButtonToRml(event->button.button), keymods);
|
||||
break;
|
||||
case SDL_EventType::SDL_EVENT_KEY_DOWN:
|
||||
if (event->key.key == SDLK_F8)
|
||||
{
|
||||
if (g_debuggerEnabled)
|
||||
DisableDebugger();
|
||||
else
|
||||
EnableDebugger();
|
||||
}
|
||||
g_context->ProcessKeyDown(SDLKeyToRml(event->key.key), keymods);
|
||||
break;
|
||||
case SDL_EventType::SDL_EVENT_KEY_UP:
|
||||
g_context->ProcessKeyUp(SDLKeyToRml(event->key.key), keymods);
|
||||
break;
|
||||
case SDL_EventType::SDL_EVENT_TEXT_INPUT:
|
||||
g_context->ProcessTextInput(Rml::String(&event->text.text[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID UI::OnResize(IN INT32 width, IN INT32 height)
|
||||
{
|
||||
}
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
VOID UI::AddFontFromFile(IN CONST String &path)
|
||||
{
|
||||
Rml::LoadFontFace(path.c_str());
|
||||
}
|
||||
|
||||
VOID UI::EnableDebugger()
|
||||
{
|
||||
Rml::Debugger::SetVisible(g_debuggerEnabled = true);
|
||||
}
|
||||
|
||||
VOID UI::DisableDebugger()
|
||||
{
|
||||
Rml::Debugger::SetVisible(g_debuggerEnabled = false);
|
||||
}
|
||||
|
||||
Handle UI::AddWindowFromFile(IN CONST String &path)
|
||||
{
|
||||
const auto w = g_context->LoadDocument(path.c_str());
|
||||
const auto handle = (Handle) w;
|
||||
g_eventListeners[handle] = new EventListener(w);
|
||||
return handle;
|
||||
}
|
||||
|
||||
VOID UI::ShowWindow(IN Handle handle)
|
||||
{
|
||||
reinterpret_cast<Rml::ElementDocument *>(handle)->Show();
|
||||
}
|
||||
|
||||
VOID UI::HideWindow(IN Handle handle)
|
||||
{
|
||||
reinterpret_cast<Rml::ElementDocument *>(handle)->Hide();
|
||||
}
|
||||
|
||||
VOID UI::AddClickEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
g_eventListeners[handle]->AddClickListener(elementId, callback);
|
||||
}
|
||||
|
||||
VOID UI::AddHoverEnterEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
g_eventListeners[handle]->AddHoverEnterListener(elementId, callback);
|
||||
}
|
||||
|
||||
VOID UI::AddHoverExitEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
g_eventListeners[handle]->AddHoverExitListener(elementId, callback);
|
||||
}
|
||||
|
||||
VOID UI::AddPointerDownEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
g_eventListeners[handle]->AddPointerDownListener(elementId, callback);
|
||||
}
|
||||
|
||||
VOID UI::AddPointerUpEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback)
|
||||
{
|
||||
g_eventListeners[handle]->AddPointerUpListener(elementId, callback);
|
||||
}
|
||||
|
||||
String UI::GetInputValue(IN INT32 index)
|
||||
{
|
||||
return g_mainDataModel.InputValues[index].c_str();
|
||||
}
|
||||
|
||||
VOID UI::SetInputValue(IN INT32 index, IN CONST String &value)
|
||||
{
|
||||
g_mainDataModel.InputValues[index] = Rml::String(value.c_str());
|
||||
}
|
||||
|
||||
VOID UI::DestroyWindow(IN Handle handle)
|
||||
{
|
||||
const auto w = reinterpret_cast<Rml::ElementDocument *>(handle);
|
||||
w->Hide();
|
||||
w->Close();
|
||||
}
|
||||
} // namespace ia::iae
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Rml::CompiledGeometryHandle RmlUIRenderInterface::CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
|
||||
Rml::Span<const int> indices)
|
||||
{
|
||||
Vector<MeshVertex> _vertices;
|
||||
Vector<INT32> _indices;
|
||||
for (const auto &v : vertices)
|
||||
_vertices.pushBack({glm::vec3{v.position.x, v.position.y, 0.0f}, glm::vec2{v.tex_coord.x, v.tex_coord.y},
|
||||
glm::vec4{v.colour.red / 255.0f, v.colour.green / 255.0f, v.colour.blue / 255.0f,
|
||||
v.colour.alpha / 255.0f}});
|
||||
for (const auto &v : indices)
|
||||
_indices.pushBack(v);
|
||||
return Renderer::CreateMesh(_vertices, _indices);
|
||||
}
|
||||
|
||||
void RmlUIRenderInterface::RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation,
|
||||
Rml::TextureHandle texture)
|
||||
{
|
||||
Renderer::SetState_FlippedH(false);
|
||||
Renderer::SetState_FlippedV(false);
|
||||
Renderer::SetState_CameraRelative(false);
|
||||
Renderer::SetState_TextureOffset(0, 0);
|
||||
if (texture)
|
||||
Renderer::Draw(geometry, g_textures[texture - 1].GetHandle(), {translation.x, translation.y}, {1.0f, 1.0f},
|
||||
0.0f, Renderer::MAX_LAYER_INDEX);
|
||||
else
|
||||
Renderer::Draw(geometry, 0, {translation.x, translation.y}, {1.0f, 1.0f}, 0.0f, Renderer::MAX_LAYER_INDEX);
|
||||
}
|
||||
|
||||
void RmlUIRenderInterface::ReleaseGeometry(Rml::CompiledGeometryHandle geometry)
|
||||
{
|
||||
}
|
||||
|
||||
Rml::TextureHandle RmlUIRenderInterface::LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source)
|
||||
{
|
||||
g_textures.pushBack(Engine::CreateTexture(File::ReadToVector(source.c_str())));
|
||||
return g_textures.size();
|
||||
}
|
||||
|
||||
Rml::TextureHandle RmlUIRenderInterface::GenerateTexture(Rml::Span<const Rml::byte> source,
|
||||
Rml::Vector2i source_dimensions)
|
||||
{
|
||||
g_textures.pushBack(
|
||||
Engine::CreateTexture((PCUINT8) source.data(), (INT32) source_dimensions.x, (INT32) source_dimensions.y));
|
||||
return g_textures.size();
|
||||
}
|
||||
|
||||
void RmlUIRenderInterface::ReleaseTexture(Rml::TextureHandle texture)
|
||||
{
|
||||
}
|
||||
|
||||
void RmlUIRenderInterface::EnableScissorRegion(bool enable)
|
||||
{
|
||||
Renderer::SetState_ScissorEnabled(enable);
|
||||
}
|
||||
|
||||
void RmlUIRenderInterface::SetScissorRegion(Rml::Rectanglei region)
|
||||
{
|
||||
Renderer::SetState_Scissor({region.Left(), region.Top(), region.Right(), region.Bottom()});
|
||||
}
|
||||
} // namespace ia::iae
|
||||
23
Src/IAEngine/imp/glsl/PostProcessing/PostProcess.frag
Normal file
23
Src/IAEngine/imp/glsl/PostProcessing/PostProcess.frag
Normal file
@ -0,0 +1,23 @@
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec2 inTexCoord;
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D sceneDrawTexture;
|
||||
layout(set = 2, binding = 1) uniform sampler2D debugDrawTexture;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
vec4 overlay(vec4 background, vec4 foreground) {
|
||||
return mix(
|
||||
2.0 * background * foreground,
|
||||
1.0 - 2.0 * (1.0 - background) * (1.0 - foreground),
|
||||
step(0.5, background)
|
||||
);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(inTexCoord.x, 1.0 - inTexCoord.y);
|
||||
outColor = overlay(texture(debugDrawTexture, uv), texture(sceneDrawTexture, uv));
|
||||
}
|
||||
10
Src/IAEngine/imp/glsl/PostProcessing/PostProcess.vert
Normal file
10
Src/IAEngine/imp/glsl/PostProcessing/PostProcess.vert
Normal file
@ -0,0 +1,10 @@
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) out vec2 outTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(outTexCoord * 2.0f - 1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
26
Src/IAEngine/imp/glsl/UnlitMesh/UnlitMesh.frag
Normal file
26
Src/IAEngine/imp/glsl/UnlitMesh/UnlitMesh.frag
Normal file
@ -0,0 +1,26 @@
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec2 inTexCoord;
|
||||
layout(location = 1) in vec4 inVertexColor;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D texSampler;
|
||||
layout(set = 3, binding = 0) uniform UniformBufferObject {
|
||||
bool flippedH;
|
||||
bool flippedV;
|
||||
vec2 uvOffset;
|
||||
vec4 colorOverlay;
|
||||
} ubo;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = inTexCoord;
|
||||
uv += ubo.uvOffset;
|
||||
if(ubo.flippedH) uv.x = 1.0 - uv.x;
|
||||
if(ubo.flippedV) uv.y = 1.0 - uv.y;
|
||||
outColor = texture(texSampler, uv) * inVertexColor * ubo.colorOverlay;
|
||||
if(outColor.w < 0.1)
|
||||
discard;
|
||||
}
|
||||
26
Src/IAEngine/imp/glsl/UnlitMesh/UnlitMesh.vert
Normal file
26
Src/IAEngine/imp/glsl/UnlitMesh/UnlitMesh.vert
Normal file
@ -0,0 +1,26 @@
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec3 inPosition;
|
||||
layout (location = 1) in vec2 inTexCoord;
|
||||
layout (location = 2) in vec4 inVertexColor;
|
||||
|
||||
layout(location = 0) out vec2 outTexCoord;
|
||||
layout(location = 1) out vec4 outVertexColor;
|
||||
|
||||
layout(set = 1, binding = 0) uniform UBO_Vertex_PerScene {
|
||||
mat4 projection;
|
||||
} uboPerScene;
|
||||
layout(set = 1, binding = 1) uniform UBO_Vertex_PerFrame {
|
||||
mat4 view;
|
||||
} uboPerFrame;
|
||||
layout(set = 1, binding = 2) uniform UBO_Vertex_PerDraw {
|
||||
mat4 model;
|
||||
} uboPerDraw;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = uboPerScene.projection * uboPerFrame.view * uboPerDraw.model * vec4(inPosition, 1.0f);
|
||||
outTexCoord = inTexCoord;
|
||||
outVertexColor = inVertexColor;
|
||||
}
|
||||
39
Src/IAEngine/imp/hpp/EmbeddedShaders.hpp
Normal file
39
Src/IAEngine/imp/hpp/EmbeddedShaders.hpp
Normal file
File diff suppressed because one or more lines are too long
@ -1433,6 +1433,15 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i
|
||||
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
||||
}
|
||||
|
||||
STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp, size_t& readSize)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer,len);
|
||||
const auto data = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
||||
readSize = s.img_buffer - s.img_buffer_original;
|
||||
return data;
|
||||
}
|
||||
|
||||
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
|
||||
@ -63,12 +63,14 @@ namespace ia::iae
|
||||
public:
|
||||
STATIC VOID Initialize();
|
||||
STATIC VOID Terminate();
|
||||
|
||||
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
|
||||
|
||||
STATIC VOID Update();
|
||||
|
||||
STATIC INT64 CreateTrack();
|
||||
STATIC VOID DestroyTrack(IN INT64 trackHandle);
|
||||
|
||||
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
|
||||
|
||||
STATIC VOID QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle);
|
||||
STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay);
|
||||
STATIC VOID ClearTrack(IN INT64 trackHandle);
|
||||
|
||||
@ -22,9 +22,15 @@
|
||||
#include <IACore/String.hpp>
|
||||
#include <IACore/Exception.hpp>
|
||||
|
||||
#include <IAMath/Vec.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale
|
||||
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective
|
||||
#include <glm/ext/scalar_constants.hpp> // glm::pi
|
||||
|
||||
#define IAE_LOG_TAG "IAE"
|
||||
#define IAE_LOG_TAG "[IAE]: "
|
||||
|
||||
#define IAE_LOG_INFO(...) ia::Logger::Info(IAE_LOG_TAG, __VA_ARGS__)
|
||||
#define IAE_LOG_WARN(...) ia::Logger::Warn(IAE_LOG_TAG, __VA_ARGS__)
|
||||
|
||||
@ -16,36 +16,39 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/Component.hpp>
|
||||
#include <IAEngine/Components/TextureRenderer.hpp>
|
||||
#include <IAEngine/Rendering/GPUTexture.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class AtlasRendererComponent : public IComponent
|
||||
class AtlasRendererComponent : public TextureRendererComponent
|
||||
{
|
||||
public:
|
||||
struct TileGrid
|
||||
{
|
||||
iam::Vec3f Position{};
|
||||
glm::vec3 Position{};
|
||||
|
||||
INT32 TileWidth{};
|
||||
INT32 TileHeight{};
|
||||
INT32 TileCountX{};
|
||||
INT32 TileCountY{};
|
||||
|
||||
Vector<Handle> m_tileTextures{};
|
||||
|
||||
private:
|
||||
Vector<class Texture> m_tileTextures{};
|
||||
|
||||
friend class AtlasRendererComponent;
|
||||
};
|
||||
|
||||
public:
|
||||
AtlasRendererComponent(IN Node *node);
|
||||
~AtlasRendererComponent();
|
||||
|
||||
public:
|
||||
Handle AddTexture(IN RefPtr<Texture> texture);
|
||||
|
||||
VOID SetGrid(IN CONST TileGrid &grid);
|
||||
VOID SetGridTileTexture(IN INT32 x, IN INT32 y, IN Handle textureHandle);
|
||||
VOID SetGrid(IN INT32 tileWidth, IN INT32 tileHeight, IN INT32 tileCountX, IN INT32 tileCountY);
|
||||
VOID SetGridTileTexture(IN INT32 index, IN class Texture texture);
|
||||
VOID SetGridTileTexture(IN INT32 x, IN INT32 y, IN class Texture texture);
|
||||
VOID BakeGrid();
|
||||
|
||||
public:
|
||||
VOID Draw();
|
||||
@ -53,6 +56,6 @@ namespace ia::iae
|
||||
|
||||
private:
|
||||
TileGrid m_tileGrid{};
|
||||
Vector<RefPtr<Texture>> m_textures;
|
||||
RefPtr<GPUTexture> m_bakedGPUTexture{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -24,13 +24,21 @@ namespace ia::iae
|
||||
|
||||
class IComponent
|
||||
{
|
||||
public:
|
||||
IComponent(IN Node* node): m_node(node) {}
|
||||
|
||||
public:
|
||||
IComponent(IN Node *node) : m_node(node)
|
||||
{
|
||||
}
|
||||
|
||||
PURE_VIRTUAL(VOID Draw());
|
||||
PURE_VIRTUAL(VOID Update());
|
||||
|
||||
protected:
|
||||
Node* m_node{};
|
||||
public:
|
||||
Node *GetNode()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
protected:
|
||||
Node *m_node{};
|
||||
};
|
||||
}
|
||||
} // namespace ia::iae
|
||||
81
Src/IAEngine/inc/IAEngine/Components/Physics.hpp
Normal file
81
Src/IAEngine/inc/IAEngine/Components/Physics.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
// 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 PhysicsComponent : public IComponent
|
||||
{
|
||||
public:
|
||||
struct Collider
|
||||
{
|
||||
BOOL IsTrigger{false};
|
||||
glm::vec2 Position{};
|
||||
glm::vec2 Size{};
|
||||
};
|
||||
|
||||
public:
|
||||
PhysicsComponent(IN Node *node);
|
||||
~PhysicsComponent();
|
||||
|
||||
Handle CreateCollider();
|
||||
Handle AddCollider(IN Collider collider);
|
||||
Collider &GetCollider(IN Handle handle);
|
||||
|
||||
VOID Move(IN glm::vec2 direction);
|
||||
|
||||
VOID Jump(IN FLOAT32 force);
|
||||
|
||||
public:
|
||||
BOOL &IsDynamic()
|
||||
{
|
||||
return m_isDynamic;
|
||||
}
|
||||
|
||||
FLOAT32 &MovementSpeed()
|
||||
{
|
||||
return m_movementSpeed;
|
||||
}
|
||||
|
||||
Vector<Collider> &Colliders()
|
||||
{
|
||||
return m_colliders;
|
||||
}
|
||||
|
||||
CONST glm::vec2& GetVelocity() CONST
|
||||
{
|
||||
return m_velocity;
|
||||
}
|
||||
|
||||
public:
|
||||
VOID Draw();
|
||||
VOID Update();
|
||||
|
||||
private:
|
||||
glm::vec2 m_velocity{};
|
||||
BOOL m_isDynamic{false};
|
||||
Vector<Collider> m_colliders;
|
||||
FLOAT32 m_movementSpeed{1.0f};
|
||||
Handle m_physicsHandle{INVALID_HANDLE};
|
||||
|
||||
VOID OnCollision(IN PhysicsComponent *other);
|
||||
|
||||
friend class Physics;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -16,23 +16,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/Component.hpp>
|
||||
#include <IAEngine/Components/TextureRenderer.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class SpriteRendererComponent : public IComponent
|
||||
class SpriteRendererComponent : public TextureRendererComponent
|
||||
{
|
||||
public:
|
||||
struct AnimationKeyFrame
|
||||
{
|
||||
Texture Texture;
|
||||
INT32 Duration{100};
|
||||
iam::Vec3f Position{};
|
||||
iam::Vec3f Rotation{};
|
||||
iam::Vec3f Scale{1.0f, 1.0f, 1.0f};
|
||||
iam::Vec4f ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
BOOL ShouldInterpolate{};
|
||||
RefPtr<Texture> Texture;
|
||||
|
||||
FLOAT32 Rotation{};
|
||||
glm::vec2 Position{};
|
||||
glm::vec2 Scale{1.0f, 1.0f};
|
||||
glm::vec4 ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
|
||||
struct Animation
|
||||
@ -49,6 +50,9 @@ namespace ia::iae
|
||||
VOID BakeAnimations();
|
||||
|
||||
VOID SetActiveAnimation(IN Handle animation);
|
||||
VOID ForceSetActiveAnimation(IN Handle animation);
|
||||
|
||||
VOID SetAnimationFrame(IN INT32 animation, IN INT32 frame);
|
||||
|
||||
public:
|
||||
Vector<Animation> &Animations()
|
||||
@ -61,14 +65,9 @@ namespace ia::iae
|
||||
return m_animations;
|
||||
}
|
||||
|
||||
BOOL& IsFlippedV()
|
||||
BOOL &ReverseAnimation()
|
||||
{
|
||||
return m_isFlippedV;
|
||||
}
|
||||
|
||||
BOOL& IsFlippedH()
|
||||
{
|
||||
return m_isFlippedH;
|
||||
return m_reverseAnimation;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -78,9 +77,10 @@ namespace ia::iae
|
||||
private:
|
||||
VOID UpdateAnimation();
|
||||
|
||||
AnimationKeyFrame GetKeyFrame(IN INT32 index);
|
||||
|
||||
private:
|
||||
BOOL m_isFlippedV{false};
|
||||
BOOL m_isFlippedH{false};
|
||||
BOOL m_reverseAnimation{};
|
||||
FLOAT32 m_timelinePosition{};
|
||||
Animation m_activeAnimation{};
|
||||
Handle m_activeAnimationHandle{INVALID_HANDLE};
|
||||
|
||||
@ -26,14 +26,59 @@ namespace ia::iae
|
||||
public:
|
||||
TextureRendererComponent(IN Node *node);
|
||||
|
||||
RefPtr<iae::Texture> &Texture()
|
||||
Texture &CurrentTexture()
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
iam::Vec3f &Position()
|
||||
glm::vec2 &PositionOffset()
|
||||
{
|
||||
return m_position;
|
||||
return m_positionOffset;
|
||||
}
|
||||
|
||||
glm::vec2 &ScaleOffset()
|
||||
{
|
||||
return m_scaleOffset;
|
||||
}
|
||||
|
||||
FLOAT32 &RotationOffset()
|
||||
{
|
||||
return m_rotationOffset;
|
||||
}
|
||||
|
||||
glm::vec2 &TextureOffset()
|
||||
{
|
||||
return m_textureOffset;
|
||||
}
|
||||
|
||||
glm::vec4 &ColorOverlay()
|
||||
{
|
||||
return m_colorOverlay;
|
||||
}
|
||||
|
||||
BOOL &IsFlippedH()
|
||||
{
|
||||
return m_isFlippedH;
|
||||
}
|
||||
|
||||
BOOL &IsFlippedV()
|
||||
{
|
||||
return m_isFlippedV;
|
||||
}
|
||||
|
||||
BOOL &IsCameraRelative()
|
||||
{
|
||||
return m_isCameraRelative;
|
||||
}
|
||||
|
||||
BOOL& ShouldDrawOutline()
|
||||
{
|
||||
return m_shouldDrawOutline;
|
||||
}
|
||||
|
||||
glm::vec4& OutlineColor()
|
||||
{
|
||||
return m_outlineColor;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -41,7 +86,16 @@ namespace ia::iae
|
||||
VOID Update();
|
||||
|
||||
private:
|
||||
iam::Vec3f m_position;
|
||||
RefPtr<iae::Texture> m_texture;
|
||||
BOOL m_isFlippedH{};
|
||||
BOOL m_isFlippedV{};
|
||||
BOOL m_shouldDrawOutline{};
|
||||
glm::vec4 m_outlineColor{0.25f, 0.25f, 0.25f, 0.75f};
|
||||
BOOL m_isCameraRelative{true};
|
||||
glm::vec2 m_positionOffset{};
|
||||
glm::vec2 m_scaleOffset{1.0f, 1.0f};
|
||||
FLOAT32 m_rotationOffset{};
|
||||
glm::vec2 m_textureOffset{};
|
||||
glm::vec4 m_colorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
class Texture m_texture;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -16,25 +16,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Nodes/Node.hpp>
|
||||
#include <IAEngine/Scene.hpp>
|
||||
#include <IAEngine/Audio.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
#include <IAEngine/ResourceManager.hpp>
|
||||
#include <IAEngine/Scene.hpp>
|
||||
#include <IAEngine/Rendering/Renderer.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
struct EngineContext;
|
||||
|
||||
class Engine
|
||||
{
|
||||
struct DebugUIWindow
|
||||
{
|
||||
PCCHAR Title{""};
|
||||
iam::Vec2f Position{};
|
||||
iam::Vec2f Size{};
|
||||
std::function<VOID()> ContentDrawCallback{};
|
||||
};
|
||||
|
||||
public:
|
||||
struct InitConfig
|
||||
{
|
||||
@ -43,48 +33,38 @@ namespace ia::iae
|
||||
INT32 WindowHeight{600};
|
||||
};
|
||||
|
||||
public:
|
||||
Engine();
|
||||
~Engine();
|
||||
|
||||
BOOL Initialize(IN CONST InitConfig &config);
|
||||
VOID Terminate();
|
||||
|
||||
VOID BeginFrame();
|
||||
VOID EndFrame();
|
||||
BOOL ShouldClose();
|
||||
|
||||
VOID AddDebugUIWindow(IN PCCHAR title, IN CONST iam::Vec2f &position, IN CONST iam::Vec2f &size, IN std::function<VOID()> contentDrawCallback);
|
||||
|
||||
template<typename _class_type>
|
||||
_class_type* RegisterResourceManager();
|
||||
#if defined(__DEBUG_MODE__)
|
||||
STATIC CONSTEXPR BOOL IsDebugMode = TRUE;
|
||||
#else
|
||||
STATIC CONSTEXPR BOOL IsDebugMode = FALSE;
|
||||
#endif
|
||||
|
||||
public:
|
||||
RefPtr<Scene> CreateScene();
|
||||
STATIC BOOL Initialize(IN CONST InitConfig &config);
|
||||
STATIC VOID Terminate();
|
||||
|
||||
VOID ChangeScene(IN RefPtr<Scene> scene);
|
||||
STATIC VOID BeginFrame();
|
||||
STATIC VOID EndFrame();
|
||||
STATIC BOOL ShouldClose();
|
||||
|
||||
STATIC VOID ChangeScene(IN Scene* scene);
|
||||
STATIC Scene* GetActiveScene();
|
||||
|
||||
public:
|
||||
PVOID GetRendererHandle() CONST;
|
||||
STATIC RefPtr<Scene> CreateScene();
|
||||
|
||||
STATIC Texture CreateTexture(IN CONST Vector<UINT8> &encodedData);
|
||||
STATIC Texture CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
|
||||
STATIC Texture CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
|
||||
STATIC Vector<Texture> CreateTextures(IN CONST Vector<UINT8> &encodedData, IN INT32 textureCount);
|
||||
STATIC Vector<Texture> CreateTextures(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize, IN INT32 textureCount);
|
||||
|
||||
STATIC Sound CreateSound(IN CONST Vector<UINT8> &audioData);
|
||||
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
|
||||
|
||||
private:
|
||||
VOID RenderDebugUI();
|
||||
VOID ProcessEvents();
|
||||
VOID UpdateGame();
|
||||
VOID RenderGame();
|
||||
|
||||
private:
|
||||
FLOAT32 m_updateTimer{};
|
||||
RefPtr<Scene> m_activeScene{};
|
||||
CONST RefPtr<EngineContext> m_context;
|
||||
RefPtr<ResourceManager> m_resourceManager;
|
||||
Vector<DebugUIWindow> m_debugUIWindows;
|
||||
STATIC VOID ProcessEvents();
|
||||
STATIC VOID UpdateGame();
|
||||
STATIC VOID RenderGame();
|
||||
};
|
||||
|
||||
template<typename _class_type>
|
||||
_class_type* Engine::RegisterResourceManager()
|
||||
{
|
||||
m_resourceManager = MakeRefPtr<_class_type>(this);
|
||||
return (_class_type*)m_resourceManager.get();
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -255,8 +255,8 @@ namespace ia::iae
|
||||
|
||||
enum class DirectionalInput: UINT8
|
||||
{
|
||||
NONE = 0,
|
||||
DOWN,
|
||||
NONE = 255,
|
||||
DOWN = 0,
|
||||
DOWN_LEFT,
|
||||
LEFT,
|
||||
UP_LEFT,
|
||||
@ -270,6 +270,9 @@ namespace ia::iae
|
||||
STATIC VOID Initialize();
|
||||
STATIC VOID OnEvent(IN PVOID event);
|
||||
|
||||
STATIC VOID StartTextInput();
|
||||
STATIC VOID StopTextInput();
|
||||
|
||||
STATIC BOOL IsKeyDown(IN Key key)
|
||||
{
|
||||
return s_keys[(UINT8)key];
|
||||
@ -285,8 +288,8 @@ namespace ia::iae
|
||||
return s_prevKeys[key] && !s_keys[key];
|
||||
}
|
||||
|
||||
STATIC iam::Vec2f GetDirectionalInput();
|
||||
STATIC iam::Vec2f GetDirectionalInput(OUT DirectionalInput& direction);
|
||||
STATIC glm::vec2 GetDirectionalInput();
|
||||
STATIC glm::vec2 GetDirectionalInput(OUT DirectionalInput& direction);
|
||||
|
||||
private:
|
||||
STATIC BOOL s_keys[256];
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include <IAEngine/Components/Component.hpp>
|
||||
#include <IAEngine/Nodes/Transform.hpp>
|
||||
#include <IAEngine/Nodes/Tag.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
@ -27,7 +28,9 @@ namespace ia::iae
|
||||
class Node : public Transform<Node>
|
||||
{
|
||||
public:
|
||||
VIRTUAL VOID OnAdded(IN Scene* scene);
|
||||
~Node();
|
||||
|
||||
VIRTUAL VOID OnAdded(IN Scene *scene);
|
||||
VIRTUAL VOID OnRemoved();
|
||||
|
||||
VIRTUAL VOID Draw();
|
||||
@ -36,47 +39,77 @@ namespace ia::iae
|
||||
VIRTUAL VOID Disable();
|
||||
|
||||
public:
|
||||
VOID AddChild(IN RefPtr<Node> node);
|
||||
Node* AddChild(IN RefPtr<Node> node);
|
||||
|
||||
template<typename _component_type>
|
||||
_component_type* AddComponent();
|
||||
template<typename _component_type> _component_type *AddComponent();
|
||||
|
||||
template<typename _component_type>
|
||||
_component_type* GetComponent();
|
||||
template<typename _component_type> _component_type *GetComponent();
|
||||
|
||||
CONST Vector<RefPtr<IComponent>>& GetComponents() CONST
|
||||
CONST Vector<RefPtr<IComponent>> &GetComponents() CONST
|
||||
{
|
||||
return m_components;
|
||||
}
|
||||
|
||||
UINT8 GetLayerIndex() CONST
|
||||
{
|
||||
return m_layerIndex;
|
||||
}
|
||||
|
||||
UINT8 &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:
|
||||
Scene* m_scene{};
|
||||
Scene *m_scene{};
|
||||
UINT8 m_layerIndex{};
|
||||
BOOL m_isEnabled{true};
|
||||
glm::vec2 m_drawnSize{};
|
||||
String m_name;
|
||||
NodeTags m_tags;
|
||||
|
||||
protected:
|
||||
Vector<RefPtr<IComponent>> m_components;
|
||||
|
||||
friend class IComponent;
|
||||
|
||||
private:
|
||||
private:
|
||||
VOID AddComponent(IN RefPtr<IComponent> component);
|
||||
};
|
||||
|
||||
template<typename _component_type>
|
||||
_component_type* Node::AddComponent()
|
||||
template<typename _component_type> _component_type *Node::AddComponent()
|
||||
{
|
||||
const auto c = MakeRefPtr<_component_type>(this);
|
||||
AddComponent(c);
|
||||
return c.get();
|
||||
}
|
||||
|
||||
template<typename _component_type>
|
||||
_component_type* Node::GetComponent()
|
||||
template<typename _component_type> _component_type *Node::GetComponent()
|
||||
{
|
||||
for(auto& c: m_components)
|
||||
for (auto &c : m_components)
|
||||
{
|
||||
_component_type* comp = dynamic_cast<_component_type*>(c.get());
|
||||
if(comp)
|
||||
_component_type *comp = dynamic_cast<_component_type *>(c.get());
|
||||
if (comp)
|
||||
return comp;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
69
Src/IAEngine/inc/IAEngine/Nodes/Tag.hpp
Normal file
69
Src/IAEngine/inc/IAEngine/Nodes/Tag.hpp
Normal 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
|
||||
@ -20,55 +20,94 @@
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
template<typename _node_type>
|
||||
class Transform
|
||||
template<typename _node_type> class Transform
|
||||
{
|
||||
public:
|
||||
VOID SetLocalPosition(IN CONST iam::Vec3f &v)
|
||||
VOID Translate(IN glm::vec2 v)
|
||||
{
|
||||
m_local.Position += v;
|
||||
RecalculatePosition();
|
||||
}
|
||||
|
||||
VOID Scale(IN FLOAT32 v)
|
||||
{
|
||||
m_local.Scale *= v;
|
||||
RecalculateScale();
|
||||
}
|
||||
|
||||
VOID Scale(IN glm::vec2 v)
|
||||
{
|
||||
m_local.Scale *= v;
|
||||
RecalculateScale();
|
||||
}
|
||||
|
||||
VOID Rotate(IN FLOAT32 v)
|
||||
{
|
||||
m_local.Rotation += v;
|
||||
RecalculateRotation();
|
||||
}
|
||||
|
||||
VOID SetLocalSortIndex(IN INT16 index)
|
||||
{
|
||||
m_local.SortIndex = index;
|
||||
RecalculateSortIndex();
|
||||
}
|
||||
|
||||
VOID SetLocalPosition(IN CONST glm::vec2 &v)
|
||||
{
|
||||
m_local.Position = v;
|
||||
RecalculatePosition();
|
||||
}
|
||||
|
||||
VOID SetLocalScale(IN CONST iam::Vec3f &v)
|
||||
VOID SetLocalScale(IN CONST glm::vec2 &v)
|
||||
{
|
||||
m_local.Scale = v;
|
||||
RecalculateScale();
|
||||
}
|
||||
|
||||
VOID SetLocalRotation(IN CONST iam::Vec3f &v)
|
||||
VOID SetLocalRotation(IN FLOAT32 v)
|
||||
{
|
||||
m_local.Rotation = v;
|
||||
RecalculateRotation();
|
||||
}
|
||||
|
||||
public:
|
||||
CONST iam::Vec3f &GetPosition() CONST
|
||||
INT16 GetSortIndex() CONST
|
||||
{
|
||||
return m_global.SortIndex;
|
||||
}
|
||||
|
||||
CONST glm::vec2 &GetPosition() CONST
|
||||
{
|
||||
return m_global.Position;
|
||||
}
|
||||
|
||||
CONST iam::Vec3f &GetScale() CONST
|
||||
CONST glm::vec2 &GetScale() CONST
|
||||
{
|
||||
return m_global.Scale;
|
||||
}
|
||||
|
||||
CONST iam::Vec3f &GetRotation() CONST
|
||||
CONST FLOAT32 &GetRotation() CONST
|
||||
{
|
||||
return m_global.Rotation;
|
||||
}
|
||||
|
||||
CONST iam::Vec3f &GetLocalPosition() CONST
|
||||
INT16 GetLocalSortIndex() CONST
|
||||
{
|
||||
return m_local.SortIndex;
|
||||
}
|
||||
|
||||
CONST glm::vec2 &GetLocalPosition() CONST
|
||||
{
|
||||
return m_local.Position;
|
||||
}
|
||||
|
||||
CONST iam::Vec3f &GetLocalScale() CONST
|
||||
CONST glm::vec2 &GetLocalScale() CONST
|
||||
{
|
||||
return m_local.Scale;
|
||||
}
|
||||
|
||||
CONST iam::Vec3f &GetLocalRotation() CONST
|
||||
CONST FLOAT32 &GetLocalRotation() CONST
|
||||
{
|
||||
return m_local.Rotation;
|
||||
}
|
||||
@ -78,23 +117,30 @@ namespace ia::iae
|
||||
Vector<RefPtr<_node_type>> m_children{};
|
||||
|
||||
protected:
|
||||
VOID RecalculateSortIndex()
|
||||
{
|
||||
m_global.SortIndex = (m_parent ? m_parent->GetSortIndex() : 0) + m_local.SortIndex;
|
||||
for (auto &c : m_children)
|
||||
c->RecalculateSortIndex();
|
||||
}
|
||||
|
||||
VOID RecalculatePosition()
|
||||
{
|
||||
m_global.Position = (m_parent ? m_parent->GetPosition() : iam::Vec3f{}) + m_local.Position;
|
||||
m_global.Position = (m_parent ? m_parent->GetPosition() : glm::vec2{}) + m_local.Position;
|
||||
for (auto &c : m_children)
|
||||
c->RecalculatePosition();
|
||||
}
|
||||
|
||||
VOID RecalculateRotation()
|
||||
{
|
||||
m_global.Rotation = (m_parent ? m_parent->GetRotation() : iam::Vec3f{}) + m_local.Rotation;
|
||||
m_global.Rotation = (m_parent ? m_parent->GetRotation() : 0) + m_local.Rotation;
|
||||
for (auto &c : m_children)
|
||||
c->RecalculateRotation();
|
||||
}
|
||||
|
||||
VOID RecalculateScale()
|
||||
{
|
||||
m_global.Scale = (m_parent ? m_parent->GetScale() : iam::Vec3f{}) + m_local.Scale;
|
||||
m_global.Scale = (m_parent ? m_parent->GetScale() : glm::vec2{}) + m_local.Scale;
|
||||
for (auto &c : m_children)
|
||||
c->RecalculateScale();
|
||||
}
|
||||
@ -102,9 +148,10 @@ namespace ia::iae
|
||||
private:
|
||||
struct
|
||||
{
|
||||
iam::Vec3f Position{0.0f, 0.0f, 0.0f};
|
||||
iam::Vec3f Rotation{0.0f, 0.0f, 0.0f};
|
||||
iam::Vec3f Scale{1.0f, 1.0f, 1.0f};
|
||||
INT16 SortIndex{};
|
||||
FLOAT32 Rotation{0.0f};
|
||||
glm::vec2 Position{0.0f, 0.0f};
|
||||
glm::vec2 Scale{1.0f, 1.0f};
|
||||
} m_local{}, m_global{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -16,22 +16,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Base.hpp>
|
||||
#include <IAEngine/Physics/Physics.hpp>
|
||||
#include <IAEngine/Components/Physics.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Physics
|
||||
{
|
||||
public:
|
||||
STATIC Handle RegisterComponent(IN PhysicsComponent* component);
|
||||
|
||||
STATIC BOOL CanMove(IN Handle handle, IN CONST PhysicsComponent::Collider& collider, IN glm::vec2 movement);
|
||||
|
||||
private:
|
||||
STATIC VOID Initialize();
|
||||
STATIC VOID Terminate();
|
||||
|
||||
STATIC VOID Update();
|
||||
|
||||
STATIC Handle CreateStaticBody(IN iam::Vec3f position);
|
||||
STATIC Handle CreateDynamicBody(IN iam::Vec3f position);
|
||||
STATIC VOID AddBoxCollider(IN Handle body, IN iam::Vec3f size);
|
||||
STATIC VOID DebugDraw();
|
||||
|
||||
STATIC iam::Vec3f GetBodyPosition(IN Handle body);
|
||||
friend class Engine;
|
||||
friend class DebugDraw;
|
||||
};
|
||||
}
|
||||
44
Src/IAEngine/inc/IAEngine/Rendering/Camera.hpp
Normal file
44
Src/IAEngine/inc/IAEngine/Rendering/Camera.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// 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
|
||||
{
|
||||
class Camera2D
|
||||
{
|
||||
public:
|
||||
glm::vec2 &Position()
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
glm::mat4 GetViewMatrix()
|
||||
{
|
||||
return glm::lookAtLH(glm::vec3{m_position, -2.0f}, {m_position, 0.0f}, {0.0f, 1.0f, 0.0f});
|
||||
}
|
||||
|
||||
glm::vec2 GetCameraSize()
|
||||
{
|
||||
return glm::vec2{640, 480}; // [IATODO]
|
||||
}
|
||||
|
||||
private:
|
||||
glm::vec2 m_position{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
46
Src/IAEngine/inc/IAEngine/Rendering/DebugDraw.hpp
Normal file
46
Src/IAEngine/inc/IAEngine/Rendering/DebugDraw.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// 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/Rendering/Types.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class DebugDraw
|
||||
{
|
||||
public:
|
||||
STATIC Handle AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
|
||||
IN std::function<VOID()> contentDrawCallback);
|
||||
|
||||
STATIC VOID ToggleUIWindowVisibility(IN Handle handle);
|
||||
STATIC VOID SetUIWindowVisibility(IN Handle handle, IN BOOL visible);
|
||||
|
||||
public:
|
||||
STATIC VOID DrawLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color,
|
||||
IN FLOAT32 thickness = 1.0f);
|
||||
STATIC VOID DrawRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color, IN FLOAT32 thickness = 1.0f);
|
||||
STATIC VOID DrawRectFilled(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color);
|
||||
|
||||
private:
|
||||
STATIC VOID Initailize();
|
||||
STATIC VOID Terminate();
|
||||
|
||||
STATIC VOID Draw();
|
||||
|
||||
friend class Renderer;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -16,36 +16,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Audio.hpp>
|
||||
#include <IAEngine/Texture.hpp>
|
||||
#include <IAEngine/Base.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Engine;
|
||||
class Renderer;
|
||||
|
||||
class ResourceManager
|
||||
class GPUBuffer
|
||||
{
|
||||
public:
|
||||
ResourceManager(IN Engine *engine);
|
||||
|
||||
RefPtr<Texture> CreateTexture(IN CONST Span<CONST UINT8> &encodedData);
|
||||
RefPtr<Texture> CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
|
||||
RefPtr<Texture> CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
|
||||
enum class Usage
|
||||
{
|
||||
VERTEX,
|
||||
INDEX,
|
||||
STORAGE
|
||||
};
|
||||
|
||||
public:
|
||||
Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
|
||||
~GPUBuffer();
|
||||
|
||||
STATIC RefPtr<GPUBuffer> Create(IN Usage usage, IN PCVOID data, IN UINT32 dataSize);
|
||||
|
||||
public:
|
||||
Handle GetHandle() CONST
|
||||
{
|
||||
return Audio::CreateSound(audioData, audioDataSize);
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
Sound CreateSound(IN CONST Vector<UINT8> &audioData)
|
||||
{
|
||||
return CreateSound(audioData.data(), audioData.size());
|
||||
}
|
||||
private:
|
||||
Usage m_usage{};
|
||||
UINT32 m_size{};
|
||||
Handle m_handle{};
|
||||
|
||||
protected:
|
||||
Engine *CONST m_engine;
|
||||
private:
|
||||
STATIC BOOL InitializeStagingBuffer();
|
||||
STATIC VOID TerminateStagingBuffer();
|
||||
STATIC BOOL EnsureStagingBufferSize(IN UINT32 size);
|
||||
|
||||
friend class Engine;
|
||||
friend class Renderer;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
46
Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp
Normal file
46
Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// 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
|
||||
{
|
||||
class GPUTexture
|
||||
{
|
||||
public:
|
||||
STATIC VOID Initialize();
|
||||
STATIC VOID Terminate();
|
||||
STATIC Handle GetDefaultSampler();
|
||||
|
||||
public:
|
||||
~GPUTexture();
|
||||
|
||||
STATIC RefPtr<GPUTexture> Create(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
|
||||
|
||||
STATIC RefPtr<GPUTexture> GridCombine(IN Handle* handles, IN INT32 unitCountX, IN INT32 unitCountY, IN INT32 unitSizeX, IN INT32 unitSizeY);
|
||||
|
||||
public:
|
||||
Handle GetHandle() CONST
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
private:
|
||||
Handle m_handle{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
47
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/Pipeline.hpp
Normal file
47
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/Pipeline.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
// 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/Rendering/Types.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class IPipeline
|
||||
{
|
||||
public:
|
||||
enum class ShaderStage
|
||||
{
|
||||
VERTEX,
|
||||
PIXEL,
|
||||
COMPUTE,
|
||||
GEOMETRY
|
||||
};
|
||||
|
||||
public:
|
||||
PURE_VIRTUAL(VOID Bind(IN Handle renderPassHandle));
|
||||
|
||||
protected:
|
||||
STATIC Handle LoadShaderFromMemory(IN ShaderStage stage, IN PCUINT8 sourceData, IN SIZE_T sourceLength, IN UINT32 samplerCount,
|
||||
IN UINT32 uniformBufferCount, IN UINT32 storageBufferCount,
|
||||
IN UINT32 storageTextureCount);
|
||||
STATIC Handle LoadShaderFromFile(IN ShaderStage stage, IN PCCHAR fileName, IN UINT32 samplerCount,
|
||||
IN UINT32 uniformBufferCount, IN UINT32 storageBufferCount,
|
||||
IN UINT32 storageTextureCount);
|
||||
|
||||
STATIC VOID UnloadShader(IN Handle handle);
|
||||
};
|
||||
} // namespace ia::iae
|
||||
35
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/PostProcess.hpp
Normal file
35
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/PostProcess.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
// 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/Rendering/Pipeline/Pipeline.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Pipeline_PostProcess: public IPipeline
|
||||
{
|
||||
public:
|
||||
~Pipeline_PostProcess();
|
||||
|
||||
STATIC RefPtr<Pipeline_PostProcess> Create();
|
||||
|
||||
VOID Bind(IN Handle renderPassHandle);
|
||||
|
||||
private:
|
||||
Handle m_handle{INVALID_HANDLE};
|
||||
};
|
||||
}
|
||||
35
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/UnlitMesh.hpp
Normal file
35
Src/IAEngine/inc/IAEngine/Rendering/Pipeline/UnlitMesh.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
// 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/Rendering/Pipeline/Pipeline.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Pipeline_UnlitMesh: public IPipeline
|
||||
{
|
||||
public:
|
||||
~Pipeline_UnlitMesh();
|
||||
|
||||
STATIC RefPtr<Pipeline_UnlitMesh> Create();
|
||||
|
||||
VOID Bind(IN Handle renderPassHandle);
|
||||
|
||||
private:
|
||||
Handle m_handle{INVALID_HANDLE};
|
||||
};
|
||||
}
|
||||
74
Src/IAEngine/inc/IAEngine/Rendering/Renderer.hpp
Normal file
74
Src/IAEngine/inc/IAEngine/Rendering/Renderer.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
// 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/Rendering/Types.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Camera2D;
|
||||
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
STATIC CONSTEXPR UINT8 MAX_LAYER_INDEX = 255;
|
||||
|
||||
public:
|
||||
STATIC BOOL Initialize();
|
||||
STATIC VOID Terminate();
|
||||
|
||||
public:
|
||||
STATIC VOID BeginFrame();
|
||||
STATIC VOID EndFrame();
|
||||
|
||||
STATIC VOID SetState_FlippedH(IN BOOL value);
|
||||
STATIC VOID SetState_FlippedV(IN BOOL value);
|
||||
STATIC VOID SetState_CameraRelative(IN BOOL value);
|
||||
STATIC VOID SetState_ScissorEnabled(IN BOOL value);
|
||||
STATIC VOID SetState_Scissor(IN CONST glm::vec4 ®ion);
|
||||
STATIC VOID SetState_TextureOffset(IN FLOAT32 u, IN FLOAT32 v);
|
||||
|
||||
public:
|
||||
STATIC Handle GetMesh_Quad();
|
||||
|
||||
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,
|
||||
IN CONST glm::vec2 &scale, IN FLOAT32 rotation = 0, IN UINT8 layerIndex = 0,
|
||||
IN INT16 sortIndex = 0, IN CONST glm::vec4 &colorOverlay = {1.0f, 1.0f, 1.0f, 1.0f});
|
||||
|
||||
public:
|
||||
STATIC Camera2D *GetCamera();
|
||||
|
||||
public:
|
||||
STATIC INT32 Width()
|
||||
{
|
||||
return s_width;
|
||||
}
|
||||
|
||||
STATIC INT32 Height()
|
||||
{
|
||||
return s_height;
|
||||
}
|
||||
|
||||
private:
|
||||
STATIC INT32 s_width;
|
||||
STATIC INT32 s_height;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
29
Src/IAEngine/inc/IAEngine/Rendering/Types.hpp
Normal file
29
Src/IAEngine/inc/IAEngine/Rendering/Types.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// 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
|
||||
{
|
||||
struct MeshVertex
|
||||
{
|
||||
glm::vec3 Position{};
|
||||
glm::vec2 UV{};
|
||||
glm::vec4 Color{};
|
||||
};
|
||||
}
|
||||
@ -20,16 +20,16 @@
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Engine;
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
Scene(IN Engine* engine);
|
||||
~Scene();
|
||||
|
||||
VOID Draw();
|
||||
VOID Update();
|
||||
VIRTUAL VOID OnActivate();
|
||||
VIRTUAL VOID OnDeactivate();
|
||||
|
||||
VIRTUAL VOID Draw();
|
||||
VIRTUAL VOID Update();
|
||||
|
||||
public:
|
||||
VOID AddNode(IN RefPtr<Node> node);
|
||||
@ -41,8 +41,19 @@ namespace ia::iae
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
BOOL &YSortingEnabled()
|
||||
{
|
||||
return m_ySortingEnabled;
|
||||
}
|
||||
|
||||
glm::vec4 &Bounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
private:
|
||||
Engine* CONST m_engine;
|
||||
BOOL m_ySortingEnabled{false};
|
||||
Vector<RefPtr<Node>> m_nodes;
|
||||
glm::vec4 m_bounds;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -20,36 +20,36 @@
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class Engine;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(IN Engine* engine);
|
||||
Texture();
|
||||
Texture(IN Handle handle, IN INT32 width, IN INT32 height);
|
||||
~Texture();
|
||||
|
||||
public:
|
||||
VOID Draw(IN CONST iam::Vec3f& position, IN CONST iam::Vec3f& scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN CONST iam::Vec4f& colorOverlay) CONST;
|
||||
Handle GetHandle() CONST
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
public:
|
||||
INT32 GetWidth() CONST
|
||||
{
|
||||
return m_width;
|
||||
return (INT32) m_extent.x;
|
||||
}
|
||||
|
||||
INT32 GetHeight() CONST
|
||||
{
|
||||
return m_height;
|
||||
return (INT32) m_extent.y;
|
||||
}
|
||||
|
||||
CONST glm::vec2 &GetExtent() CONST
|
||||
{
|
||||
return m_extent;
|
||||
}
|
||||
|
||||
private:
|
||||
INT32 m_width;
|
||||
INT32 m_height;
|
||||
PVOID m_handle{};
|
||||
Engine* CONST m_engine;
|
||||
|
||||
private:
|
||||
friend class Engine;
|
||||
friend class ResourceManager;
|
||||
Handle m_handle{INVALID_HANDLE};
|
||||
glm::vec2 m_extent{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
59
Src/IAEngine/inc/IAEngine/UI.hpp
Normal file
59
Src/IAEngine/inc/IAEngine/UI.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
// 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
|
||||
{
|
||||
class UI
|
||||
{
|
||||
public:
|
||||
STATIC VOID AddFontFromFile(IN CONST String &path);
|
||||
|
||||
STATIC Handle AddWindowFromFile(IN CONST String &path);
|
||||
|
||||
STATIC VOID DestroyWindow(IN Handle handle);
|
||||
|
||||
STATIC VOID ShowWindow(IN Handle handle);
|
||||
STATIC VOID HideWindow(IN Handle handle);
|
||||
|
||||
STATIC String GetInputValue(IN INT32 index);
|
||||
STATIC VOID SetInputValue(IN INT32 index, IN CONST String& value);
|
||||
|
||||
STATIC VOID AddClickEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback);
|
||||
STATIC VOID AddHoverEnterEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback);
|
||||
STATIC VOID AddHoverExitEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback);
|
||||
STATIC VOID AddPointerDownEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback);
|
||||
STATIC VOID AddPointerUpEvent(IN Handle handle, IN PCCHAR elementId, IN std::function<VOID()> callback);
|
||||
|
||||
STATIC VOID EnableDebugger();
|
||||
STATIC VOID DisableDebugger();
|
||||
|
||||
private:
|
||||
STATIC VOID Initialize(IN INT32 width, IN INT32 height);
|
||||
STATIC VOID Terminate();
|
||||
|
||||
STATIC VOID Draw();
|
||||
STATIC VOID Update();
|
||||
|
||||
STATIC VOID OnEvent(IN PVOID event);
|
||||
STATIC VOID OnResize(IN INT32 width, IN INT32 height);
|
||||
|
||||
friend class Engine;
|
||||
};
|
||||
} // namespace ia::iae
|
||||
63
Src/IAEngine/srcgen/embed_shaders.py
Normal file
63
Src/IAEngine/srcgen/embed_shaders.py
Normal file
@ -0,0 +1,63 @@
|
||||
import os
|
||||
|
||||
GEN_SOURCE_PREFIX = """// 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/>.
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// GENERATED FILE. DO NOT EDIT.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Base.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
"""
|
||||
|
||||
GEN_SOURCE_SUFFIX = """} // namespace ia::iae\n"""
|
||||
GEN_SOURCE_PATH = "Src/IAEngine/imp/hpp/EmbeddedShaders.hpp"
|
||||
SHADER_SOURCE_PATH = "Src/IAEngine/imp/glsl"
|
||||
|
||||
SHADER_SOURCE_FILES = [
|
||||
"UnlitMesh/UnlitMesh.vert",
|
||||
"UnlitMesh/UnlitMesh.frag",
|
||||
"PostProcessing/PostProcess.vert",
|
||||
"PostProcessing/PostProcess.frag"
|
||||
]
|
||||
|
||||
def file_to_source_array(arrayName, filePath):
|
||||
data = b''
|
||||
with open(filePath, 'rb') as f:
|
||||
data = f.read()
|
||||
res = f"CONSTEXPR UINT8 {arrayName}[{len(data)}] = {{\n"
|
||||
for d in data:
|
||||
res += f"{hex(d)},"
|
||||
res += "};\n"
|
||||
return res
|
||||
|
||||
def main():
|
||||
with open(GEN_SOURCE_PATH, 'w') as outFile:
|
||||
outFile.write(GEN_SOURCE_PREFIX)
|
||||
for fileName in SHADER_SOURCE_FILES:
|
||||
p = f"{SHADER_SOURCE_PATH}/{fileName}"
|
||||
os.system(f"glslc {p} -o {p}.spv")
|
||||
src = file_to_source_array(f"SHADER_SOURCE_{fileName.split('/')[-1].upper().replace('.', '_')}", f"{p}.spv")
|
||||
outFile.write(f"{src}\n")
|
||||
os.remove(f"{p}.spv")
|
||||
outFile.write(GEN_SOURCE_SUFFIX)
|
||||
|
||||
main()
|
||||
21
Vendor/CMakeLists.txt
vendored
21
Vendor/CMakeLists.txt
vendored
@ -1,4 +1,4 @@
|
||||
# -----------------------------------------------
|
||||
#-----------------------------------------------
|
||||
# SDL3
|
||||
# -----------------------------------------------
|
||||
set(SDL_TEST_LIBRARY OFF)
|
||||
@ -23,7 +23,7 @@ add_library(
|
||||
"imgui/imgui_tables.cpp"
|
||||
"imgui/imgui_widgets.cpp"
|
||||
"imgui/backends/imgui_impl_sdl3.cpp"
|
||||
"imgui/backends/imgui_impl_sdlrenderer3.cpp"
|
||||
"imgui/backends/imgui_impl_sdlgpu3.cpp"
|
||||
)
|
||||
target_include_directories(
|
||||
ImGui PRIVATE
|
||||
@ -37,3 +37,20 @@ target_include_directories(
|
||||
"imgui/backends"
|
||||
)
|
||||
|
||||
# -----------------------------------------------
|
||||
# GLM
|
||||
# -----------------------------------------------
|
||||
add_subdirectory(glm/)
|
||||
|
||||
# -----------------------------------------------
|
||||
# FreeType
|
||||
# -----------------------------------------------
|
||||
add_subdirectory(freetype/)
|
||||
|
||||
add_library(Freetype::Freetype ALIAS freetype)
|
||||
|
||||
# -----------------------------------------------
|
||||
# RmlUI
|
||||
# -----------------------------------------------
|
||||
add_subdirectory(RmlUI/)
|
||||
|
||||
|
||||
1
Vendor/RmlUi
vendored
Submodule
1
Vendor/RmlUi
vendored
Submodule
Submodule Vendor/RmlUi added at 5556ac74c5
2
Vendor/SDL
vendored
2
Vendor/SDL
vendored
Submodule Vendor/SDL updated: 4efdfd92a2...cfa31df2d5
2
Vendor/SDL_Mixer
vendored
2
Vendor/SDL_Mixer
vendored
Submodule Vendor/SDL_Mixer updated: 172997758b...40a580fe85
1
Vendor/freetype
vendored
Submodule
1
Vendor/freetype
vendored
Submodule
Submodule Vendor/freetype added at 41eab7e66d
1
Vendor/glm
vendored
Submodule
1
Vendor/glm
vendored
Submodule
Submodule Vendor/glm added at 2d4c4b4dd3
2
Vendor/imgui
vendored
2
Vendor/imgui
vendored
Submodule Vendor/imgui updated: 8eb22ea620...02af06ea5f
Reference in New Issue
Block a user