Refactoring lots of stuff.

This commit is contained in:
2025-05-29 17:45:48 -05:00
parent e6022898e5
commit 474b62f267
7 changed files with 282 additions and 165 deletions

View File

@@ -1,15 +1,79 @@
#include <JUI/Widgets/ImageRect.hpp>
#include <App/EditorApp.hpp>
#include <App/NewMapDialog.hpp>
#include <Data/Format.hpp>
void EditorApp::PopulateQuads()
JUI::Window* EditorApp::CreateAppInfoDialogWindow(JUI::Widget* parent)
{
//quads.reserve(tileset_width*tileset_height);
//for (int i = 0; i < tileset_width*tileset_height; i++) {
// Vector2i cell = IndexToCell(i, tileset_width);
// quads.push_back(Quad{cell.x*grid_pixel_width, cell.y*grid_pixel_height, grid_pixel_width, grid_pixel_height});
//}
// TODO: Implement JUI structure that makes blocks of text easy to impelement.
auto window = new JUI::Window(parent);
window->SetTitle("About Editor2D");
window->Size({350_px, 375_px});
window->MinSize({350, 375});
auto* layout = new JUI::VerticalListLayout(window->Content());
layout->Padding(0_px);
// TODO: Code like this ends up being a common construct in JUI programs: Make a TextList widget.
auto line_item = [&] (const std::string& text, int size = 20, const Color4& color = Colors::White) {
auto* content = new JUI::TextRect(layout);
content->Size({100_percent, JUI::UDim(size+5, 0)});
content->SetContent(text);
content->SetTextSize(size);
content->SetTextColor(color);
content->BGColor(Colors::Transparent);
content->AlignCenterHorizontally();
content->BorderWidth(0);
};
line_item("Redacted Tile Map Editor", 30);
line_item("Version 1.0", 14);
auto* box = new JUI::Rect(layout);
box->Size({100_percent, 200_px});
box->BGColor(Colors::Transparent);
box->BorderWidth(0);
auto* img = new JUI::ImageRect(box);
img->Content(new JGL::Texture("../icon.png"));
img->Size({200_px, 200_px});
img->BGColor(Colors::Transparent);
img->AnchorPoint({.5f, .5f});
img->Position({50_percent, 50_percent});
img->BorderWidth(0);
img->BGColor(Colors::Transparent);
line_item("Developed & Maintained by Josh O'Leary.", 16);
line_item("William R. Maxine H. Ash B.", 12);
line_item("(c) 2024 - 2025 Redacted Software", 16);
auto* btn_box = new JUI::Rect(layout);
btn_box->Size({100_percent, 40_px});
btn_box->BGColor(Colors::Transparent);
btn_box->BorderWidth(0);
auto* btn_layout = new JUI::HorizontalListLayout(btn_box);
btn_layout->Padding(8_px);
auto btn_item = [&] (const std::string& text) -> JUI::TextButton* {
JUI::TextButton* btn = new JUI::TextButton(btn_layout);
btn->SetContent(text);
btn->Size({32_percent, 100_percent});
btn->SetTextColor(Colors::Black);
btn->Center();
return btn;
};
auto* btn_a = btn_item("License");
auto* btn_b = btn_item("Wiki");
auto* btn_c = btn_item("Source");
window->Close();
return window;
}
Vector2i EditorApp::IndexToCell(int index, int width)
@@ -118,71 +182,29 @@ void EditorApp::SavePreferences()
preferences.recent_camera_state.scale = camera.scale.goal;
write_file_contents("preferences.json", json::deparse(preferences.Serialize()));
}
void EditorApp::LoadTestFile()
{
LoadLevel("level.json");
//if (!std::filesystem::exists("test_level/metadata.json"))
//loaded_level = Level(std::filesystem::path("level.json"));
//grid_rows = loaded_level->layers[0].rows;
//grid_cols = loaded_level->layers[0].cols;
//InitGrid();
//std::string level_metadata_text = read_file_contents("test_level/metadata.json");
/*std::ifstream input;
input.open("test.lvl", std::ios::binary | std::ios::in);
input.seekg(0, std::ios::end);
int data_length = input.tellg();
input.seekg(0, std::ios::beg);
char* buffer = new char[data_length];
input.read(buffer, data_length);
input.close();
auto* data = reinterpret_cast<int*>(buffer);
for (int x = 0; x < grid_rows; x++)
{
for (int y = 0; y < grid_cols; y++)
{
int index = (x*grid_cols + y);
grid[x][y] = data[index];
}
}
//memcpy(grid, data, grid_rows * grid_cols * sizeof(int));
delete[] buffer;*/
}
void EditorApp::SaveTestFile()
{
/*int* buffer = new int[grid_rows*grid_cols];
for (int x = 0; x < grid_rows; x++)
for (auto layer : loaded_level->layers)
{
for (int y = 0; y < grid_cols; y++)
{
int index = (x*grid_cols + y);
buffer[index] = grid[x][y];
}
layer->Save();
}
std::ofstream output;
output.open("test.lvl", std::ios::out | std::ios::binary);
output.write(reinterpret_cast<const char*>(buffer), grid_rows * grid_cols * sizeof(int));
output.close();
auto data = loaded_level->Serialize();
write_file_contents("level.json", json::deparse(data));
delete[] buffer;*/
}
void EditorApp::LoadLevel(const std::filesystem::path& level_meta_path)
{
loaded_level = new Level(level_meta_path);
@@ -194,16 +216,11 @@ void EditorApp::LoadLevel(const std::filesystem::path& level_meta_path)
for (auto layer : loaded_level->layers)
layer->Load();
PopulateQuads();
layer_view->UpdateComponents(loaded_level);
data_ready = true;
}
void EditorApp::LoadMisc()
{
LoadTestFile();
}
void EditorApp::SizeCellIndicatorToTilesetSize()
@@ -311,6 +328,8 @@ void EditorApp::CreateWidgets()
{
scene = new JUI::Scene();
app_info_dialog = CreateAppInfoDialogWindow(scene);
console = new JUI::CommandLine(scene);
console->Close();
BindConsoleCallbacks();
@@ -321,7 +340,7 @@ void EditorApp::CreateWidgets()
layer_view = new LayerView(scene);
layer_view->Open();
auto* topbar = new JUI::UtilityBar(scene);
topbar = new JUI::UtilityBar(scene);
auto* file = topbar->AddSubmenu("File");
file->SetFont(JGL::Fonts::Jupiteroid);
@@ -335,7 +354,7 @@ void EditorApp::CreateWidgets()
file->AddButton("Save", [this]{SaveTestFile();});
file->AddButton("Save As");
file->AddSeparator(2_px);
file->AddButton("About");
file->AddButton("About", [this]{app_info_dialog->Toggle(); });
file->AddButton("Preferences");
auto* edit = topbar->AddSubmenu("Edit");
@@ -405,7 +424,7 @@ bool EditorApp::Open()
// 1. Initialize elements of widgets that are independent of the level itself / the level depends on.
// 2. Initialize the level.
// 3. Initialize widgets that are dependent on the level itself.
LoadMisc();
LoadTestFile();
CreateWidgets();
@@ -536,6 +555,39 @@ void EditorApp::EraseTile(const Vector2i& cell)
SetTile(cell, -1);
}
bool EditorApp::IsMouseFocusedAnyActiveWidget()
{
if (bg_color_tool->IsVisible() && bg_color_tool->IsMouseInside())
return true;
if (layer_view->IsVisible() && layer_view->IsMouseInside())
return true;
if (nmd->IsVisible() && nmd->IsMouseInside())
return true;
if (console->IsVisible() && console->IsMouseInside())
return true;
if (console->IsVisible() && console->IsMouseInside())
return true;
if (tileset_viewer->IsVisible() && tileset_viewer->IsMouseInside())
return true;
if (topbar->IsVisible() && topbar->IsMouseInsideDescendants(true))
return true;
//for (auto child : scene->GetDescendants())
//if (child->GetParent()->IsVisible() && child->IsVisible() && child->IsMouseInside())
//return true;
return false;
}
void EditorApp::Update(float elapsed)
{
CameraUpdate(elapsed);
@@ -549,7 +601,16 @@ void EditorApp::Update(float elapsed)
scene->SetViewportSize(Vector2(vSize));
scene->Update(elapsed);
bool mouse_hovering_ui_element = scene->IsMouseInsideDescendants();
// TODO: Widget::IsMouseInsideVisibleDescendants(); I.e. ShouldMouseInputsPayAttention?
//bool mouse_hovering_ui_element = scene->IsMouseInsideDescendants();
bool mouse_hovering_ui_element = IsMouseFocusedAnyActiveWidget();
//for (auto child : scene->GetChildren())
// if (child->IsVisible() && child->IsMouseInsideDescendants(true))
// mouse_hovering_ui_element = true;
if (tileset_viewer->IsMouseInside()) {
if (tileset_viewer->Content()->IsMouseInside()) {
@@ -647,6 +708,47 @@ void EditorApp::DrawTiles()
}*/
}
void EditorApp::DrawLayer(const Layer* layer) const
{
for (int gx = 0; gx < layer->rows; gx++) {
for (int gy = 0; gy < layer->cols; gy++) {
auto quad_idx = layer->cells[gx][gy];
Vector2 pos(gx*layer->cell_width, gy*layer->cell_height);
//if ((gx+gy) % 2 == 0)
//J2D::FillRect(Colors::Purples::Fuchsia, pos, {16, 16});
if (quad_idx < 0)
continue;
auto quad = loaded_tileset->quads[quad_idx];
J2D::DrawPartialSprite(loaded_tilesheet, pos,
Vector2(quad.x, quad.y), Vector2(quad.w, quad.h));
}
}
}
void EditorApp::DrawLevel(const Level* level) const
{
// TODO: Draw Per-Level Background Texture.
// TODO: Draw Per-Layer Background Texture.
for (const auto* layer : level->layers)
{
DrawLayer(layer);
}
// TODO: Support a handful of presets to represent entity shape types.
for (auto entity : level->entities)
{
J2D::DrawPoint(entity->overlay_color, entity->x, entity->y, 1);
J2D::DrawString(Colors::White, std::format("{} - {}", entity->type, entity->name), entity->x, entity->y, 1.f, 12);
}
}
void EditorApp::Draw()
{
glClearColor(bg_color.RN(), bg_color.GN(), bg_color.BN(), 1);
@@ -693,3 +795,65 @@ void EditorApp::OnClosing()
SavePreferences();
SaveTestFile();
}
void EditorApp::OnRefresh(float elapsed)
{
Update(elapsed);
Draw();
SwapBuffers();
}
JUI::MouseButton EditorApp::ToJUIEnum(const MouseButton& btn)
{
if (btn == MouseButtons::Left) return JUI::MouseButton::Left;
if (btn == MouseButtons::Middle) return JUI::MouseButton::Middle;
if (btn == MouseButtons::Right) return JUI::MouseButton::Right;
// Default condition.
return JUI::MouseButton::Left;
}
void EditorApp::OnMouseButtonDown(const MouseButtonDownEvent& e)
{
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, true)) return;
// Tile-pick - Middle Click
if (btn == JUI::MouseButton::Middle)
{
Vector2i cell = GetGridCellFromMouse();
selected_quad = loaded_level->layers[0]->cells[cell.x][cell.y];
}
}
void EditorApp::OnMouseButtonUp(const MouseButtonUpEvent& e)
{
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, false)) return;
if (tileset_viewer->Content()->IsMouseInside()) {
Vector2i cell = GetTilesetCellFromMouse();
int index = CellToIndex(cell, loaded_tileset->rows);
selected_quad = index;
}
// TODO: This always runs even if we release the mouse inside the window. ObserveMouseInput should handle the case.
}
void EditorApp::OnMouseMove(const MouseMoveEvent& e)
{
Vector2 mposv2(e.Position.x, e.Position.y);
if (scene->ObserveMouseMovement(mposv2)) return;
}
void EditorApp::OnKeyDown(const KeyDownEvent& e)
{
if (scene->ObserveKeyInput(e.key, true)) return;
}
void EditorApp::OnKeyUp(const KeyUpEvent& e)
{
if (scene->ObserveKeyInput(e.key, false)) return;
}

View File

@@ -3,8 +3,6 @@
#include <fstream>
Color4 JsonConversions::parse_color(const JJX::json::value& v)
{
if (v.type == json::value_type::string)