Refactoring lots of stuff.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -3,8 +3,6 @@
|
||||
#include <fstream>
|
||||
|
||||
|
||||
|
||||
|
||||
Color4 JsonConversions::parse_color(const JJX::json::value& v)
|
||||
{
|
||||
if (v.type == json::value_type::string)
|
||||
|
Reference in New Issue
Block a user