This commit is contained in:
Isuru Samarathunga
2025-11-14 09:43:09 +05:30
parent 9ff39d7245
commit a2b80ef600
32 changed files with 928 additions and 295 deletions

View File

@ -9,26 +9,6 @@
</Properties> </Properties>
<Entries> <Entries>
<SpriteSheet name="SpriteSheet_Player" path="Cute_Fantasy_Free/Player/Player.png" spriteWidth="32" spriteHeight="32">
<Animation name="IdleDown" frameCount="6"></Animation>
<Animation name="IdleRight" frameCount="6"></Animation>
<Animation name="IdleUp" frameCount="6"></Animation>
<Animation name="WalkDown" frameCount="6"></Animation>
<Animation name="WalkRight" frameCount="6"></Animation>
<Animation name="WalkUp" frameCount="6"></Animation>
<Animation name="AttackDown" frameCount="4"></Animation>
<Animation name="AttackRight" frameCount="4"></Animation>
<Animation name="AttackUp" frameCount="4"></Animation>
<Animation name="Die" frameCount="4"></Animation>
</SpriteSheet>
<TileSheet name="TileSheet_MiddlePath" path="Cute_Fantasy_Free/Tiles/Path_Middle.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_MiddleWater" path="Cute_Fantasy_Free/Tiles/Water_Middle.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_MiddleGrass" path="Cute_Fantasy_Free/Tiles/Grass_Middle.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_Path" path="Cute_Fantasy_Free/Tiles/Path_Tile.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_Water" path="Cute_Fantasy_Free/Tiles/Water_Tile.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_Beach" path="Cute_Fantasy_Free/Tiles/Beach_Tile.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_Cliff" path="Cute_Fantasy_Free/Tiles/Cliff_Tile.png" tileWidth="16" tileHeight="16"></TileSheet>
<TileSheet name="TileSheet_FarmLand" path="Cute_Fantasy_Free/Tiles/FarmLand_Tile.png" tileWidth="16" tileHeight="16"></TileSheet>
</Entries> </Entries>
</Assets> </Assets>

View File

@ -25,84 +25,5 @@
</Nodes> </Nodes>
<Grid tileWidth="16" tileHeight="16"> <Grid tileWidth="16" tileHeight="16">
<Repeat times="50">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="30">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="30">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="13">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Cell tileSheet="TileSheet_Beach" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="1" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="2" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Repeat times="14">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="13">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Cell tileSheet="TileSheet_Beach" tileX="0" tileY="1" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="1" tileY="1" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="2" tileY="1" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Repeat times="14">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="13">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Cell tileSheet="TileSheet_Beach" tileX="0" tileY="2" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="1" tileY="2" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Cell tileSheet="TileSheet_Beach" tileX="2" tileY="2" collisionMask="0" colorOverlay="#ffffffff"></Cell>
<Repeat times="14">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="30">
<Cell tileSheet="TileSheet_MiddleWater" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="10">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
<Repeat times="50">
<Cell tileSheet="TileSheet_MiddleGrass" tileX="0" tileY="0" collisionMask="0" colorOverlay="#ffffffff"></Cell>
</Repeat>
</Grid> </Grid>
</Scene> </Scene>

View File

@ -10,12 +10,14 @@ set(SRC_FILES
"imp/cpp/UI/TabContainer.cpp" "imp/cpp/UI/TabContainer.cpp"
"imp/cpp/UI/View/IView.cpp" "imp/cpp/UI/View/IView.cpp"
"imp/cpp/UI/View/Asset.cpp" "imp/cpp/UI/View/FilePreview.cpp"
"imp/cpp/UI/View/AssetBrowser.cpp" "imp/cpp/UI/View/AssetBrowser.cpp"
"imp/cpp/UI/View/Console.cpp" "imp/cpp/UI/View/Console.cpp"
"imp/cpp/UI/View/Nodes.cpp" "imp/cpp/UI/View/Nodes.cpp"
"imp/cpp/UI/View/Package.cpp" "imp/cpp/UI/View/Package.cpp"
"imp/cpp/UI/View/Scene.cpp" "imp/cpp/UI/View/Scene.cpp"
"imp/cpp/UI/View/Game.cpp"
"imp/cpp/UI/View/Asset.cpp"
"imp/cpp/UI/View/Properties.cpp" "imp/cpp/UI/View/Properties.cpp"
# imgui # imgui

View File

@ -26,6 +26,7 @@
#include <UI/UI.hpp> #include <UI/UI.hpp>
#include <UI/View/Asset.hpp> #include <UI/View/Asset.hpp>
#include <UI/View/FilePreview.hpp>
#include <LogoIcon.hpp> #include <LogoIcon.hpp>
@ -41,15 +42,46 @@ namespace ia::iae
ImDrawData *g_imDrawData{}; ImDrawData *g_imDrawData{};
IVec2 g_windowExtent{800, 600}; IVec2 g_windowExtent{800, 600};
Map<String, String> g_assetNameMap;
SIZE_T g_uniqueNameCounter{0};
String generate_unique_asset_name()
{
return BuildString("Asset_", g_uniqueNameCounter++);
}
VOID Editor::LoadProject(IN CONST String &directory) VOID Editor::LoadProject(IN CONST String &directory)
{ {
m_activeProject = Project::Load(directory); m_activeProject = Project::Load(directory);
} }
VOID Editor::OpenAsset(IN Path path) VOID Editor::OpenFile(IN Path path)
{
const auto assetName = AssetManager::GetAssetName(path.string().c_str());
if (assetName.size())
{
UI::GetAssetView()->Open(assetName);
UI::OpenAssetView();
}
else
{
UI::GetFilePreviewView()->Open(path);
UI::OpenFilePreviewView();
}
}
VOID Editor::MarkAsAsset(IN Path path)
{
const auto assetName = generate_unique_asset_name();
AssetManager::AssignAssetName(AssetManager::LoadTexture(path.string().c_str()), assetName);
UI::CloseFilePreviewView();
UI::GetAssetView()->Open(assetName);
UI::OpenAssetView();
}
VOID Editor::RemoveFromAssets(IN CONST String &assetName)
{ {
UI::GetAssetView()->Open(path);
UI::FocusAssetView();
} }
INT32 Editor::Run(IN INT32 argc, IN PCCHAR argv[]) INT32 Editor::Run(IN INT32 argc, IN PCCHAR argv[])

View File

@ -20,7 +20,9 @@ namespace ia::iae
{ {
INT32 g_tabContainerCount{0}; INT32 g_tabContainerCount{0};
TabContainer::TabContainer() : m_containerID(BuildString("TabContainer##", g_tabContainerCount++)), m_tabBarID(BuildString("TabBar##", g_tabContainerCount++)) TabContainer::TabContainer()
: m_containerID(BuildString("TabContainer##", g_tabContainerCount++)),
m_tabBarID(BuildString("TabBar##", g_tabContainerCount++))
{ {
} }
@ -52,9 +54,10 @@ namespace ia::iae
m_pendingActiveTabName = nullptr; m_pendingActiveTabName = nullptr;
} }
if (ImGui::BeginTabItem(v->Value->IconAndName().c_str(), nullptr, flags)) BOOL* isOpen = v->Value.IsCloseable ? &v->Value.IsOpen : nullptr;
if (ImGui::BeginTabItem(v->Value.View->IconAndName().c_str(), isOpen, flags))
{ {
v->Value->Render(); v->Value.View->Render();
ImGui::EndTabItem(); ImGui::EndTabItem();
m_activeTabName = v->Key.c_str(); m_activeTabName = v->Key.c_str();
@ -68,20 +71,20 @@ namespace ia::iae
VOID TabContainer::Update() VOID TabContainer::Update()
{ {
for (const auto &t : m_tabViews) for (const auto &t : m_tabViews)
t->Value->Update(); t->Value.View->Update();
} }
VOID TabContainer::ProcessEvent(IN SDL_Event *event) VOID TabContainer::ProcessEvent(IN SDL_Event *event)
{ {
for (const auto &t : m_tabViews) for (const auto &t : m_tabViews)
t->Value->ProcessEvent(event); t->Value.View->ProcessEvent(event);
} }
VOID TabContainer::AddTab(IN CONST String &name, IN IView *view) VOID TabContainer::AddTab(IN CONST String &name, IN IView *view, IN BOOL isCloseable)
{ {
RemoveTab(name); RemoveTab(name);
view->Initialize(); view->Initialize();
m_tabViews[name] = view; m_tabViews[name] = Tab{.View = view, .IsCloseable = isCloseable};
if (!m_activeTabName) if (!m_activeTabName)
m_activeTabName = name.c_str(); m_activeTabName = name.c_str();
} }
@ -90,10 +93,25 @@ namespace ia::iae
{ {
if (!m_tabViews.contains(name)) if (!m_tabViews.contains(name))
return; return;
if (m_tabViews[name]) m_tabViews[name].IsOpen = false;
m_tabViews[name]->Terminate(); if (m_tabViews[name].View)
delete m_tabViews[name]; m_tabViews[name].View->Terminate();
m_tabViews[name] = nullptr; delete m_tabViews[name].View;
m_tabViews[name] = {};
}
VOID TabContainer::OpenTab(IN CONST String &name)
{
if (!m_tabViews.contains(name))
return;
m_tabViews[name].IsOpen = true;
}
VOID TabContainer::CloseTab(IN CONST String &name)
{
if (!m_tabViews.contains(name))
return;
m_tabViews[name].IsOpen = false;
} }
VOID TabContainer::ChangeActiveTab(IN PCCHAR name) VOID TabContainer::ChangeActiveTab(IN PCCHAR name)
@ -103,6 +121,6 @@ namespace ia::iae
IView *TabContainer::GetTab(IN CONST String &name) IView *TabContainer::GetTab(IN CONST String &name)
{ {
return m_tabViews[name]; return m_tabViews[name].View;
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -21,22 +21,26 @@
#include <UI/View/Asset.hpp> #include <UI/View/Asset.hpp>
#include <UI/View/AssetBrowser.hpp> #include <UI/View/AssetBrowser.hpp>
#include <UI/View/Console.hpp> #include <UI/View/Console.hpp>
#include <UI/View/FilePreview.hpp>
#include <UI/View/Nodes.hpp> #include <UI/View/Nodes.hpp>
#include <UI/View/Package.hpp> #include <UI/View/Package.hpp>
#include <UI/View/Properties.hpp> #include <UI/View/Properties.hpp>
#include <UI/View/Scene.hpp> #include <UI/View/Scene.hpp>
#include <UI/View/Game.hpp>
#include <UI/TabContainer.hpp> #include <UI/TabContainer.hpp>
namespace ia::iae namespace ia::iae
{ {
STATIC CONSTEXPR PCCHAR VIEW_NAME_ASSET_BROWSER = "AssetBrowser"; STATIC CONSTEXPR PCCHAR VIEW_NAME_ASSET_BROWSER = "AssetBrowser";
STATIC CONSTEXPR PCCHAR VIEW_NAME_FILE_PREVIEW = "FilePreview";
STATIC CONSTEXPR PCCHAR VIEW_NAME_ASSET = "Asset"; STATIC CONSTEXPR PCCHAR VIEW_NAME_ASSET = "Asset";
STATIC CONSTEXPR PCCHAR VIEW_NAME_CONSOLE = "Console"; STATIC CONSTEXPR PCCHAR VIEW_NAME_CONSOLE = "Console";
STATIC CONSTEXPR PCCHAR VIEW_NAME_NODES = "Nodes"; STATIC CONSTEXPR PCCHAR VIEW_NAME_NODES = "Nodes";
STATIC CONSTEXPR PCCHAR VIEW_NAME_PACKAGE = "Package"; STATIC CONSTEXPR PCCHAR VIEW_NAME_PACKAGE = "Package";
STATIC CONSTEXPR PCCHAR VIEW_NAME_PROPERTIES = "Properties"; STATIC CONSTEXPR PCCHAR VIEW_NAME_PROPERTIES = "Properties";
STATIC CONSTEXPR PCCHAR VIEW_NAME_SCENE = "SCENE"; STATIC CONSTEXPR PCCHAR VIEW_NAME_SCENE = "Scene";
STATIC CONSTEXPR PCCHAR VIEW_NAME_GAME = "Game";
EXTERN IVec2 g_windowExtent; EXTERN IVec2 g_windowExtent;
@ -47,16 +51,38 @@ namespace ia::iae
TabContainer g_tabContainerTM; TabContainer g_tabContainerTM;
TabContainer g_tabContainerTR; TabContainer g_tabContainerTR;
VOID UI::FocusAssetView() VOID UI::OpenFilePreviewView()
{ {
g_tabContainerTR.OpenTab(VIEW_NAME_FILE_PREVIEW);
g_tabContainerTR.ChangeActiveTab(VIEW_NAME_FILE_PREVIEW);
}
VOID UI::CloseFilePreviewView()
{
g_tabContainerTR.CloseTab(VIEW_NAME_FILE_PREVIEW);
}
VOID UI::OpenAssetView()
{
g_tabContainerTR.OpenTab(VIEW_NAME_ASSET);
g_tabContainerTR.ChangeActiveTab(VIEW_NAME_ASSET); g_tabContainerTR.ChangeActiveTab(VIEW_NAME_ASSET);
} }
VOID UI::CloseAssetView()
{
g_tabContainerTR.CloseTab(VIEW_NAME_ASSET);
}
class View_Asset *UI::GetAssetView() class View_Asset *UI::GetAssetView()
{ {
return (View_Asset *) g_tabContainerTR.GetTab(VIEW_NAME_ASSET); return (View_Asset *) g_tabContainerTR.GetTab(VIEW_NAME_ASSET);
} }
class View_FilePreview *UI::GetFilePreviewView()
{
return (View_FilePreview *) g_tabContainerTR.GetTab(VIEW_NAME_FILE_PREVIEW);
}
VOID UI::Initialize() VOID UI::Initialize()
{ {
g_tabContainerB.Initialize(); g_tabContainerB.Initialize();
@ -71,9 +97,14 @@ namespace ia::iae
g_tabContainerTL.AddTab<View_Package>(VIEW_NAME_PACKAGE); g_tabContainerTL.AddTab<View_Package>(VIEW_NAME_PACKAGE);
g_tabContainerTM.AddTab<View_Scene>(VIEW_NAME_SCENE); g_tabContainerTM.AddTab<View_Scene>(VIEW_NAME_SCENE);
g_tabContainerTM.AddTab<View_Game>(VIEW_NAME_GAME);
g_tabContainerTR.AddTab<View_Properties>(VIEW_NAME_PROPERTIES); g_tabContainerTR.AddTab<View_Properties>(VIEW_NAME_PROPERTIES);
g_tabContainerTR.AddTab<View_Asset>(VIEW_NAME_ASSET); g_tabContainerTR.AddTab<View_Asset>(VIEW_NAME_ASSET, true);
g_tabContainerTR.AddTab<View_FilePreview>(VIEW_NAME_FILE_PREVIEW, true);
g_tabContainerTR.CloseTab(VIEW_NAME_ASSET);
g_tabContainerTR.CloseTab(VIEW_NAME_FILE_PREVIEW);
} }
VOID UI::Terminate() VOID UI::Terminate()
@ -180,4 +211,13 @@ namespace ia::iae
{ {
ImGui::SetCursorPosY((rect.GetHeight() - height) / 2.0f); ImGui::SetCursorPosY((rect.GetHeight() - height) / 2.0f);
} }
VOID UI::DrawTextCentered(IN CONST ImVec2 &viewExtent, IN CONST String &text)
{
ImRect rect{{}, viewExtent};
const auto textSize = ImGui::CalcTextSize(text.c_str());
UI::AlignCursorHCenter(rect, textSize.x);
UI::AlignCursorVCenter(rect, textSize.y);
ImGui::Text("%s", text.c_str());
}
} // namespace ia::iae } // namespace ia::iae

View File

@ -16,13 +16,13 @@
#include <UI/View/Asset.hpp> #include <UI/View/Asset.hpp>
#include <IAEngine/Asset/AssetManager.hpp>
#include <RenderCore/RenderCore.hpp>
#include <Editor.hpp>
namespace ia::iae namespace ia::iae
{ {
struct AssetCacheEntry
{
};
VOID View_Asset::Initialize() VOID View_Asset::Initialize()
{ {
SetName("Asset"); SetName("Asset");
@ -37,13 +37,47 @@ namespace ia::iae
{ {
PreRender(); PreRender();
if(m_assetPath.empty()) if (!m_asset)
{ {
PostRender(); PostRender();
return; return;
} }
ImGui::Text("%s", m_assetPath.filename().string().c_str()); STATIC CHAR NAME_BUFFER[256];
memcpy(NAME_BUFFER, m_assetName.c_str(), m_assetName.size() + 1);
ImGui::Text("Name: ");
ImGui::SameLine();
ImGui::InputText("##name", NAME_BUFFER, sizeof(NAME_BUFFER));
m_assetName = NAME_BUFFER;
DrawAssetTypePicker();
switch (m_asset->GetType())
{
case EAssetType::TEXTURE:
RenderTextureAsset();
break;
case EAssetType::SPRITE:
RenderSpriteAsset();
break;
case EAssetType::TILESHEET:
RenderTileSheetAsset();
break;
case EAssetType::SPRITESHEET:
RenderSpriteSheetAsset();
break;
case EAssetType::INVALID:
case EAssetType::SOUND:
case EAssetType::SCENE:
case EAssetType::PLUGIN:
case EAssetType::PACKAGE:
break;
}
PostRender(); PostRender();
} }
@ -56,14 +90,125 @@ namespace ia::iae
{ {
} }
VOID View_Asset::Open(IN Path path) VOID View_Asset::Open(IN String assetName)
{ {
Close(); m_assetName = assetName;
m_assetPath = path; const auto asset = AssetManager::GetAssetByName<Asset_Texture>(m_assetName);
m_assetImageHandle = RDC::BakeTexture(asset->GetHandle()->ImagePtr);
m_assetImageExtent = {asset->GetHandle()->ImagePtr->Width, asset->GetHandle()->ImagePtr->Height};
m_asset = asset;
m_assetType = asset->GetType();
} }
VOID View_Asset::Close() VOID View_Asset::Close()
{ {
m_assetPath = Path(); m_assetName = "";
m_asset = nullptr;
m_assetImageHandle = 0;
m_assetImageExtent = {};
m_assetType = EAssetType::INVALID;
}
VOID View_Asset::RenderTextureAsset()
{
const auto asset = (Asset_Texture *) m_asset;
DrawAssetImage(0.75f, {0, 0});
}
VOID View_Asset::RenderSpriteAsset()
{
const auto asset = (Asset_Sprite *) m_asset;
DrawAssetImage(0.75f, {0, 0});
}
VOID View_Asset::RenderTileSheetAsset()
{
const auto asset = (Asset_TileSheet *) m_asset;
ImGui::Text("Tile Width: ");
ImGui::SameLine();
ImGui::InputInt("##TileWidth", &asset->TileWidth());
if (asset->TileWidth() < 1)
asset->TileWidth() = 1;
if (asset->TileWidth() > m_assetImageExtent.x)
asset->TileWidth() = m_assetImageExtent.x;
ImGui::Text("Tile Height: ");
ImGui::SameLine();
ImGui::InputInt("##TileHeight", &asset->TileHeight());
if (asset->TileHeight() < 1)
asset->TileHeight() = 1;
if (asset->TileHeight() > m_assetImageExtent.y)
asset->TileHeight() = m_assetImageExtent.y;
DrawAssetImage(0.75f, {asset->TileWidth(), asset->TileHeight()});
}
VOID View_Asset::RenderSpriteSheetAsset()
{
const auto asset = (Asset_SpriteSheet *) m_asset;
}
VOID View_Asset::DrawAssetImage(IN FLOAT32 relativeWidth, IN IVec2 gridSize)
{
ImVec2 base_pos = ImGui::GetCursorScreenPos();
const auto ImageWidth = m_extent.x * relativeWidth;
const auto aspectRatio =
static_cast<FLOAT32>(m_assetImageExtent.y) / static_cast<FLOAT32>(m_assetImageExtent.x);
const auto ImageHeight = aspectRatio * ImageWidth;
ImGui::Image((ImTextureRef) m_assetImageHandle, {ImageWidth, ImageHeight});
if((!gridSize.x) || (!gridSize.y))
return;
gridSize.x *= ImageWidth/m_assetImageExtent.x;
gridSize.y *= ImageHeight/m_assetImageExtent.y;
ImDrawList *draw_list = ImGui::GetWindowDrawList();
auto gridCountX = ImageWidth / gridSize.x;
auto gridCountY = ImageHeight / gridSize.y;
ImU32 grid_color = IM_COL32(200, 200, 200, 50);
float grid_thickness = 1.0f;
ImGui::Dummy(ImVec2(ImageWidth, ImageHeight));
for (int i = 0; i <= gridCountX; ++i)
{
ImVec2 p1 = ImVec2(base_pos.x + i * gridSize.x, base_pos.y);
ImVec2 p2 = ImVec2(base_pos.x + i * gridSize.x, base_pos.y + ImageHeight);
draw_list->AddLine(p1, p2, grid_color, grid_thickness);
}
for (int i = 0; i <= gridCountY; ++i)
{
ImVec2 p1 = ImVec2(base_pos.x, base_pos.y + i * gridSize.y);
ImVec2 p2 = ImVec2(base_pos.x + ImageWidth, base_pos.y + i * gridSize.y);
draw_list->AddLine(p1, p2, grid_color, grid_thickness);
}
}
VOID View_Asset::DrawAssetTypePicker()
{
ImGui::Text("Asset Type: ");
ImGui::SameLine();
ImGui::Combo("##", (INT32 *) &m_assetType, "None\0Texture\0Sprite\0TileSheet\0SpriteSheet\0");
if (m_assetType != m_asset->GetType())
{
ImGui::SameLine();
if (ImGui::Button("Apply"))
{
if (m_assetType == EAssetType::INVALID)
{
Editor::Instance().RemoveFromAssets(m_assetName);
Close();
UI::CloseAssetView();
}
m_asset = AssetManager::ChangeAssetType(m_assetName, m_assetType);
}
}
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -147,6 +147,6 @@ namespace ia::iae
VOID View_AssetBrowser::OpenAsset(IN CONST std::filesystem::path &path) VOID View_AssetBrowser::OpenAsset(IN CONST std::filesystem::path &path)
{ {
Editor::Instance().OpenAsset(path); Editor::Instance().OpenFile(path);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -0,0 +1,170 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@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 <UI/View/FilePreview.hpp>
#include <IAEngine/Asset/AssetManager.hpp>
#include <RenderCore/RenderCore.hpp>
#include <Editor.hpp>
#include <fstream>
namespace ia::iae
{
BOOL is_extension_one_of(IN PCCHAR ext, IN std::initializer_list<PCCHAR> values)
{
for (const auto &t : values)
{
if (!strcmp(ext, t))
return true;
}
return false;
}
Vector<String> get_lines_of_file(IN CONST Path &path)
{
Vector<String> result;
std::string line;
std::ifstream file(path);
while (std::getline(file, line))
result.pushBack(line.c_str());
return result;
}
VOID View_FilePreview::Initialize()
{
SetName("File Preview");
SetIcon(ICON_FA_MAGNIFYING_GLASS);
}
VOID View_FilePreview::Terminate()
{
}
VOID View_FilePreview::Render()
{
PreRender();
if (m_filePath.empty())
{
PostRender();
return;
}
switch (m_fileType)
{
case EFileType::UNKNOWN:
RenderUnknownFile();
break;
case EFileType::TEXT:
RenderTextFile();
break;
case EFileType::IMAGE:
RenderImageFile();
break;
}
PostRender();
}
VOID View_FilePreview::Update()
{
}
VOID View_FilePreview::OnEvent(IN SDL_Event *event)
{
}
VOID View_FilePreview::Open(IN Path path)
{
Close();
m_filePath = path;
m_fileType = EFileType::UNKNOWN;
const auto ext = path.extension().string();
if (is_extension_one_of(&ext[1], {"txt", "xml", "md", "cpp", "c", "hpp", "h"}))
{
m_fileType = EFileType::TEXT;
const auto lines = get_lines_of_file(path);
m_fileDataSize = lines.size();
const auto fileData = new String[m_fileDataSize];
for (SIZE_T i = 0; i < m_fileDataSize; i++)
fileData[i] = lines[i];
m_fileData = fileData;
}
else if (is_extension_one_of(&ext[1], {"png", "jpg", "webp"}))
{
m_fileType = EFileType::IMAGE;
m_fileDataSize = SIZE_MAX;
const auto image = AssetManager::LoadTexture(path.string().c_str())->GetHandle()->ImagePtr;
m_fileDataExtent = IVec2{image->Width, image->Height};
m_fileData = (PVOID)RDC::BakeTexture(image);
}
}
VOID View_FilePreview::Close()
{
switch (m_fileType)
{
case EFileType::UNKNOWN:
break;
case EFileType::TEXT:
delete[] ((String *) m_fileData);
m_fileDataSize = 0;
m_fileData = nullptr;
break;
case EFileType::IMAGE:
m_fileDataSize = 0;
m_fileData = nullptr;
m_fileDataExtent = {};
break;
}
m_filePath = Path();
m_fileType = EFileType::UNKNOWN;
}
VOID View_FilePreview::RenderTextFile()
{
const auto lines = (String*)m_fileData;
for(SIZE_T i = 0; i < m_fileDataSize; i++)
ImGui::Text("%s", lines[i].c_str());
}
VOID View_FilePreview::RenderImageFile()
{
UI::PadX();
UI::PadY();
if(ImGui::Button("Mark as Asset"))
Editor::Instance().MarkAsAsset(m_filePath);
UI::PadY();
const auto ImageWidth = m_extent.x * 0.75f;
UI::AlignCursorHCenter(ImRect{{}, m_extent}, ImageWidth);
const auto aspectRatio = static_cast<FLOAT32>(m_fileDataExtent.y)/static_cast<FLOAT32>(m_fileDataExtent.x);
ImGui::Image((ImTextureRef)m_fileData, {ImageWidth, aspectRatio * ImageWidth});
}
VOID View_FilePreview::RenderUnknownFile()
{
UI::DrawTextCentered(m_extent, "Unsupported File Format");
}
} // namespace ia::iae

View File

@ -0,0 +1,99 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@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 <Editor.hpp>
#include <UI/View/Game.hpp>
#include <RenderCore/RenderCore.hpp>
#include <IAEngine/LibInterface.hpp>
namespace ia::iae
{
VOID View_Game::Initialize()
{
SetName("Game");
SetIcon(ICON_FA_GAMEPAD);
IAEngine::__Initialize(SCENE_EDITOR_RESOULTION, Editor::Instance().GetActiveProject()->AssetDirectory());
m_gameRenderTexture = new RDC_Texture(RDC_Texture::EType::SAMPLED, SCENE_EDITOR_RESOULTION.x, SCENE_EDITOR_RESOULTION.y);
}
VOID View_Game::Terminate()
{
delete m_gameRenderTexture;
}
VOID View_Game::Render()
{
PreRender();
ImGui::Image(m_gameRenderTexture->GetHandle(), m_extent);
PostRender();
}
VOID View_Game::Update()
{
STATIC INT32 frameCounter{0};
IAEngine::__Update();
frameCounter++;
if (frameCounter >= 60)
{
frameCounter = 0;
IAEngine::__FixedUpdate();
}
IAEngine::__RenderToTexture(m_gameRenderTexture->GetHandle());
}
VOID View_Game::OnEvent(IN SDL_Event *event)
{
IAEngine::__ProcessEvent(event);
}
} // namespace ia::iae
C_DECL(GameRequestedConfig *Game_GetConfigRequest())
{
return nullptr;
}
C_DECL(VOID Game_OnInitialize())
{
}
C_DECL(VOID Game_OnTerminate())
{
}
C_DECL(VOID Game_OnDebugDraw())
{
}
C_DECL(VOID Game_OnFixedUpdate())
{
}
C_DECL(VOID Game_OnUpdate(IN FLOAT32 deltaTime))
{
}
C_DECL(VOID Game_OnResize(IN INT32 newWidth, IN INT32 newHeight))
{
}

View File

@ -19,8 +19,6 @@
#include <RenderCore/RenderCore.hpp> #include <RenderCore/RenderCore.hpp>
#include <IAEngine/LibInterface.hpp>
namespace ia::iae namespace ia::iae
{ {
VOID View_Scene::Initialize() VOID View_Scene::Initialize()
@ -28,21 +26,16 @@ namespace ia::iae
SetName("Scene"); SetName("Scene");
SetIcon(ICON_FA_HASHTAG); SetIcon(ICON_FA_HASHTAG);
IAEngine::__Initialize(SCENE_EDITOR_RESOULTION, Editor::Instance().GetActiveProject()->AssetDirectory());
m_gamePreviewTexture = new RDC_Texture(RDC_Texture::EType::SAMPLED, SCENE_EDITOR_RESOULTION.x, SCENE_EDITOR_RESOULTION.y);
} }
VOID View_Scene::Terminate() VOID View_Scene::Terminate()
{ {
delete m_gamePreviewTexture;
} }
VOID View_Scene::Render() VOID View_Scene::Render()
{ {
PreRender(); PreRender();
ImGui::Image(m_gamePreviewTexture->GetHandle(), {SCENE_EDITOR_RESOULTION.x, SCENE_EDITOR_RESOULTION.y});
PostRender(); PostRender();
} }
@ -51,49 +44,9 @@ namespace ia::iae
{ {
STATIC INT32 frameCounter{0}; STATIC INT32 frameCounter{0};
IAEngine::__Update();
frameCounter++;
if (frameCounter >= 60)
{
frameCounter = 0;
IAEngine::__FixedUpdate();
}
IAEngine::__RenderToTexture(m_gamePreviewTexture->GetHandle());
} }
VOID View_Scene::OnEvent(IN SDL_Event *event) VOID View_Scene::OnEvent(IN SDL_Event *event)
{ {
IAEngine::__ProcessEvent(event);
} }
} // namespace ia::iae } // namespace ia::iae
C_DECL(GameRequestedConfig *Game_GetConfigRequest())
{
return nullptr;
}
C_DECL(VOID Game_OnInitialize())
{
}
C_DECL(VOID Game_OnTerminate())
{
}
C_DECL(VOID Game_OnDebugDraw())
{
}
C_DECL(VOID Game_OnFixedUpdate())
{
}
C_DECL(VOID Game_OnUpdate(IN FLOAT32 deltaTime))
{
}
C_DECL(VOID Game_OnResize(IN INT32 newWidth, IN INT32 newHeight))
{
}

View File

@ -33,7 +33,9 @@ namespace ia::iae
public: public:
VOID LoadProject(IN CONST String &directory); VOID LoadProject(IN CONST String &directory);
VOID OpenAsset(IN Path path); VOID OpenFile(IN Path path);
VOID MarkAsAsset(IN Path path);
VOID RemoveFromAssets(IN CONST String& assetName);
public: public:
CONST Project *GetActiveProject() CONST CONST Project *GetActiveProject() CONST

View File

@ -22,6 +22,13 @@ namespace ia::iae
{ {
class TabContainer class TabContainer
{ {
struct Tab
{
IView* View{};
BOOL IsOpen{true};
BOOL IsCloseable{false};
};
public: public:
TabContainer(); TabContainer();
@ -31,10 +38,13 @@ namespace ia::iae
VOID Update(); VOID Update();
VOID ProcessEvent(IN SDL_Event *event); VOID ProcessEvent(IN SDL_Event *event);
template<typename ViewType> INLINE VOID AddTab(IN CONST String &name); template<typename ViewType> INLINE VOID AddTab(IN CONST String &name, IN BOOL isCloseable = false);
IView *GetTab(IN CONST String &name); IView *GetTab(IN CONST String &name);
VOID RemoveTab(IN CONST String &name); VOID RemoveTab(IN CONST String &name);
VOID OpenTab(IN CONST String& name);
VOID CloseTab(IN CONST String& name);
VOID ChangeActiveTab(IN PCCHAR name); VOID ChangeActiveTab(IN PCCHAR name);
private: private:
@ -42,14 +52,14 @@ namespace ia::iae
CONST String m_containerID; CONST String m_containerID;
PCCHAR m_activeTabName{}; PCCHAR m_activeTabName{};
PCCHAR m_pendingActiveTabName{}; PCCHAR m_pendingActiveTabName{};
Map<String, IView *> m_tabViews; Map<String, Tab> m_tabViews;
private: private:
VOID AddTab(IN CONST String &name, IN IView *view); VOID AddTab(IN CONST String &name, IN IView *view, IN BOOL isCloseable);
}; };
template<typename ViewType> VOID TabContainer::AddTab(IN CONST String &name) template<typename ViewType> VOID TabContainer::AddTab(IN CONST String &name, IN BOOL isCloseable)
{ {
AddTab(name, new ViewType()); AddTab(name, new ViewType(), isCloseable);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -33,10 +33,16 @@ namespace ia::iae
STATIC VOID AlignCursorHCenter(IN CONST ImRect &rect, IN FLOAT32 width); STATIC VOID AlignCursorHCenter(IN CONST ImRect &rect, IN FLOAT32 width);
STATIC VOID AlignCursorVCenter(IN CONST ImRect &rect, IN FLOAT32 height); STATIC VOID AlignCursorVCenter(IN CONST ImRect &rect, IN FLOAT32 height);
STATIC VOID DrawTextCentered(IN CONST ImVec2& viewExtent, IN CONST String& text);
public: public:
STATIC VOID FocusAssetView(); STATIC VOID OpenFilePreviewView();
STATIC VOID CloseFilePreviewView();
STATIC VOID OpenAssetView();
STATIC VOID CloseAssetView();
STATIC class View_Asset* GetAssetView(); STATIC class View_Asset* GetAssetView();
STATIC class View_FilePreview *GetFilePreviewView();
STATIC class IView *GetFocusedView() STATIC class IView *GetFocusedView()
{ {

View File

@ -18,12 +18,14 @@
#include <UI/View/IView.hpp> #include <UI/View/IView.hpp>
#include <IAEngine/Asset/IAsset.hpp>
namespace ia::iae namespace ia::iae
{ {
class View_Asset : public IView class View_Asset : public IView
{ {
public: public:
VOID Open(IN Path path); VOID Open(IN String assetName);
VOID Close(); VOID Close();
public: public:
@ -36,6 +38,19 @@ namespace ia::iae
VOID OnEvent(IN SDL_Event *event); VOID OnEvent(IN SDL_Event *event);
private: private:
Path m_assetPath{}; VOID RenderTextureAsset();
VOID RenderSpriteAsset();
VOID RenderTileSheetAsset();
VOID RenderSpriteSheetAsset();
VOID DrawAssetTypePicker();
VOID DrawAssetImage(IN FLOAT32 relativeWidth, IN IVec2 gridSize);
private:
class IAsset *m_asset{};
String m_assetName{};
Handle m_assetImageHandle{};
IVec2 m_assetImageExtent{};
EAssetType m_assetType{};
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -0,0 +1,58 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@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 <UI/View/IView.hpp>
namespace ia::iae
{
class View_FilePreview : public IView
{
enum class EFileType
{
UNKNOWN,
TEXT,
IMAGE,
};
public:
VOID Open(IN Path path);
VOID Close();
public:
VOID Initialize();
VOID Terminate();
VOID Render();
VOID Update();
protected:
VOID OnEvent(IN SDL_Event *event);
private:
VOID RenderTextFile();
VOID RenderImageFile();
VOID RenderUnknownFile();
private:
Path m_filePath{};
EFileType m_fileType{EFileType::UNKNOWN};
PVOID m_fileData{};
SIZE_T m_fileDataSize{};
IVec2 m_fileDataExtent{};
};
} // namespace ia::iae

View File

@ -0,0 +1,43 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@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 <UI/View/IView.hpp>
namespace ia::iae
{
class View_Game : public IView
{
public:
VOID Initialize();
VOID Terminate();
VOID Render();
VOID Update();
protected:
VOID OnEvent(IN SDL_Event *event);
public:
VOID ProcessEvent(IN SDL_Event *event)
{
OnEvent(event);
}
private:
class RDC_Texture* m_gameRenderTexture;
};
} // namespace ia::iae

View File

@ -71,7 +71,7 @@ namespace ia::iae
VOID IView::PreRender() VOID IView::PreRender()
{ {
m_extent = ImGui::GetWindowSize(); m_extent = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##"); ImGui::BeginChild("##");
} }

View File

@ -36,8 +36,5 @@ namespace ia::iae
{ {
OnEvent(event); OnEvent(event);
} }
private:
class RDC_Texture* m_gamePreviewTexture;
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -26,13 +26,18 @@
#include <IACore/DynamicLib.hpp> #include <IACore/DynamicLib.hpp>
#include <filesystem>
namespace ia::iae namespace ia::iae
{ {
Map<String, String> g_assetNameToPathMap;
Map<String, String> g_assetPathToNameMap;
String AssetManager::s_assetDirectory; String AssetManager::s_assetDirectory;
Vector<IAsset *> AssetManager::s_assets; Vector<IAsset *> AssetManager::s_assets;
Map<String, IAsset *> AssetManager::s_assetNames; Map<String, IAsset *> AssetManager::s_assetNames;
Handle CreateTextureFromFile(IN PCCHAR path, IN INT32 tileWidth = -1, IN INT32 tileHeight = -1) ImageView *CreateTextureFromFile(IN PCCHAR path, IN INT32 tileWidth = -1, IN INT32 tileHeight = -1)
{ {
const auto data = AssetManager::ReadBinaryAsset(path); const auto data = AssetManager::ReadBinaryAsset(path);
@ -40,8 +45,8 @@ namespace ia::iae
auto pixels = stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, STBI_rgb_alpha); auto pixels = stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, STBI_rgb_alpha);
if (!pixels) if (!pixels)
THROW_INVALID_DATA(path); THROW_INVALID_DATA(path);
const auto t = const auto t = RDC::CreateImageView(RDC::CreateImage(pixels, w, h), tileWidth == -1 ? 1 : w / tileWidth,
RDC::CreateImage(pixels, w, h, tileWidth == -1 ? 1 : w / tileWidth, tileHeight == -1 ? 1 : h / tileHeight); tileHeight == -1 ? 1 : h / tileHeight);
stbi_image_free(pixels); stbi_image_free(pixels);
return t; return t;
} }
@ -56,6 +61,65 @@ namespace ia::iae
DestroyAsset(s_assets[i]); DestroyAsset(s_assets[i]);
} }
String get_relative_asset_path(IN CONST String& _path)
{
std::string __path = _path.c_str();
const auto t = std::filesystem::path(_path.c_str());
return t.is_absolute() ? String(__path.substr(__path.find("Assets") + 7).c_str()) : _path;
}
String AssetManager::GetAssetName(IN CONST String &_path)
{
const auto path = get_relative_asset_path(_path);
if(g_assetPathToNameMap.contains(path))
return g_assetPathToNameMap[path];
return "";
}
IAsset* AssetManager::ChangeAssetType(IN CONST String& assetName, IN EAssetType newType)
{
if(!s_assetNames.contains(assetName))
return nullptr;
const auto currentAsset = (Asset_Texture*)s_assetNames[assetName];
if(newType == currentAsset->GetType())
return currentAsset;
IAsset* asset{};
switch(newType)
{
case EAssetType::TEXTURE:
asset = new Asset_Texture(currentAsset->GetHandle());
break;
case EAssetType::SPRITE:
asset = new Asset_Sprite(currentAsset->GetHandle());
break;
case EAssetType::TILESHEET:
asset = new Asset_TileSheet(currentAsset->GetHandle(), currentAsset->GetHandle()->ImagePtr->Width, currentAsset->GetHandle()->ImagePtr->Height);
break;
case EAssetType::SPRITESHEET:
asset = new Asset_SpriteSheet(currentAsset->GetHandle(), currentAsset->GetHandle()->ImagePtr->Width, currentAsset->GetHandle()->ImagePtr->Height, {});
break;
case EAssetType::INVALID:
case EAssetType::SOUND:
case EAssetType::SCENE:
case EAssetType::PLUGIN:
case EAssetType::PACKAGE:
break;
}
DestroyAsset(s_assetNames[assetName]);
s_assetNames[assetName] = asset;
return asset;
}
VOID AssetManager::SetAssetDirectory(IN CONST String &path) VOID AssetManager::SetAssetDirectory(IN CONST String &path)
{ {
s_assetDirectory = path; s_assetDirectory = path;
@ -63,7 +127,8 @@ namespace ia::iae
String AssetManager::ReadTextAsset(IN CONST String &path) String AssetManager::ReadTextAsset(IN CONST String &path)
{ {
const auto t = BuildString(s_assetDirectory, "/", path); const auto t =
std::filesystem::path(path.c_str()).is_absolute() ? path : BuildString(s_assetDirectory, "/", path);
SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "r"); SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "r");
if (!f) if (!f)
THROW_FILE_OPEN_READ(t); THROW_FILE_OPEN_READ(t);
@ -79,7 +144,8 @@ namespace ia::iae
Vector<UINT8> AssetManager::ReadBinaryAsset(IN CONST String &path) Vector<UINT8> AssetManager::ReadBinaryAsset(IN CONST String &path)
{ {
const auto t = BuildString(s_assetDirectory, "/", path); const auto t =
std::filesystem::path(path.c_str()).is_absolute() ? path : BuildString(s_assetDirectory, "/", path);
SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "rb"); SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "rb");
if (!f) if (!f)
THROW_FILE_OPEN_READ(t); THROW_FILE_OPEN_READ(t);
@ -94,25 +160,19 @@ namespace ia::iae
Asset_Texture *AssetManager::LoadTexture(IN CONST String &path) Asset_Texture *AssetManager::LoadTexture(IN CONST String &path)
{ {
const auto t = new Asset_Sprite(CreateTextureFromFile(path.c_str())); const auto t = new Asset_Texture(CreateTextureFromFile(path.c_str()));
t->SetPath(get_relative_asset_path(path));
s_assets.pushBack(t); s_assets.pushBack(t);
return t; return t;
} }
Asset_Sprite *AssetManager::LoadSprite(IN CONST String &path) Asset_Sprite *AssetManager::LoadSprite(IN CONST String &path)
{ {
const auto t = new Asset_Sprite(CreateTextureFromFile(path.c_str())); return nullptr;
s_assets.pushBack(t);
return t;
} }
Asset_SpriteSheet *AssetManager::LoadSpriteSheet(IN CONST String &path) Asset_SpriteSheet *AssetManager::LoadSpriteSheet(IN CONST String &path)
{ {
// const auto t = new Asset_SpriteSheet();
// t->m_frameCounts = frameCounts;
// t->m_texture = CreateTextureFromFile(path.c_str(), spriteWidth, spriteHeight);
// s_assets.pushBack(t);
// return t;
return nullptr; return nullptr;
} }
@ -128,16 +188,22 @@ namespace ia::iae
Asset_Texture *AssetManager::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height) Asset_Texture *AssetManager::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
{ {
return nullptr; return new Asset_Texture(RDC::CreateImageView(RDC::CreateImage(rgbaData, width, height)));
} }
Asset_Sprite *AssetManager::CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height) Asset_Sprite *AssetManager::CreateSprite(IN CONST Asset_Texture *texture)
{
return new Asset_Sprite(texture->m_handle);
}
Asset_SpriteSheet *AssetManager::CreateSpriteSheet(IN CONST Vector<Asset_Texture *> &sprites,
IN CONST Map<String, INT32> &animations)
{ {
return nullptr; return nullptr;
} }
Asset_SpriteSheet *AssetManager::CreateSpriteSheet(IN CONST Asset_Texture *texture, IN INT32 spriteWidth, Asset_SpriteSheet *AssetManager::CreateSpriteSheet(IN CONST Asset_Texture *texture, IN INT32 frameWidth,
IN INT32 spriteHeight, IN CONST Vector<INT32> &frameCounts) IN INT32 frameHeight, IN CONST Map<String, INT32> &animations)
{ {
return nullptr; return nullptr;
} }
@ -145,7 +211,9 @@ namespace ia::iae
Asset_TileSheet *AssetManager::CreateTileSheet(IN CONST Asset_Texture *texture, IN INT32 tileWidth, Asset_TileSheet *AssetManager::CreateTileSheet(IN CONST Asset_Texture *texture, IN INT32 tileWidth,
IN INT32 tileHeight) IN INT32 tileHeight)
{ {
const auto t = new Asset_TileSheet(texture->m_handle, tileWidth, tileHeight); const auto image = texture->m_handle->ImagePtr;
const auto t = new Asset_TileSheet(
RDC::CreateImageView(image, image->Width / tileWidth, image->Height / tileHeight), tileWidth, tileHeight);
s_assets.pushBack(t); s_assets.pushBack(t);
return t; return t;
} }
@ -172,6 +240,8 @@ namespace ia::iae
VOID AssetManager::AssignAssetName(IN IAsset *asset, IN CONST String &name) VOID AssetManager::AssignAssetName(IN IAsset *asset, IN CONST String &name)
{ {
s_assetNames[name] = asset; s_assetNames[name] = asset;
g_assetNameToPathMap[name] = asset->GetPath();
g_assetPathToNameMap[asset->GetPath()] = name;
} }
Asset_Scene *AssetManager::CreateScene(IN IVec2 extent) Asset_Scene *AssetManager::CreateScene(IN IVec2 extent)

View File

@ -86,7 +86,7 @@ namespace ia::iae
else if (!strcmp(entry.name(), "TileSheet")) else if (!strcmp(entry.name(), "TileSheet"))
{ {
AssetManager::AssignAssetName( AssetManager::AssignAssetName(
AssetManager::CreateTileSheet(entry.attribute("path").as_string(), AssetManager::CreateTileSheet(AssetManager::LoadTexture(entry.attribute("path").as_string()),
entry.attribute("tileWidth").as_int(), entry.attribute("tileWidth").as_int(),
entry.attribute("tileHeight").as_int()), entry.attribute("tileHeight").as_int()),
entry.attribute("name").as_string()); entry.attribute("name").as_string());

View File

@ -44,14 +44,18 @@ namespace ia::iae
STATIC Asset_Scene *CreateScene(IN IVec2 extent); STATIC Asset_Scene *CreateScene(IN IVec2 extent);
STATIC Asset_Texture *CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); STATIC Asset_Texture *CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
STATIC Asset_Sprite *CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); STATIC Asset_Sprite *CreateSprite(IN CONST Asset_Texture *texture);
STATIC Asset_SpriteSheet *CreateSpriteSheet(IN CONST Asset_Texture *texture, IN INT32 spriteWidth, STATIC Asset_SpriteSheet *CreateSpriteSheet(IN CONST Vector<Asset_Texture*>& sprites, IN CONST Map<String, INT32> &animations);
IN INT32 spriteHeight, IN CONST Vector<INT32> &frameCounts); STATIC Asset_SpriteSheet *CreateSpriteSheet(IN CONST Asset_Texture *texture, IN INT32 frameWidth,
IN INT32 frameHeight, IN CONST Map<String, INT32> &animations);
STATIC Asset_TileSheet *CreateTileSheet(IN CONST Asset_Texture *texture, IN INT32 tileWidth, STATIC Asset_TileSheet *CreateTileSheet(IN CONST Asset_Texture *texture, IN INT32 tileWidth,
IN INT32 tileHeight); IN INT32 tileHeight);
STATIC VOID DestroyAsset(IN IAsset *asset); STATIC VOID DestroyAsset(IN IAsset *asset);
STATIC VOID AssignAssetName(IN IAsset *asset, IN CONST String &name); STATIC VOID AssignAssetName(IN IAsset *asset, IN CONST String &name);
STATIC String GetAssetName(IN CONST String& path);
STATIC IAsset* ChangeAssetType(IN CONST String& assetName, IN EAssetType newType);
template<typename AssetType> template<typename AssetType>
requires std::is_base_of<IAsset, AssetType>::value requires std::is_base_of<IAsset, AssetType>::value

View File

@ -20,7 +20,7 @@
namespace ia::iae namespace ia::iae
{ {
enum class EAssetType enum class EAssetType: INT32
{ {
INVALID, INVALID,
@ -43,7 +43,24 @@ namespace ia::iae
PURE_VIRTUAL(VOID Compile()); PURE_VIRTUAL(VOID Compile());
PURE_VIRTUAL(VOID Destroy()); PURE_VIRTUAL(VOID Destroy());
public:
String GetPath() CONST
{
return m_path;
}
VOID SetPath(IN CONST String &path)
{
m_path = path;
}
EAssetType GetType() CONST
{
return m_type;
}
protected: protected:
String m_path;
CONST EAssetType m_type; CONST EAssetType m_type;
}; };
} } // namespace ia::iae

View File

@ -23,7 +23,7 @@ namespace ia::iae
class Asset_Sprite : public Asset_Texture class Asset_Sprite : public Asset_Texture
{ {
public: public:
Asset_Sprite(IN Handle textureHandle) : Asset_Texture(textureHandle, EAssetType::SPRITE) Asset_Sprite(IN ImageView* textureHandle) : Asset_Texture(textureHandle, EAssetType::SPRITE)
{ {
} }

View File

@ -30,20 +30,35 @@ namespace ia::iae
}; };
public: public:
Asset_SpriteSheet(IN Handle textureHandle, IN INT32 frameWidth, IN INT32 frameHeight, Asset_SpriteSheet(IN ImageView *textureHandle, IN INT32 frameWidth, IN INT32 frameHeight,
IN Map<String, AnimationDesc> &&animations) IN Map<String, AnimationDesc> &&animations)
: Asset_Texture(textureHandle, EAssetType::SPRITESHEET), m_frameWidth(frameWidth), m_frameHeight(frameHeight), : Asset_Texture(textureHandle, EAssetType::SPRITESHEET), m_frameWidth(frameWidth),
m_animations(IA_MOVE(animations)) m_frameHeight(frameHeight), m_animations(IA_MOVE(animations))
{ {
} }
VIRTUAL VOID Compile(); VIRTUAL VOID Compile();
VIRTUAL VOID Destroy(); VIRTUAL VOID Destroy();
INT32 &FrameWidth()
{
return m_frameWidth;
}
INT32 &FrameHeight()
{
return m_frameHeight;
}
Map<String, AnimationDesc> &Animations()
{
return m_animations;
}
protected: protected:
CONST INT32 m_frameWidth; INT32 m_frameWidth;
CONST INT32 m_frameHeight; INT32 m_frameHeight;
CONST Map<String, AnimationDesc> m_animations; Map<String, AnimationDesc> m_animations;
friend class AssetManager; friend class AssetManager;
}; };

View File

@ -23,26 +23,26 @@ namespace ia::iae
class Asset_Texture : public IAsset class Asset_Texture : public IAsset
{ {
public: public:
Asset_Texture(IN Handle handle) : IAsset(EAssetType::TEXTURE), m_handle(handle) Asset_Texture(IN ImageView* handle) : IAsset(EAssetType::TEXTURE), m_handle(handle)
{ {
} }
Asset_Texture(IN Handle handle, IN EAssetType type) : IAsset(type), m_handle(handle) Asset_Texture(IN ImageView* handle, IN EAssetType type) : IAsset(type), m_handle(handle)
{ {
} }
VIRTUAL VOID Compile(); VIRTUAL VOID Compile();
VIRTUAL VOID Destroy(); VIRTUAL VOID Destroy();
INLINE Handle GetHandle(); INLINE ImageView* GetHandle();
protected: protected:
CONST Handle m_handle; ImageView* CONST m_handle;
friend class AssetManager; friend class AssetManager;
}; };
INLINE Handle Asset_Texture::GetHandle() INLINE ImageView* Asset_Texture::GetHandle()
{ {
return m_handle; return m_handle;
} }

View File

@ -23,7 +23,7 @@ namespace ia::iae
class Asset_TileSheet : public Asset_Texture class Asset_TileSheet : public Asset_Texture
{ {
public: public:
Asset_TileSheet(IN Handle textureHandle, IN INT32 tileWidth, IN INT32 tileHeight) Asset_TileSheet(IN ImageView *textureHandle, IN INT32 tileWidth, IN INT32 tileHeight)
: Asset_Texture(textureHandle, EAssetType::TILESHEET), m_tileWidth(tileWidth), m_tileHeight(tileHeight) : Asset_Texture(textureHandle, EAssetType::TILESHEET), m_tileWidth(tileWidth), m_tileHeight(tileHeight)
{ {
} }
@ -31,9 +31,19 @@ namespace ia::iae
VIRTUAL VOID Compile(); VIRTUAL VOID Compile();
VIRTUAL VOID Destroy(); VIRTUAL VOID Destroy();
INT32 &TileWidth()
{
return m_tileWidth;
}
INT32 &TileHeight()
{
return m_tileHeight;
}
protected: protected:
CONST INT32 m_tileWidth; INT32 m_tileWidth;
CONST INT32 m_tileHeight; INT32 m_tileHeight;
friend class AssetManager; friend class AssetManager;
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -50,6 +50,8 @@ namespace ia::iae
INT32 RDC::s_primitiveInstanceCount{}; INT32 RDC::s_primitiveInstanceCount{};
GeometryVertex RDC::s_primitiveInstances[RDC::MAX_PRIMITIVE_COUNT]; GeometryVertex RDC::s_primitiveInstances[RDC::MAX_PRIMITIVE_COUNT];
Vector<RDC_Texture*> g_managedBakedTextures;
VOID RDC::Initialize(IN IVec2 viewportExtent, IN SDL_Window *windowHandle, IN BOOL isDebugMode) VOID RDC::Initialize(IN IVec2 viewportExtent, IN SDL_Window *windowHandle, IN BOOL isDebugMode)
{ {
if (s_windowHandle) if (s_windowHandle)
@ -77,6 +79,9 @@ namespace ia::iae
RDC_Device::DestroyGeometry(s_quadGeometry); RDC_Device::DestroyGeometry(s_quadGeometry);
for (const auto &t : g_managedBakedTextures)
delete t;
SDL_ReleaseGPUSampler(RDC_Device::GetHandle(), s_linearClampSampler); SDL_ReleaseGPUSampler(RDC_Device::GetHandle(), s_linearClampSampler);
SDL_ReleaseGPUSampler(RDC_Device::GetHandle(), s_linearRepeatSampler); SDL_ReleaseGPUSampler(RDC_Device::GetHandle(), s_linearRepeatSampler);
@ -190,29 +195,26 @@ namespace ia::iae
RDC_Device::WaitForIdle(); RDC_Device::WaitForIdle();
} }
Vec2 RDC::DrawSpriteTopLeft(IN Handle _image, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position, Vec2 RDC::DrawSpriteTopLeft(IN ImageView *imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset)
{ {
const auto image = (ImageData *) _image; const auto _s = Vec2{scale.x * imageView->TileWidth, scale.y * imageView->TileHeight};
const auto _s = Vec2{scale.x * image->TileWidth, scale.y * image->TileHeight};
Mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y, 0}); Mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y, 0});
transform = glm::rotate(transform, rotation, glm::vec3(0.0f, 0.0f, 1.0f)); transform = glm::rotate(transform, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
transform = glm::scale(transform, glm::vec3(_s, 1.0f)); transform = glm::scale(transform, glm::vec3(_s, 1.0f));
s_spriteInstances[s_spriteInstanceCount++] = { s_spriteInstances[s_spriteInstanceCount++] = {
.Transform = transform, .Transform = transform,
.TexCoords = s_dynamicSpriteAtlas ? s_dynamicSpriteAtlas->GetTextureCoordinates( .TexCoords = s_dynamicSpriteAtlas ? s_dynamicSpriteAtlas->GetTextureCoordinates(
_image, tileIndexX, tileIndexY, flipH, flipV, uvOffset) imageView, tileIndexX, tileIndexY, flipH, flipV, uvOffset)
: Vec4{0.0f, 0.0f, 1.0f, 1.0f}, : Vec4{0.0f, 0.0f, 1.0f, 1.0f},
.Color = {1.0f, 1.0f, 1.0f, 1.0f}}; .Color = {1.0f, 1.0f, 1.0f, 1.0f}};
return _s; return _s;
} }
Vec2 RDC::DrawSpriteCentered(IN Handle _image, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position, Vec2 RDC::DrawSpriteCentered(IN ImageView *imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset)
{ {
const auto image = (ImageData *) _image; const auto _s = Vec2{scale.x * imageView->TileWidth, scale.y * imageView->TileHeight};
const auto _s = Vec2{scale.x * image->TileWidth, scale.y * image->TileHeight};
Mat4 transform = Mat4 transform =
glm::translate(glm::mat4(1.0f), glm::vec3{position.x - _s.x / 2.0f, position.y - _s.y / 2.0f, 0}); glm::translate(glm::mat4(1.0f), glm::vec3{position.x - _s.x / 2.0f, position.y - _s.y / 2.0f, 0});
transform = glm::rotate(transform, rotation, glm::vec3(0.0f, 0.0f, 1.0f)); transform = glm::rotate(transform, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
@ -220,7 +222,7 @@ namespace ia::iae
s_spriteInstances[s_spriteInstanceCount++] = { s_spriteInstances[s_spriteInstanceCount++] = {
.Transform = transform, .Transform = transform,
.TexCoords = s_dynamicSpriteAtlas ? s_dynamicSpriteAtlas->GetTextureCoordinates( .TexCoords = s_dynamicSpriteAtlas ? s_dynamicSpriteAtlas->GetTextureCoordinates(
_image, tileIndexX, tileIndexY, flipH, flipV, uvOffset) imageView, tileIndexX, tileIndexY, flipH, flipV, uvOffset)
: Vec4{0.0f, 0.0f, 1.0f, 1.0f}, : Vec4{0.0f, 0.0f, 1.0f, 1.0f},
.Color = {1.0f, 1.0f, 1.0f, 1.0f}}; .Color = {1.0f, 1.0f, 1.0f, 1.0f}};
return _s; return _s;
@ -263,34 +265,50 @@ namespace ia::iae
s_viewMatrix = glm::lookAtLH(glm::vec3{s_cameraPosition, -1.0f}, {s_cameraPosition, 0.0f}, {0.0f, 1.0f, 0.0f}); s_viewMatrix = glm::lookAtLH(glm::vec3{s_cameraPosition, -1.0f}, {s_cameraPosition, 0.0f}, {0.0f, 1.0f, 0.0f});
} }
Handle RDC::CreateImage(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height, IN INT32 tileCountX, Image *RDC::CreateImage(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
IN INT32 tileCountY)
{ {
const auto pixelDataSize = width * height * 4; const auto pixelDataSize = width * height * 4;
const auto image = new ImageData{ const auto image = new Image{.Pixels = new UINT8[pixelDataSize], .Width = width, .Height = height};
.Pixels = new UINT8[pixelDataSize],
.Width = width, ia_memcpy(image->Pixels, rgbaData, pixelDataSize);
.Height = height,
.TileWidth = width / tileCountX, return image;
.TileHeight = height / tileCountY, }
ImageView *RDC::CreateImageView(IN Image *image, IN INT32 tileCountX, IN INT32 tileCountY)
{
const auto imageView = new ImageView{
.ImagePtr = image,
.TileWidth = image->Width / tileCountX,
.TileHeight = image->Height / tileCountY,
.TileCountX = tileCountX, .TileCountX = tileCountX,
.TileCountY = tileCountY, .TileCountY = tileCountY,
}; };
ia_memcpy(image->Pixels, rgbaData, pixelDataSize); return imageView;
return (Handle) image;
} }
VOID RDC::DestroyImage(IN Handle _image) VOID RDC::DestroyImage(IN Image *image)
{ {
const auto image = (ImageData *) _image;
delete[] image->Pixels; delete[] image->Pixels;
delete image; delete image;
} }
VOID RDC::CompileTextures(IN CONST Vector<Handle> &images) VOID RDC::DestroyImageView(IN ImageView *imageView)
{
delete imageView;
}
Handle RDC::BakeTexture(IN Image *image)
{
const auto texture = new RDC_Texture(RDC_Texture::EType::SAMPLED, image->Width, image->Height);
texture->SetImageData(image->Pixels);
g_managedBakedTextures.pushBack(texture);
return (Handle)texture->GetHandle();
}
VOID RDC::CompileTextures(IN CONST Vector<Image *> &images)
{ {
if (!images.size()) if (!images.size())
return; return;

View File

@ -18,19 +18,18 @@
namespace ia::iae namespace ia::iae
{ {
RDC_TextureAtlas::RDC_TextureAtlas(IN CONST Vector<Handle> &images) RDC_TextureAtlas::RDC_TextureAtlas(IN CONST Vector<Image*> &images)
{ {
if (images.empty()) if (images.empty())
return; return;
m_atlasSize.x = 0; m_atlasSize.x = 0;
m_atlasSize.y = 0; m_atlasSize.y = 0;
for (const auto &_image : images) for (const auto &image : images)
{ {
const auto d = (ImageData *) _image; m_atlasSize.x += image->Width;
m_atlasSize.x += d->Width; if (image->Height > m_atlasSize.y)
if (d->Height > m_atlasSize.y) m_atlasSize.y = image->Height;
m_atlasSize.y = d->Height;
} }
m_inverseAtlasSize = {1.0f / ((FLOAT32) m_atlasSize.x), 1.0f / ((FLOAT32) m_atlasSize.y)}; m_inverseAtlasSize = {1.0f / ((FLOAT32) m_atlasSize.x), 1.0f / ((FLOAT32) m_atlasSize.y)};
@ -38,13 +37,12 @@ namespace ia::iae
const auto pixels = new UINT8[m_atlasSize.x * m_atlasSize.y * 4]; const auto pixels = new UINT8[m_atlasSize.x * m_atlasSize.y * 4];
INT32 atlasCursor{0}; INT32 atlasCursor{0};
for (const auto &_image : images) for (const auto &image : images)
{ {
const auto d = (ImageData *) _image; for (INT32 y = 0; y < image->Height; y++)
for (INT32 y = 0; y < d->Height; y++) ia_memcpy(&pixels[(atlasCursor + (y * m_atlasSize.x)) * 4], &image->Pixels[y * image->Width * 4], image->Width * 4);
ia_memcpy(&pixels[(atlasCursor + (y * m_atlasSize.x)) * 4], &d->Pixels[y * d->Width * 4], d->Width * 4); m_texCoordMap[(Handle)(image)] = Vec2(((FLOAT32) atlasCursor) / ((FLOAT32) m_atlasSize.x), 0.0f);
m_texCoordMap[_image] = Vec2(((FLOAT32) atlasCursor) / ((FLOAT32) m_atlasSize.x), 0.0f); atlasCursor += image->Width;
atlasCursor += d->Width;
} }
m_texture = new RDC_Texture(RDC_Texture::EType::SAMPLED, m_atlasSize.x, m_atlasSize.y); m_texture = new RDC_Texture(RDC_Texture::EType::SAMPLED, m_atlasSize.x, m_atlasSize.y);
@ -58,15 +56,14 @@ namespace ia::iae
delete m_texture; delete m_texture;
} }
Vec4 RDC_TextureAtlas::GetTextureCoordinates(IN Handle _image, IN INT32 tileIndexX, IN INT32 tileIndexY, IN BOOL flipH, Vec4 RDC_TextureAtlas::GetTextureCoordinates(IN ImageView* imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN BOOL flipH,
IN BOOL flipV, IN Vec2 uvOffset) IN BOOL flipV, IN Vec2 uvOffset)
{ {
const auto d = (ImageData *) _image; const auto &t = m_texCoordMap[(Handle)(imageView->ImagePtr)];
const auto &t = m_texCoordMap[_image]; const auto pX = ((tileIndexX + uvOffset.x) * ((FLOAT32) imageView->TileWidth)) * m_inverseAtlasSize.x;
const auto pX = ((tileIndexX + uvOffset.x) * ((FLOAT32) d->TileWidth)) * m_inverseAtlasSize.x; const auto pY = ((tileIndexY + uvOffset.y) * ((FLOAT32) imageView->TileHeight)) * m_inverseAtlasSize.y;
const auto pY = ((tileIndexY + uvOffset.y) * ((FLOAT32) d->TileHeight)) * m_inverseAtlasSize.y; auto texCoords = Vec4(t.x + pX, t.y + pY, imageView->TileWidth * m_inverseAtlasSize.x,
auto texCoords = Vec4(t.x + pX, t.y + pY, d->TileWidth * m_inverseAtlasSize.x, imageView->TileHeight * m_inverseAtlasSize.y);
d->TileHeight * m_inverseAtlasSize.y);
if (flipH) if (flipH)
{ {
texCoords.x += texCoords.z; texCoords.x += texCoords.z;

View File

@ -27,11 +27,16 @@
namespace ia::iae namespace ia::iae
{ {
struct ImageData struct Image
{ {
PUINT8 Pixels{}; PUINT8 Pixels{};
INT32 Width{}; INT32 Width{};
INT32 Height{}; INT32 Height{};
};
struct ImageView
{
Image* ImagePtr{};
INT32 TileWidth{}; INT32 TileWidth{};
INT32 TileHeight{}; INT32 TileHeight{};
INT32 TileCountX{}; INT32 TileCountX{};

View File

@ -17,10 +17,11 @@
#pragma once #pragma once
#include <RenderCore/Buffer.hpp> #include <RenderCore/Buffer.hpp>
#include <RenderCore/Texture.hpp>
#include <RenderCore/Pipeline.hpp> #include <RenderCore/Pipeline.hpp>
#include <RenderCore/Texture.hpp>
#include <RenderCore/TextureAtlas.hpp> #include <RenderCore/TextureAtlas.hpp>
namespace ia::iae namespace ia::iae
{ {
#pragma pack(push, 1) #pragma pack(push, 1)
@ -53,19 +54,24 @@ namespace ia::iae
STATIC Vec2 GetCameraPosition(); STATIC Vec2 GetCameraPosition();
STATIC VOID SetCameraPosition(IN Vec2 position); STATIC VOID SetCameraPosition(IN Vec2 position);
STATIC Vec2 DrawSpriteTopLeft(IN Handle image, IN INT32 tileIndexX, IN INT32 tileIndexY, STATIC Vec2 DrawSpriteTopLeft(IN ImageView* imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH = false, IN BOOL flipV = false, IN Vec2 uvOffset = {}); IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH = false, IN BOOL flipV = false,
STATIC Vec2 DrawSpriteCentered(IN Handle image, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 uvOffset = {});
IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH = false, IN BOOL flipV = false, IN Vec2 uvOffset = {}); STATIC Vec2 DrawSpriteCentered(IN ImageView* imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH = false, IN BOOL flipV = false,
IN Vec2 uvOffset = {});
STATIC VOID DrawLine(IN Vec2 start, IN Vec2 end, IN Vec4 color); STATIC VOID DrawLine(IN Vec2 start, IN Vec2 end, IN Vec4 color);
STATIC VOID DrawRect(IN Vec2 start, IN Vec2 end, IN Vec4 color); STATIC VOID DrawRect(IN Vec2 start, IN Vec2 end, IN Vec4 color);
STATIC Handle CreateImage(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height, IN INT32 tileCountX = 1, STATIC Image* CreateImage(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
IN INT32 tileCountY = 1); STATIC ImageView* CreateImageView(IN Image* image, IN INT32 tileCountX = 1, IN INT32 tileCountY = 1);
STATIC VOID DestroyImage(IN Handle image); STATIC VOID DestroyImage(IN Image* image);
STATIC VOID DestroyImageView(IN ImageView* imageView);
STATIC VOID CompileTextures(IN CONST Vector<Handle>& images); STATIC Handle BakeTexture(IN Image* image);
STATIC VOID CompileTextures(IN CONST Vector<Image*> &images);
private: private:
STATIC VOID InitializeSamplers(); STATIC VOID InitializeSamplers();

View File

@ -23,10 +23,10 @@ namespace ia::iae
class RDC_TextureAtlas class RDC_TextureAtlas
{ {
public: public:
RDC_TextureAtlas(IN CONST Vector<Handle> &images); RDC_TextureAtlas(IN CONST Vector<Image*> &images);
~RDC_TextureAtlas(); ~RDC_TextureAtlas();
Vec4 GetTextureCoordinates(IN Handle image, IN INT32 tileIndexX, IN INT32 tileIndexY, IN BOOL flipH, Vec4 GetTextureCoordinates(IN ImageView* imageView, IN INT32 tileIndexX, IN INT32 tileIndexY, IN BOOL flipH,
IN BOOL flipV, IN Vec2 uvOffset); IN BOOL flipV, IN Vec2 uvOffset);
public: public: