Refactoring, load and save levels from console-command.

This commit is contained in:
2025-06-20 14:30:08 -05:00
parent 2cdc4b5b8f
commit 4252febd3a
7 changed files with 202 additions and 79 deletions

View File

@@ -157,6 +157,9 @@ public:
/// Saves the current editor's data to test.lvl.
/// @note Placeholder until FileDialogs are added.
void SaveCurrentLevel() const;
void SaveCurrentLevelAs(const std::string &filename) const;
void LoadLevel(const std::filesystem::path& level_meta_path);
void CreateTestLevel();
@@ -178,7 +181,9 @@ public:
bool Open() override;
Vector2i GetTilesetCellFromMouse();
Vector2 GetMouseV2() const;
Vector2i GetMouseV2i() const;
Vector2i GetGridCellFromMouse();

View File

@@ -33,13 +33,11 @@ public:
}
void UpdateComponents(const Level* level)
{
for (auto entry : entry_elements) {
entry->Parent(nullptr);
delete entry;
}
entry_elements.clear();
for (auto layer : level->layers)

View File

@@ -4,7 +4,12 @@
class TilesetView : public JUI::Window {
public:
int tileset_width;
int tileset_height;
Tileset* stored_tileset;
Texture* stored_texture;
Event<int> TileSelected;
bool is_focusing;
TilesetView() : JUI::Window() {
Title("Tileset View");
@@ -18,10 +23,13 @@ public:
}
TilesetView(Tileset* tileset, JGL::Texture* texture) {
stored_tileset = tileset;
stored_texture = texture;
Title(std::format("Tileset View : {}", tileset->name));
Size(JUI::UDim2::FromPixels(texture->GetDimensions().x, texture->GetDimensions().y));
auto grid_overlay_target = new JGL::RenderTarget(texture->GetDimensions());
J2D::Begin(grid_overlay_target);
AABB2D aabb({0,0}, Vector2(texture->GetDimensions()));
@@ -34,7 +42,12 @@ public:
overlay->Content(grid_overlay);
overlay->ZIndex(2);
//cell_indicator = new JUI::Rect(Content());
cell_indicator = new JUI::Rect(Content());
cell_indicator->BorderMode(JUI::BorderMode::Outline);
cell_indicator->BorderColor(Colors::Blues::CornflowerBlue);
cell_indicator->BorderWidth(2);
SetCellSizeIndicatorToTilesetSize();
}
TilesetView(Widget* parent) {
Parent(parent);
@@ -42,9 +55,71 @@ public:
TilesetView(Tileset* tileset, JGL::Texture* texture, Widget* parent) : TilesetView(tileset, texture) {
Parent(parent);
}
Vector2i GetTilesetCell(const Vector2& pos) {
}
Vector2i GetTilesetCellFromMouse(const Vector2& mouse) {
Vector2 rel = Content()->GetAbsolutePosition();
Vector2 rel_mouse = mouse - rel;
return Vector2i(
Math::Floor(rel_mouse.x/stored_tileset->tile_width),
Math::Floor(rel_mouse.y/stored_tileset->tile_height));
}
void SetCellSizeIndicatorToTilesetSize() {
cell_indicator->Size(JUI::UDim2::FromPixels(stored_tileset->tile_width, stored_tileset->tile_height));
}
void UpdateCellIndicator(float elapsed) {
if (IsMouseInside() && Content()->IsMouseInside()) {
is_focusing = true;
cell_indicator->Visible(true);
Vector2 rel = Vector2(GetTilesetCellFromMouse(last_known_mouse_pos));
rel.x = tileset_width;
rel.y = tileset_height;
cell_indicator->Position(JUI::UDim2::FromPixels(rel.x, rel.y));
} else {
cell_indicator->Visible(false);
is_focusing = false;
}
}
bool ObserveMouseInput(JUI::MouseButton btn, bool pressed) override {
if (pressed == false) {
if (btn == JUI::MouseButton::Left) {
if (Content()->IsMouseInside()) {
Vector2i cell = GetTilesetCellFromMouse(last_known_mouse_pos);
int index = CellToIndex(cell, stored_tileset->rows);
TileSelected.Invoke(index);
}
}
}
}
bool IsFocusing() {
}
void Update(float delta) override {
Window::Update(delta);
UpdateCellIndicator(delta);
}
protected:
JUI::Image* tilesheet;
JGL::Texture* grid_overlay;
JUI::Image* tilesheet = nullptr;
JGL::Texture* grid_overlay = nullptr;
JUI::Rect* cell_indicator = nullptr;
protected:
Color4 grid_overlay_color = {255, 255, 255, 64};
Color4 cell_pointer_outline_color = Colors::Blues::LightSteelBlue;

View File

@@ -45,3 +45,6 @@ template <> inline void Lerped<Vector2>::Step(float elapsed) { current = Vector2
std::string read_file_contents(const std::filesystem::path& file_path);
bool write_file_contents(const std::filesystem::path& file_path, const std::string& contents);
std::vector<std::string> split (const std::string &s, char delim);

View File

@@ -199,7 +199,7 @@ void EditorApp::LoadTestFile()
void EditorApp::SaveCurrentLevel() const
{
// TODO: Is it decent for the layers to be written to file separate?
for (auto layer : loaded_level->layers)
{
layer->Save();
@@ -208,7 +208,21 @@ void EditorApp::SaveCurrentLevel() const
auto data = loaded_level->Serialize();
write_file_contents("level.json", json::deparse(data));
}
void EditorApp::SaveCurrentLevelAs(const std::string& filename) const {
// TODO: Is it decent for the layers to be written to file separate?
for (auto layer : loaded_level->layers)
{
layer->Save();
}
auto data = loaded_level->Serialize();
write_file_contents(filename, json::deparse(data));
}
void EditorApp::LoadLevel(const std::filesystem::path& level_meta_path)
@@ -222,6 +236,9 @@ void EditorApp::LoadLevel(const std::filesystem::path& level_meta_path)
for (auto layer : loaded_level->layers)
layer->Load();
tileset_view = new TilesetView(loaded_tileset, loaded_tilesheet);
data_ready = true;
}
@@ -277,7 +294,10 @@ JUI::Window* EditorApp::CreateTilesetViewerWindow(JUI::Widget* parent)
using namespace JUI;
auto* wind = new Window(parent);
wind->Title("Tileset Viewer");
return new TilesetView(loaded_tileset, loaded_tilesheet);
/*wind->Title("Tileset Viewer");
wind->Size(JUI::UDim2::FromPixels(loaded_tilesheet->GetDimensions().x, loaded_tilesheet->GetDimensions().y+20));
wind->SetResizable(false);
@@ -306,7 +326,7 @@ JUI::Window* EditorApp::CreateTilesetViewerWindow(JUI::Widget* parent)
cell_indicator->BorderColor(Colors::Blues::CornflowerBlue);
cell_indicator->BorderWidth(2);
SizeCellIndicatorToTilesetSize();
SizeCellIndicatorToTilesetSize();*/
return wind;
@@ -364,8 +384,38 @@ void EditorApp::BindConsoleCallbacks()
// TODO: This parsing pattern is duplicated between at least 2 other projects at this point.
// TODO: Move up into JUI or a separate package.
console->OnInput += [this] (const std::string& cmd)
console->OnInput += [this] (const std::string& input)
{
auto tokens = split(input, ' ');
std::string cmd = tokens[0];
if (cmd == "load") {
LoadLevel(tokens[1]);
}
if (cmd == "save") {
SaveCurrentLevel();
}
if (cmd == "save-as") {
if (tokens.size() >= 2)
SaveCurrentLevelAs(tokens[1]);
else
console->Log(std::format("ERROR: Must provide file name: {}", cmd));
}
if (cmd == "new") {
SaveCurrentLevel();
}
if (cmd == "info") {
}
if (cmd == "layer") {
}
if (cmd == "tileset") {
}
};
}
@@ -434,7 +484,7 @@ void EditorApp::CreateWidgets()
view->AddButton("Set Background Color", [this]{bg_color_tool_window->Toggle();});
view->AddSeparator(2_px);
view->AddButton("Console", [this]()mutable { console->Toggle();});
view->AddButton("Tileset Viewer", [this]()mutable { tileset_viewer->Toggle();});
view->AddButton("Tileset Viewer", [this]()mutable { tileset_view->Toggle();});
auto* level = topbar->AddSubmenu("Level");
auto* layer = topbar->AddSubmenu("Layer");
@@ -446,8 +496,6 @@ void EditorApp::CreateWidgets()
layer->AddButton("Export Layer");
tileset_viewer = CreateTilesetViewerWindow(scene);
bg_color_tool_window = new JUI::Window(scene);
bg_color_tool_window->Close();
@@ -502,7 +550,7 @@ bool EditorApp::Open()
CreateWidgets();
layer_view->UpdateComponents(loaded_level);
//layer_view->UpdateComponents(loaded_level);
layer_view->ActiveLayerSelected += [this](const std::string& id) mutable {
int layer_index = GetLayerIndexFromName(id);
@@ -515,27 +563,21 @@ bool EditorApp::Open()
loaded_level->layers[layer_index]->visible = value;
};
for (auto tile : loaded_tileset->tiles) {
/*for (auto tile : loaded_tileset->tiles) {
std::cout << tile.id << ", " << tile.name << std::endl;
}
}*/
return true;
}
Vector2i EditorApp::GetTilesetCellFromMouse()
{
Vector2 EditorApp::GetMouseV2() const {
auto maus = GetMouseCoordinates();
Vector2 mouse_v2(maus.x, maus.y);
Vector2 rel = tileset_viewer->Content()->GetAbsolutePosition();
Vector2 rel_mouse = mouse_v2 - rel;
return Vector2i(
Math::Floor(rel_mouse.x/GetFocusLayer()->cell_width),
Math::Floor(rel_mouse.y/GetFocusLayer()->cell_height));
return Vector2(maus.x, maus.y);
}
Vector2i EditorApp::GetMouseV2i() const {
auto maus = GetMouseCoordinates();
return Vector2i(maus.x, maus.y);
}
Vector2i EditorApp::GetGridCellFromMouse()
@@ -663,7 +705,7 @@ bool EditorApp::IsMouseFocusedAnyActiveWidget()
if (console->IsVisible() && console->IsMouseInside())
return true;
if (tileset_viewer->IsVisible() && tileset_viewer->IsMouseInside())
if (tileset_view != nullptr && tileset_view->IsVisible() && tileset_view->IsMouseInside())
return true;
if (topbar->IsVisible() && topbar->IsMouseInsideDescendants(true))
@@ -678,8 +720,7 @@ bool EditorApp::IsMouseFocusedAnyActiveWidget()
return false;
}
void EditorApp::Update(float elapsed)
{
void EditorApp::Update(float elapsed) {
CameraUpdate(elapsed);
auto size = GetSize();
Vector2i vSize = Vector2i(size.x, size.y);
@@ -701,24 +742,9 @@ void EditorApp::Update(float elapsed)
// mouse_hovering_ui_element = true;
if (tileset_viewer->IsMouseInside()) {
if (tileset_viewer->Content()->IsMouseInside()) {
cell_indicator->Visible(true);
Vector2 rel_mouse = Vector2(GetTilesetCellFromMouse());
rel_mouse.x *= loaded_tileset->tile_width;
rel_mouse.y *= loaded_tileset->tile_height;
cell_indicator->Position(JUI::UDim2::FromPixels(rel_mouse.x, rel_mouse.y));
}
} else {
cell_indicator->Visible(false);
if (!mouse_hovering_ui_element)
{
if (!mouse_hovering_ui_element)
{
if (data_ready) {
if (IsMouseButtonDown(MouseButtons::Left))
PlaceTileBrush(GetGridCellFromMouse());
@@ -730,10 +756,8 @@ void EditorApp::Update(float elapsed)
void EditorApp::DrawGrid(const AABB2D& bounds, const Color4& color)
{
Vector2 cell_size (loaded_tileset->tile_width, loaded_tileset->tile_height);
DrawGrid2(bounds, cell_size, color);
}
void EditorApp::DrawGrid(const Color4& color)
@@ -854,45 +878,53 @@ void EditorApp::Draw()
glScalef(camera.scale.current, camera.scale.current, 1);
if (grid_overlay_enabled)
DrawGrid(grid_overlay_color);
if (data_ready)
if (data_ready) {
if (grid_overlay_enabled)
DrawGrid(grid_overlay_color);
DrawLevel(loaded_level);
else
J2D::DrawString(Colors::White, "Loading Level", 0, 0, 1, 24);
if (grid_overlay_enabled)
DrawGrid(grid_overlay_color);
DrawCellPointerOutline();
}
if (grid_overlay_enabled)
DrawGrid(grid_overlay_color);
DrawCellPointerOutline();
glPopMatrix();
auto maus = GetMouseCoordinates();
if (data_ready) {
auto maus = GetMouseCoordinates();
Vector2 mouse_v2(maus.x, maus.y);
Vector2 mouse_v2(maus.x, maus.y);
auto bruhbruh = camera.CameraToScreenSpace(camera.ScreenToCameraSpace(mouse_v2));
auto bruhbruh = camera.CameraToScreenSpace(camera.ScreenToCameraSpace(mouse_v2));
Tile selected_tile = loaded_tileset->tiles[selected_quad];
J2D::DrawString(Colors::White, std::format("Selected Tile: {}", selected_tile.name), 16, 48, 16);
Tile selected_tile = loaded_tileset->tiles[selected_quad];
J2D::DrawString(Colors::White, std::format("Selected Tile: {}", selected_tile.name), 16, 48, 16);
Vector2i cell = GetGridCellFromMouse();
Vector2i cell = GetGridCellFromMouse();
int hovered_tile_id = GetTile(cell);
int hovered_tile_id = GetTile(cell);
if (hovered_tile_id > -1) {
Tile hovered_tile = loaded_tileset->tiles[hovered_tile_id];
J2D::DrawString(Colors::White, std::format("Hovered Tile: {}", hovered_tile.name), 16, 64, 16);
}
J2D::DrawPoint(Colors::White, bruhbruh, 4);
if (hovered_tile_id > -1) {
Tile hovered_tile = loaded_tileset->tiles[hovered_tile_id];
J2D::DrawString(Colors::White, std::format("Hovered Tile: {}", hovered_tile.name), 16, 64, 16);
}
J2D::DrawPoint(Colors::White, bruhbruh, 4);
J2D::End();
scene->Draw();
}
@@ -938,12 +970,12 @@ void EditorApp::OnMouseButtonUp(const MouseButtonUpEvent& e)
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, false)) return;
if (tileset_viewer->Content()->IsMouseInside()) {
/*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.
}
@@ -964,5 +996,5 @@ void EditorApp::OnKeyUp(const KeyUpEvent& e)
if (scene->ObserveKeyInput(e.key, false)) return;
if (e.key == Keys::T)
tileset_viewer->Visible(!tileset_viewer->IsVisible());
tileset_view->Toggle();
}

View File

@@ -86,3 +86,15 @@ bool write_file_contents(const std::filesystem::path& file_path, const std::stri
}
return false;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> result;
std::stringstream ss (s);
std::string item;
while (getline (ss, item, delim)) {
result.push_back (item);
}
return result;
}

View File

@@ -15,8 +15,6 @@
#include <TestGame/TestGameApp.hpp>
int main()
{
ReWindow::Logger::Debug.EnableConsole(false);