working on tilemap
This commit is contained in:
parent
9ddfa06bd9
commit
fbb0574b81
23
imgui.ini
23
imgui.ini
@ -14,8 +14,8 @@ Size=1280,701
|
||||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=938,19
|
||||
Size=342,701
|
||||
Pos=900,19
|
||||
Size=380,701
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
@ -27,23 +27,24 @@ DockId=0x00000003,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=344,19
|
||||
Size=592,390
|
||||
Size=554,390
|
||||
Collapsed=0
|
||||
DockId=0x00000007,0
|
||||
|
||||
[Window][##MainMenuBar]
|
||||
Size=1920,19
|
||||
Pos=0,0
|
||||
Size=1280,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=344,411
|
||||
Size=592,309
|
||||
Size=554,309
|
||||
Collapsed=0
|
||||
DockId=0x00000008,3
|
||||
|
||||
[Window][Console]
|
||||
Pos=344,411
|
||||
Size=592,309
|
||||
Size=554,309
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
|
||||
@ -55,7 +56,7 @@ DockId=0x00000007,1
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=344,411
|
||||
Size=592,309
|
||||
Size=554,309
|
||||
Collapsed=0
|
||||
DockId=0x00000008,2
|
||||
|
||||
@ -79,7 +80,7 @@ DockId=0x00000008,1
|
||||
|
||||
[Window][Color Correction]
|
||||
Pos=344,411
|
||||
Size=592,309
|
||||
Size=554,309
|
||||
Collapsed=0
|
||||
DockId=0x00000008,1
|
||||
|
||||
@ -91,12 +92,12 @@ DockId=0x00000004,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
|
||||
DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1576,1158 Split=X
|
||||
DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1538,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1576,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1194,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,847 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,309 Selected=0x9B5D3198
|
||||
DockNode ID=0x00000006 Parent=0x11111111 SizeRef=342,1158 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000006 Parent=0x11111111 SizeRef=380,1158 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[RUN] Executed app.exe successfully.
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[ERROR] Runtime crash
|
||||
Command 'src\build\app.exe' returned non-zero exit status 1.
|
||||
|
52
src/assets/scenes/TilemapTest.cene
Normal file
52
src/assets/scenes/TilemapTest.cene
Normal file
@ -0,0 +1,52 @@
|
||||
engine_version: 0.1.0
|
||||
scene_name: New Text Document
|
||||
scene_hash: ab18a816340bea7fd8b460cde813cb5277bc2a67ca413862f648cf030c93a85f
|
||||
format_version: 1
|
||||
objects:
|
||||
- name: TilemapTest
|
||||
uid: 4afa4d0c474b4fb9b9b80eb1bb31195a
|
||||
id: 0
|
||||
position: [0, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- Type: TilemapComponent
|
||||
TextureUAID: 1
|
||||
TexelWidth: 1
|
||||
TexelHeight: 1
|
||||
TileSize:
|
||||
x: 32
|
||||
y: 32
|
||||
Tiles:
|
||||
- [0, 0, 1]
|
||||
- [1, 0, 2]
|
||||
- [2, 0, 3]
|
||||
- [0, 1, 4]
|
||||
- [1, 1, 5]
|
||||
- [2, 1, 6]
|
||||
- [0, 2, 7]
|
||||
- [1, 2, 8]
|
||||
- [2, 2, 9]
|
||||
- [3, 3, 10]
|
||||
- [4, 3, 11]
|
||||
- [5, 3, 12]
|
||||
- [6, 3, 13]
|
||||
- [6, 2, 14]
|
||||
- [6, 1, 15]
|
||||
- [6, 0, 16]
|
||||
children: []
|
||||
color_correction:
|
||||
brightness: 1
|
||||
saturation: 1
|
||||
gamma: 1
|
||||
bloom: true
|
||||
intensity: 1.2
|
||||
threshold: 1
|
||||
Assets:
|
||||
- uaid: 1
|
||||
path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png
|
||||
filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png
|
||||
filetype: png
|
||||
type: 0
|
||||
size: [1024, 1024]
|
@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include "../core/utils/ExceptionHandler.h"
|
||||
#include "../core/utils/AssetManager.h"
|
||||
#include "../core/utils/Logging.h"
|
||||
|
||||
|
||||
class Object;
|
||||
|
@ -1,262 +1,126 @@
|
||||
#include "TilemapComponent.h"
|
||||
#include "../core/utils/Logging.h"
|
||||
#include "../core/utils/FileDialog.h"
|
||||
#include "../core/utils/utils.h"
|
||||
#include <stb_image.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
static int g_selectedTileIndex = 0;
|
||||
#include "../Renderer.h"
|
||||
|
||||
|
||||
// Constructor: initialize with a default grid (optional)
|
||||
TilemapComponent::TilemapComponent(Object *owner)
|
||||
TilemapComponent::TilemapComponent(Object* owner)
|
||||
: Component(owner)
|
||||
{
|
||||
// For example, create an empty 10x10 tilemap
|
||||
SetGridSize(glm::ivec2(10, 10));
|
||||
// Optionally set a default tile size
|
||||
m_TileSize = glm::ivec2(32, 32);
|
||||
renderType = RenderType::Unlit;
|
||||
}
|
||||
|
||||
// Set grid dimensions and resize tile array; initially all -1 (empty)
|
||||
void TilemapComponent::SetGridSize(const glm::ivec2 &size)
|
||||
uint64_t TilemapComponent::PackCoord(int x, int y)
|
||||
{
|
||||
m_GridSize = size;
|
||||
m_Tiles.assign(size.x * size.y, -1);
|
||||
return (static_cast<uint64_t>(static_cast<uint32_t>(x)) << 32) |
|
||||
static_cast<uint32_t>(y);
|
||||
}
|
||||
|
||||
// Set individual tile at (x, y)
|
||||
void TilemapComponent::SetTile(int x, int y, int tileIndex)
|
||||
void TilemapComponent::UnpackCoord(uint64_t key, int& x, int& y)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= m_GridSize.x || y >= m_GridSize.y)
|
||||
x = static_cast<int32_t>(key >> 32);
|
||||
y = static_cast<int32_t>(key & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void TilemapComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight)
|
||||
{
|
||||
textureUAID = uaid;
|
||||
|
||||
const auto* asset = AssetManager::GetAssetByID(uaid);
|
||||
if (!asset || !asset->loaded)
|
||||
{
|
||||
Logger::LogError("TilemapComponent: Asset not found or not loaded (UAID: %llu)", uaid);
|
||||
return;
|
||||
m_Tiles[y * m_GridSize.x + x] = tileIndex;
|
||||
}
|
||||
|
||||
texture = std::make_shared<Texture>(uaid);
|
||||
|
||||
atlas.texture = texture;
|
||||
atlas.SetTexelSize(texelWidth, texelHeight);
|
||||
|
||||
int texWidth = static_cast<int>(asset->size.x);
|
||||
int texHeight = static_cast<int>(asset->size.y);
|
||||
|
||||
atlasColumns = texWidth / texelWidth;
|
||||
atlasRows = texHeight / texelHeight;
|
||||
}
|
||||
|
||||
void TilemapComponent::SetTile(int x, int y, int index)
|
||||
{
|
||||
uint64_t key = PackCoord(x, y);
|
||||
if (index >= 0)
|
||||
tiles[key] = index;
|
||||
else
|
||||
tiles.erase(key);
|
||||
}
|
||||
|
||||
int TilemapComponent::GetTile(int x, int y) const
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= m_GridSize.x || y >= m_GridSize.y)
|
||||
return -1;
|
||||
return m_Tiles[y * m_GridSize.x + x];
|
||||
}
|
||||
|
||||
void TilemapComponent::SetTileSize(const glm::ivec2 &size)
|
||||
{
|
||||
m_TileSize = size;
|
||||
}
|
||||
|
||||
// Set atlas (tileset) settings; also update dimensions
|
||||
void TilemapComponent::SetAtlas(const std::string &path, int atlasTileWidth, int atlasTileHeight)
|
||||
{
|
||||
m_AtlasPath = path;
|
||||
m_AtlasTileWidth = atlasTileWidth;
|
||||
m_AtlasTileHeight = atlasTileHeight;
|
||||
UpdateAtlasDimensions();
|
||||
}
|
||||
|
||||
// Helper: load atlas image info using stbi_info to compute columns and rows
|
||||
void TilemapComponent::UpdateAtlasDimensions()
|
||||
{
|
||||
if (m_AtlasPath.empty())
|
||||
return;
|
||||
int texW, texH, comp;
|
||||
if (stbi_info(m_AtlasPath.c_str(), &texW, &texH, &comp))
|
||||
{
|
||||
m_AtlasCols = texW / m_AtlasTileWidth;
|
||||
m_AtlasRows = texH / m_AtlasTileHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AtlasCols = m_AtlasRows = 0;
|
||||
Logger::LogError("Failed to get atlas info: %s", m_AtlasPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TilemapComponent::IsTileFullyTransparent(int col, int row, int texW, int texH, unsigned char* imageData)
|
||||
{
|
||||
int x0 = col * m_AtlasTileWidth;
|
||||
int y0 = row * m_AtlasTileHeight;
|
||||
|
||||
for (int y = 0; y < m_AtlasTileHeight; ++y)
|
||||
{
|
||||
for (int x = 0; x < m_AtlasTileWidth; ++x)
|
||||
{
|
||||
int px = x0 + x;
|
||||
int py = y0 + y;
|
||||
int idx = (py * texW + px) * 4;
|
||||
if (imageData[idx + 3] > 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
uint64_t key = PackCoord(x, y);
|
||||
auto it = tiles.find(key);
|
||||
return (it != tiles.end()) ? it->second : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Serialization: store grid size, tile size, tile data, and atlas settings.
|
||||
void TilemapComponent::Save(YAML::Emitter &out) const
|
||||
// Accessors
|
||||
uint64_t TilemapComponent::GetTextureUAID() const { return textureUAID; }
|
||||
std::shared_ptr<Texture> TilemapComponent::GetTexture() const { return texture; }
|
||||
const TextureAtlas& TilemapComponent::GetAtlas() const { return atlas; }
|
||||
const core::types::Vec2& TilemapComponent::GetTileSize() const { return tileSize; }
|
||||
void TilemapComponent::SetTileSize(const core::types::Vec2& size) { tileSize = size; }
|
||||
int TilemapComponent::GetAtlasColumns() const { return atlasColumns; }
|
||||
int TilemapComponent::GetAtlasRows() const { return atlasRows; }
|
||||
const std::unordered_map<uint64_t, int>& TilemapComponent::GetTileData() const { return tiles; }
|
||||
|
||||
// Save to YAML
|
||||
void TilemapComponent::Save(YAML::Emitter& out) const
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "type" << YAML::Value << "TilemapComponent";
|
||||
out << YAML::Key << "gridSize" << YAML::Value << std::vector<int>{m_GridSize.x, m_GridSize.y};
|
||||
out << YAML::Key << "tileSize" << YAML::Value << std::vector<int>{m_TileSize.x, m_TileSize.y};
|
||||
out << YAML::Key << "tiles" << YAML::Value << m_Tiles;
|
||||
out << YAML::Key << "atlasPath" << YAML::Value << m_AtlasPath;
|
||||
out << YAML::Key << "atlasTileSize" << YAML::Value << std::vector<int>{m_AtlasTileWidth, m_AtlasTileHeight};
|
||||
out << YAML::Key << "Type" << YAML::Value << GetName();
|
||||
out << YAML::Key << "TextureUAID" << YAML::Value << textureUAID;
|
||||
out << YAML::Key << "TexelWidth" << YAML::Value << atlas.GetTexelSize().x;
|
||||
out << YAML::Key << "TexelHeight" << YAML::Value << atlas.GetTexelSize().y;
|
||||
|
||||
out << YAML::Key << "TileSize" << YAML::Value << YAML::BeginMap;
|
||||
out << YAML::Key << "x" << YAML::Value << tileSize.x;
|
||||
out << YAML::Key << "y" << YAML::Value << tileSize.y;
|
||||
out << YAML::EndMap;
|
||||
|
||||
out << YAML::Key << "Tiles" << YAML::Value << YAML::BeginSeq;
|
||||
for (const auto& [key, index] : tiles)
|
||||
{
|
||||
int x, y;
|
||||
UnpackCoord(key, x, y);
|
||||
out << YAML::Flow << YAML::BeginSeq << x << y << index << YAML::EndSeq;
|
||||
}
|
||||
out << YAML::EndSeq;
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
// Deserialization: load saved data
|
||||
void TilemapComponent::Load(const YAML::Node &node)
|
||||
|
||||
|
||||
void TilemapComponent::Load(const YAML::Node& node)
|
||||
{
|
||||
if (node["gridSize"])
|
||||
textureUAID = node["TextureUAID"].as<uint64_t>();
|
||||
int texelWidth = node["TexelWidth"].as<int>();
|
||||
int texelHeight = node["TexelHeight"].as<int>();
|
||||
SetTextureAtlas(textureUAID, texelWidth, texelHeight);
|
||||
|
||||
if (node["TileSize"])
|
||||
{
|
||||
auto vec = node["gridSize"].as<std::vector<int>>();
|
||||
if (vec.size() == 2)
|
||||
m_GridSize = glm::ivec2(vec[0], vec[1]);
|
||||
tileSize.x = node["TileSize"]["x"].as<float>();
|
||||
tileSize.y = node["TileSize"]["y"].as<float>();
|
||||
}
|
||||
if (node["tileSize"])
|
||||
|
||||
tiles.clear();
|
||||
if (node["Tiles"])
|
||||
{
|
||||
auto vec = node["tileSize"].as<std::vector<int>>();
|
||||
if (vec.size() == 2)
|
||||
m_TileSize = glm::ivec2(vec[0], vec[1]);
|
||||
}
|
||||
if (node["tiles"])
|
||||
m_Tiles = node["tiles"].as<std::vector<int>>();
|
||||
if (node["atlasPath"])
|
||||
m_AtlasPath = node["atlasPath"].as<std::string>();
|
||||
if (node["atlasTileSize"])
|
||||
{
|
||||
auto vec = node["atlasTileSize"].as<std::vector<int>>();
|
||||
if (vec.size() == 2)
|
||||
for (const auto& tile : node["Tiles"])
|
||||
{
|
||||
m_AtlasTileWidth = vec[0];
|
||||
m_AtlasTileHeight = vec[1];
|
||||
if (!tile.IsSequence() || tile.size() != 3) continue;
|
||||
int x = tile[0].as<int>();
|
||||
int y = tile[1].as<int>();
|
||||
int index = tile[2].as<int>();
|
||||
SetTile(x, y, index);
|
||||
}
|
||||
}
|
||||
// Update atlas dimensions after loading settings
|
||||
UpdateAtlasDimensions();
|
||||
}
|
||||
|
||||
void TilemapComponent::DrawEditorUI()
|
||||
{
|
||||
ImGui::Begin("Tilemap Editor");
|
||||
|
||||
if (ImGui::BeginTabBar("TilemapEditorTabs"))
|
||||
{
|
||||
// --- Atlas Settings ---
|
||||
if (ImGui::BeginTabItem("Atlas Settings"))
|
||||
{
|
||||
ImGui::Text("Current Atlas: %s", m_AtlasPath.empty() ? "None" : m_AtlasPath.c_str());
|
||||
if (ImGui::Button("Import Atlas"))
|
||||
{
|
||||
std::string path = OpenFileDialog(FileDialogType::Images);
|
||||
if (!path.empty())
|
||||
{
|
||||
m_AtlasPath = path;
|
||||
UpdateAtlasDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
int atlasW = m_AtlasTileWidth, atlasH = m_AtlasTileHeight;
|
||||
if (ImGui::InputInt("Atlas Tile Width", &atlasW))
|
||||
{
|
||||
m_AtlasTileWidth = atlasW;
|
||||
UpdateAtlasDimensions();
|
||||
}
|
||||
if (ImGui::InputInt("Atlas Tile Height", &atlasH))
|
||||
{
|
||||
m_AtlasTileHeight = atlasH;
|
||||
UpdateAtlasDimensions();
|
||||
}
|
||||
|
||||
ImGui::Text("Atlas Grid: %d x %d", m_AtlasCols, m_AtlasRows);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// --- Map Settings ---
|
||||
if (ImGui::BeginTabItem("Map Settings"))
|
||||
{
|
||||
ImGui::Text("Map Size: %d x %d", m_GridSize.x, m_GridSize.y);
|
||||
ImGui::Text("Tile Size: %d x %d", m_TileSize.x, m_TileSize.y);
|
||||
ImGui::Text("Tile Count: %zu", m_Tiles.size());
|
||||
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// --- Tile Tools ---
|
||||
if (ImGui::BeginTabItem("Tiles"))
|
||||
{
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (m_AtlasPath.empty())
|
||||
{
|
||||
ImGui::Text("No atlas loaded.");
|
||||
}
|
||||
else
|
||||
{
|
||||
int texW, texH, comp;
|
||||
unsigned char* imageData = stbi_load(m_AtlasPath.c_str(), &texW, &texH, &comp, 4);
|
||||
if (imageData)
|
||||
{
|
||||
float uvTileW = float(m_AtlasTileWidth) / float(texW);
|
||||
float uvTileH = float(m_AtlasTileHeight) / float(texH);
|
||||
GLuint textureID = LoadTextureIfNeeded(m_AtlasPath);
|
||||
|
||||
const float tileDisplaySize = 48;
|
||||
ImGui::BeginChild("TilesetView");
|
||||
for (int row = 0; row < m_AtlasRows; ++row)
|
||||
{
|
||||
for (int col = 0; col < m_AtlasCols; ++col)
|
||||
{
|
||||
int tileIndex = row * m_AtlasCols + col;
|
||||
float uvX = float(col) * uvTileW;
|
||||
float uvY = float(row) * uvTileH;
|
||||
ImVec2 uv0(uvX, uvY);
|
||||
ImVec2 uv1(uvX + uvTileW, uvY + uvTileH);
|
||||
|
||||
char id[32];
|
||||
sprintf(id, "##tile_%d", tileIndex);
|
||||
|
||||
bool isEmpty = IsTileFullyTransparent(col, row, texW, texH, imageData);
|
||||
ImVec4 tint = isEmpty ? ImVec4(0.3f, 0.3f, 0.3f, 0.5f) : ImVec4(1, 1, 1, 1);
|
||||
if (ImGui::ImageButton(id, (ImTextureID)(uintptr_t)textureID, ImVec2(tileDisplaySize, tileDisplaySize), uv0, uv1))
|
||||
{
|
||||
g_selectedTileIndex = tileIndex;
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Tile %d", tileIndex);
|
||||
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::NewLine();
|
||||
}
|
||||
stbi_image_free(imageData);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Failed to load image.");
|
||||
}
|
||||
|
||||
ImGui::Text("Selected Tile: %d", g_selectedTileIndex);
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,58 +1,47 @@
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <imgui.h>
|
||||
#include "../core/utils/TextureAtlas.h"
|
||||
#include "../core/types/Vec2.h"
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
class TilemapComponent : public Component
|
||||
{
|
||||
public:
|
||||
TilemapComponent(Object* owner);
|
||||
|
||||
// Editor UI for tilemap
|
||||
void DrawEditorUI();
|
||||
|
||||
// Set up grid and tile dimensions
|
||||
void SetGridSize(const glm::ivec2& size);
|
||||
void SetTileSize(const glm::ivec2& size);
|
||||
void SetTile(int x, int y, int tileIndex);
|
||||
void SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight);
|
||||
void SetTile(int x, int y, int index);
|
||||
int GetTile(int x, int y) const;
|
||||
|
||||
// Getters
|
||||
const glm::ivec2& GetGridSize() const { return m_GridSize; }
|
||||
const glm::ivec2& GetTileSize() const { return m_TileSize; }
|
||||
const std::vector<int>& GetTiles() const { return m_Tiles; }
|
||||
const std::string& GetAtlasPath() const { return m_AtlasPath; }
|
||||
|
||||
int GetAtlasTileWidth() const { return m_AtlasTileWidth; }
|
||||
int GetAtlasTileHeight() const { return m_AtlasTileHeight; }
|
||||
int GetAtlasCols() const { return m_AtlasCols; }
|
||||
int GetAtlasRows() const { return m_AtlasRows; }
|
||||
|
||||
// Atlas setup: import an atlas image and configure its tile dimensions.
|
||||
void SetAtlas(const std::string& path, int atlasTileWidth, int atlasTileHeight);
|
||||
|
||||
// Serialization
|
||||
// Overrides
|
||||
std::string GetName() const override { return "TilemapComponent"; }
|
||||
void Save(YAML::Emitter& out) const override;
|
||||
void Load(const YAML::Node& node) override;
|
||||
std::string GetName() const override { return "TilemapComponent"; }
|
||||
|
||||
// Accessors
|
||||
uint64_t GetTextureUAID() const;
|
||||
std::shared_ptr<Texture> GetTexture() const;
|
||||
const TextureAtlas& GetAtlas() const;
|
||||
const core::types::Vec2& GetTileSize() const;
|
||||
void SetTileSize(const core::types::Vec2& size);
|
||||
int GetAtlasColumns() const;
|
||||
int GetAtlasRows() const;
|
||||
const std::unordered_map<uint64_t, int>& GetTileData() const;
|
||||
|
||||
static uint64_t PackCoord(int x, int y);
|
||||
static void UnpackCoord(uint64_t key, int& x, int& y);
|
||||
|
||||
private:
|
||||
// Grid and tile data
|
||||
glm::ivec2 m_GridSize {0, 0};
|
||||
glm::ivec2 m_TileSize {32, 32};
|
||||
std::vector<int> m_Tiles;
|
||||
uint64_t textureUAID = 0;
|
||||
std::shared_ptr<Texture> texture;
|
||||
TextureAtlas atlas;
|
||||
RenderType renderType;
|
||||
|
||||
// Atlas (tileset) settings
|
||||
std::string m_AtlasPath;
|
||||
int m_AtlasTileWidth = 32;
|
||||
int m_AtlasTileHeight = 32;
|
||||
int m_AtlasCols = 0;
|
||||
int m_AtlasRows = 0;
|
||||
|
||||
void UpdateAtlasDimensions();
|
||||
bool IsTileFullyTransparent(int col, int row, int texW, int texH, unsigned char* imageData);
|
||||
core::types::Vec2 tileSize = {32, 32};
|
||||
int atlasColumns = 0;
|
||||
int atlasRows = 0;
|
||||
|
||||
std::unordered_map<uint64_t, int> tiles;
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "utils/GameObjectsList.h"
|
||||
#include "core/utils/Profiler.h"
|
||||
#include "core/utils/utils.h"
|
||||
#include "core/utils/LoadingWindow.h"
|
||||
|
||||
#include "editor/windows/AssetBrowser.h"
|
||||
#include "editor/windows/Inspector.h"
|
||||
@ -513,12 +514,15 @@ void Engine::Init()
|
||||
|
||||
Logger::LogVerbose("Resverving Objects");
|
||||
|
||||
m_toDraw.reserve(1024);
|
||||
m_scriptUpdates.reserve(10);
|
||||
m_collectStack.reserve(1024);
|
||||
m_physicsUpdates.reserve(1024);
|
||||
m_particleUpdates.reserve(100);
|
||||
m_animationsUpdates.reserve(100);
|
||||
|
||||
// These values were AI Generated.
|
||||
|
||||
m_toDraw.reserve(2048); // ~2K sprites per frame (including UI, particles, objects)
|
||||
m_scriptUpdates.reserve(256); // ~256 active script components per frame
|
||||
m_collectStack.reserve(2048); // Used for internal temp memory, 512 is safe unless deep recursion
|
||||
m_physicsUpdates.reserve(512); // 256-512 physics bodies/entities with Box2D
|
||||
m_particleUpdates.reserve(24); // ~1K particle systems active is fair in effects-heavy scenes
|
||||
m_animationsUpdates.reserve(512); // ~500 animated objects (characters, FX, etc.)
|
||||
|
||||
Logger::LogInfo("Initialized Engine");
|
||||
}
|
||||
@ -572,6 +576,7 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom
|
||||
if (auto animator = obj->GetComponent<AnimationComponent>())
|
||||
m_animationsUpdates.push_back(animator.get());
|
||||
|
||||
|
||||
if (playing)
|
||||
{
|
||||
if (auto script = obj->GetComponent<ScriptComponent>())
|
||||
@ -914,6 +919,13 @@ void Engine::Run()
|
||||
profiler.EndSection();
|
||||
}
|
||||
|
||||
if (auto tilemap = obj->GetComponent<TilemapComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Tilemap: " + obj->GetName());
|
||||
Renderer::DrawTilemap(tilemap.get(), worldPos, cameraZoom, cameraPos);
|
||||
profiler.EndSection();
|
||||
}
|
||||
|
||||
if (auto animator = obj->GetComponent<AnimationComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Animator: " + obj->GetName());
|
||||
@ -1159,17 +1171,24 @@ void Engine::LoadScene(const std::string &path)
|
||||
Logger::LogDebug("[LoadScene] Reading Scene File.");
|
||||
YAML::Node root = YAML::LoadFile(path);
|
||||
|
||||
Logger::LogDebug("[LoadScene] Verifying Scene");
|
||||
LoadingWindow loadingUI;
|
||||
loadingUI.Create("Loading Scene");
|
||||
|
||||
std::string currentStep = "Verifying Scene";
|
||||
std::string currentDetail = "";
|
||||
loadingUI.Update(currentStep, currentDetail, 0.0f);
|
||||
|
||||
if (!root["engine_version"] || !root["format_version"] || !root["scene_name"])
|
||||
{
|
||||
Logger::LogError("[LoadScene] Missing required metadata!");
|
||||
loadingUI.Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (root["engine_version"].as<std::string>() != "0.1.0")
|
||||
{
|
||||
Logger::LogError("[LoadScene] Version mismatch! Expected 0.1.0, got %s", root["engine_version"].as<std::string>().c_str());
|
||||
loadingUI.Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1180,26 +1199,47 @@ void Engine::LoadScene(const std::string &path)
|
||||
|
||||
if (root["Assets"])
|
||||
{
|
||||
currentStep = "Loading Assets";
|
||||
currentDetail = "Parsing asset data...";
|
||||
loadingUI.Update(currentStep, currentDetail, 0.05f);
|
||||
|
||||
Logger::LogVerbose("[LoadScene] Loading Assets");
|
||||
AssetManager::Load(root["Assets"]);
|
||||
}
|
||||
|
||||
Logger::LogDebug("[LoadScene] Reseting Scene.");
|
||||
currentStep = "Clearing Previous Scene";
|
||||
currentDetail = "Removing existing objects";
|
||||
loadingUI.Update(currentStep, currentDetail, 0.1f);
|
||||
|
||||
objects.clear();
|
||||
|
||||
Logger::LogDebug("[LoadScene] Recreating Objects");
|
||||
currentStep = "Creating Scene Objects";
|
||||
|
||||
const auto &objectArray = root["objects"];
|
||||
int objectIndex = 0;
|
||||
int totalObjects = static_cast<int>(objectArray.size());
|
||||
|
||||
for (const auto &node : objectArray)
|
||||
{
|
||||
auto obj = std::make_shared<Object>("[DefaultObject]");
|
||||
std::string objName = node["name"] ? node["name"].as<std::string>() : ("Unnamed_" + std::to_string(objectIndex));
|
||||
currentDetail = "Loading: " + objName;
|
||||
float progress = 0.1f + (0.75f * (objectIndex / static_cast<float>(std::max(1, totalObjects))));
|
||||
loadingUI.Update(currentStep, currentDetail, progress);
|
||||
|
||||
auto obj = std::make_shared<Object>(objName);
|
||||
obj->Load(node);
|
||||
objects.push_back(obj);
|
||||
objectIndex++;
|
||||
}
|
||||
|
||||
if (root["color_correction"])
|
||||
{
|
||||
Logger::LogVerbose("[LoadScene] Loading Color Correction Attributes");
|
||||
currentStep = "Color Correction";
|
||||
currentDetail = "Applying settings...";
|
||||
loadingUI.Update(currentStep, currentDetail, 0.9f);
|
||||
|
||||
ColorCorrection *cc = Renderer::GetColorCorrection();
|
||||
const auto &data = root["color_correction"];
|
||||
@ -1220,7 +1260,13 @@ void Engine::LoadScene(const std::string &path)
|
||||
}
|
||||
}
|
||||
|
||||
currentStep = "Done";
|
||||
currentDetail = "Finalizing load...";
|
||||
loadingUI.Update(currentStep, currentDetail, 1.0f);
|
||||
|
||||
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
||||
|
||||
loadingUI.Destroy();
|
||||
}
|
||||
|
||||
void Engine::SaveState()
|
||||
|
@ -11,6 +11,7 @@ class ScriptComponent;
|
||||
class PhysicsComponent;
|
||||
class ParticleComponent;
|
||||
class AnimationComponent;
|
||||
class TilemapComponent;
|
||||
|
||||
class Engine
|
||||
{
|
||||
@ -38,6 +39,7 @@ private:
|
||||
std::vector<Object *> m_toDraw;
|
||||
std::vector<ScriptComponent *> m_scriptUpdates;
|
||||
std::vector<AnimationComponent *> m_animationsUpdates;
|
||||
|
||||
int m_OnUpdateCalls;
|
||||
|
||||
std::vector<std::shared_ptr<Object>> m_collectStack;
|
||||
|
@ -161,6 +161,7 @@ void Object::Load(const YAML::Node &node)
|
||||
else if (type == "AnimationComponent") AddComponent<AnimationComponent>()->Load(compNode);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Components/SpriteComponent.h"
|
||||
#include "Components/TilemapComponent.h"
|
||||
|
||||
#include "utils/Shader.h"
|
||||
#include "core/utils/Logging.h"
|
||||
#include "core/utils/EngineConfig.h"
|
||||
@ -444,6 +446,10 @@ void Renderer::End()
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Renderer::ClearLights()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::ClearLights");
|
||||
@ -462,60 +468,24 @@ void Renderer::AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, floa
|
||||
s_LightsCount++;
|
||||
}
|
||||
|
||||
void Renderer::DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos, float zoom, const glm::vec2 &cameraPos)
|
||||
void Renderer::DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &pos, float zoom, const glm::vec2 &cameraPos)
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::DrawTilemap");
|
||||
|
||||
if (!tilemap || tilemap->GetAtlasPath().empty())
|
||||
if (!tilemap || !tilemap->GetTexture())
|
||||
return;
|
||||
|
||||
glm::ivec2 grid = tilemap->GetGridSize();
|
||||
glm::ivec2 tileSize = tilemap->GetTileSize();
|
||||
int cols = tilemap->GetAtlasCols();
|
||||
int rows = tilemap->GetAtlasRows();
|
||||
const TextureAtlas &atlas = tilemap->GetAtlas();
|
||||
const core::types::Vec2 &tileSize = tilemap->GetTileSize();
|
||||
|
||||
const std::string &atlasPath = tilemap->GetAtlasPath();
|
||||
GLuint atlasTex = LoadTextureIfNeeded(atlasPath);
|
||||
if (atlasTex == 0)
|
||||
return;
|
||||
|
||||
tilemapShader.Use();
|
||||
tilemapShader.SetVec2("uScreen", glm::vec2(width, height));
|
||||
tilemapShader.SetInt("uTex", 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, atlasTex);
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
|
||||
for (int y = 0; y < grid.y; ++y)
|
||||
for (const auto &[key, tileIndex] : tilemap->GetTileData())
|
||||
{
|
||||
for (int x = 0; x < grid.x; ++x)
|
||||
{
|
||||
int index = tilemap->GetTile(x, y);
|
||||
if (index < 0 || index >= cols * rows)
|
||||
continue;
|
||||
int x, y;
|
||||
TilemapComponent::UnpackCoord(key, x, y);
|
||||
|
||||
int atlasX = index % cols;
|
||||
int atlasY = index / cols;
|
||||
glm::vec2 tileWorldPos = glm::vec2(x * tileSize.x, y * tileSize.y);
|
||||
glm::vec2 screenPos = (tileWorldPos - cameraPos) * zoom + glm::vec2(width, height) * 0.5f;
|
||||
|
||||
glm::vec2 uvMin = glm::vec2(atlasX, atlasY) / glm::vec2(cols, rows);
|
||||
glm::vec2 uvMax = (glm::vec2(atlasX + 1, atlasY + 1)) / glm::vec2(cols, rows);
|
||||
|
||||
tilemapShader.SetVec2("uUVMin", uvMin);
|
||||
tilemapShader.SetVec2("uUVMax", uvMax);
|
||||
|
||||
glm::vec2 tileWorld = worldPos + glm::vec2(x * tileSize.x, y * tileSize.y);
|
||||
glm::vec2 screenPos = (tileWorld - cameraPos) * zoom + glm::vec2(width, height) * 0.5f;
|
||||
|
||||
tilemapShader.SetVec2("uPos", screenPos);
|
||||
tilemapShader.SetVec2("uSize", glm::vec2(tileSize) * zoom);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
s_DrawCalls++;
|
||||
}
|
||||
DrawTextureAtlas(&atlas, tileIndex, screenPos, 0.0f, zoom);
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::DrawQuad(const core::types::Vec2 &pos, const core::types::Vec2 &size, float rotation, const core::types::Color &color)
|
||||
@ -615,7 +585,7 @@ void Renderer::DrawTextureAtlas(const TextureAtlas *atlas, int index, const core
|
||||
drawEntry.sprite = entry;
|
||||
drawEntry.shader = &unlitShader;
|
||||
drawEntry.useLighting = false;
|
||||
drawEntry.usesUV = true; // <- Important!
|
||||
drawEntry.usesUV = true;
|
||||
|
||||
sortedDrawList.push_back(drawEntry);
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ public:
|
||||
static void End();
|
||||
|
||||
static void DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float zoom, glm::vec2 &CameraPos);
|
||||
static void DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos, float zoom, const glm::vec2 &cameraPos);
|
||||
static void DrawTilemap(TilemapComponent* tilemap, const glm::vec2& pos, float zoom, const glm::vec2& cameraPos);
|
||||
|
||||
|
||||
static void AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, float intensity, float radius);
|
||||
static void ClearLights();
|
||||
|
101
src/src/core/utils/LoadingWindow.cpp
Normal file
101
src/src/core/utils/LoadingWindow.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#include "LoadingWindow.h"
|
||||
#include <algorithm>
|
||||
|
||||
static const wchar_t* kWindowClass = L"LoadingWndClass";
|
||||
static LoadingWindow* g_instance = nullptr;
|
||||
|
||||
void LoadingWindow::Create(const std::string& title)
|
||||
{
|
||||
g_instance = this;
|
||||
windowTitle = std::wstring(title.begin(), title.end());
|
||||
|
||||
WNDCLASS wc = {};
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = GetModuleHandle(nullptr);
|
||||
wc.lpszClassName = kWindowClass;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
RegisterClass(&wc);
|
||||
|
||||
hwnd = CreateWindowEx(
|
||||
0, kWindowClass, windowTitle.c_str(),
|
||||
WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 500, 200,
|
||||
nullptr, nullptr, GetModuleHandle(nullptr), nullptr
|
||||
);
|
||||
|
||||
ShowWindow(hwnd, SW_SHOWNORMAL);
|
||||
UpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
void LoadingWindow::Update(const std::string& step, const std::string& detail, float progress)
|
||||
{
|
||||
currentStep = step;
|
||||
currentDetail = detail;
|
||||
currentProgress = std::clamp(progress, 0.0f, 1.0f);
|
||||
|
||||
InvalidateRect(hwnd, nullptr, TRUE);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadingWindow::Destroy()
|
||||
{
|
||||
if (hwnd)
|
||||
{
|
||||
DestroyWindow(hwnd);
|
||||
hwnd = nullptr;
|
||||
}
|
||||
UnregisterClass(kWindowClass, GetModuleHandle(nullptr));
|
||||
}
|
||||
|
||||
LRESULT CALLBACK LoadingWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (msg == WM_PAINT && g_instance)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(hWnd, &r);
|
||||
|
||||
std::wstring step = std::wstring(g_instance->currentStep.begin(), g_instance->currentStep.end());
|
||||
std::wstring detail = std::wstring(g_instance->currentDetail.begin(), g_instance->currentDetail.end());
|
||||
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
||||
|
||||
RECT textRect = r;
|
||||
textRect.top += 10;
|
||||
textRect.left += 20;
|
||||
|
||||
DrawTextW(hdc, step.c_str(), -1, &textRect, DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
textRect.top += 30;
|
||||
DrawTextW(hdc, detail.c_str(), -1, &textRect, DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
|
||||
// Progress bar background
|
||||
RECT progressRect = { r.left + 20, r.bottom - 50, r.right - 20, r.bottom - 30 };
|
||||
HBRUSH bg = CreateSolidBrush(RGB(200, 200, 200));
|
||||
FillRect(hdc, &progressRect, bg);
|
||||
DeleteObject(bg);
|
||||
|
||||
// Progress bar fill
|
||||
int barWidth = static_cast<int>((progressRect.right - progressRect.left) * g_instance->currentProgress);
|
||||
RECT fillRect = { progressRect.left, progressRect.top, progressRect.left + barWidth, progressRect.bottom };
|
||||
HBRUSH fill = CreateSolidBrush(RGB(70, 140, 255));
|
||||
FillRect(hdc, &fillRect, fill);
|
||||
DeleteObject(fill);
|
||||
|
||||
EndPaint(hWnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
19
src/src/core/utils/LoadingWindow.h
Normal file
19
src/src/core/utils/LoadingWindow.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
class LoadingWindow {
|
||||
public:
|
||||
void Create(const std::string& title = "Loading...");
|
||||
void Update(const std::string& step, const std::string& detail, float progress); // NEW
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
HWND hwnd = nullptr;
|
||||
std::wstring windowTitle;
|
||||
std::string currentStep;
|
||||
std::string currentDetail;
|
||||
float currentProgress = 0.0f;
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
};
|
@ -11,7 +11,7 @@ enum class RenderType {
|
||||
class Texture {
|
||||
public:
|
||||
Texture(const std::string& path);
|
||||
Texture(uint64_t uaid); // New constructor using UAID
|
||||
Texture(uint64_t uaid);
|
||||
~Texture();
|
||||
|
||||
unsigned int GetID() const;
|
||||
|
@ -6,8 +6,8 @@
|
||||
struct TextureAtlas
|
||||
{
|
||||
std::shared_ptr<Texture> texture;
|
||||
int frameWidth = 1;
|
||||
int frameHeight = 1;
|
||||
int frameWidth = 32;
|
||||
int frameHeight = 32;
|
||||
|
||||
TextureAtlas() = default;
|
||||
|
||||
@ -23,6 +23,11 @@ struct TextureAtlas
|
||||
frameHeight = texelHeight;
|
||||
}
|
||||
|
||||
core::types::Vec2 GetTexelSize() const
|
||||
{
|
||||
return core::types::Vec2(frameWidth, frameHeight);
|
||||
}
|
||||
|
||||
core::types::Vec2 GetFrameUV(int index) const
|
||||
{
|
||||
if (!texture || frameWidth <= 0 || frameHeight <= 0)
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "../../components/ParticleComponent.h"
|
||||
#include "../../components/AnimationComponent.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Engine::DrawInspectorUI");
|
||||
@ -276,30 +279,28 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
|
||||
{
|
||||
std::string texFile = "(None)";
|
||||
if (const auto* asset = AssetManager::GetAssetByID(anim->GetTextureUAID()))
|
||||
if (const auto *asset = AssetManager::GetAssetByID(anim->GetTextureUAID()))
|
||||
texFile = GetFilenameFromPath(asset->path);
|
||||
|
||||
|
||||
ImGui::Text("%s", texFile.c_str());
|
||||
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE"))
|
||||
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE"))
|
||||
{
|
||||
uint64_t droppedUAID = *(const uint64_t*)payload->Data;
|
||||
uint64_t droppedUAID = *(const uint64_t *)payload->Data;
|
||||
anim->SetTextureAtlas(droppedUAID, frameWidth, frameHeight, frameDuration, startFrame, endFrame);
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
if (ImGui::SmallButton("Load##AnimTex"))
|
||||
{
|
||||
std::string path = OpenFileDialog(FileDialogType::Images);
|
||||
if (const auto *asset = AssetManager::GetAssetByPath(path))
|
||||
anim->SetTextureAtlas(asset->uaid, frameWidth, frameHeight, frameDuration, startFrame, endFrame);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ImGui::InputInt("Texel Width", &frameWidth);
|
||||
ImGui::InputInt("Texel Height", &frameHeight);
|
||||
@ -312,7 +313,6 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
if (const auto *asset = AssetManager::GetAssetByID(anim->GetTextureUAID()))
|
||||
anim->SetTextureAtlas(asset->uaid, frameWidth, frameHeight, frameDuration, startFrame, endFrame);
|
||||
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Playback");
|
||||
@ -424,16 +424,65 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
ImGui::SeparatorText("Tilemap Component");
|
||||
|
||||
ImGui::Text("Refer to Tilemap Editor Window");
|
||||
static int texelWidth = (int)tilemap->GetAtlas().GetTexelSize().x;
|
||||
static int texelHeight = (int)tilemap->GetAtlas().GetTexelSize().y;
|
||||
static core::types::Vec2 tileSize = tilemap->GetTileSize();
|
||||
|
||||
uint64_t uaid = tilemap->GetTextureUAID();
|
||||
const auto *asset = AssetManager::GetAssetByID(uaid);
|
||||
|
||||
ImGui::SeparatorText("Texture Atlas");
|
||||
|
||||
// --- Atlas file name or (None) ---
|
||||
std::string texFile = asset ? GetFilenameFromPath(asset->path) : "(None)";
|
||||
ImGui::Text("%s", texFile.c_str());
|
||||
|
||||
// --- Drag and Drop Target ---
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE"))
|
||||
{
|
||||
if (payload->DataSize == sizeof(uint64_t))
|
||||
{
|
||||
uint64_t newUaid = *(const uint64_t *)payload->Data;
|
||||
tilemap->SetTextureAtlas(newUaid, texelWidth, texelHeight);
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
// --- Load via file dialog ---
|
||||
if (ImGui::SmallButton("Load##TilemapTex"))
|
||||
{
|
||||
std::string path = OpenFileDialog(FileDialogType::Images);
|
||||
if (const auto *loaded = AssetManager::GetAssetByPath(path))
|
||||
tilemap->SetTextureAtlas(loaded->uaid, texelWidth, texelHeight);
|
||||
}
|
||||
|
||||
|
||||
// --- Tile Size ---
|
||||
if (ImGui::DragFloat2("Tile Size", &tileSize.x, 1.0f, 1.0f, 512.0f))
|
||||
tilemap->SetTileSize(tileSize);
|
||||
|
||||
// --- Apply changes to atlas ---
|
||||
if (ImGui::Button("Apply"))
|
||||
{
|
||||
if (const auto *texAsset = AssetManager::GetAssetByID(tilemap->GetTextureUAID()))
|
||||
tilemap->SetTextureAtlas(texAsset->uaid, texelWidth, texelHeight);
|
||||
}
|
||||
|
||||
// --- Atlas Preview ---
|
||||
if (tilemap->GetTexture() && tilemap->GetTexture())
|
||||
{
|
||||
float previewSize = ImGui::GetContentRegionAvail().x;
|
||||
ImGui::SeparatorText("Atlas Preview");
|
||||
ImGui::Image((ImTextureID)(uintptr_t)tilemap->GetTexture()->GetID(), ImVec2(previewSize, previewSize));
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Remove TilemapComponent"))
|
||||
selected->RemoveComponent<TilemapComponent>();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
if (auto tilemap = selected->GetComponent<TilemapComponent>())
|
||||
{
|
||||
tilemap->DrawEditorUI();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user