Files
Editor2D/include/App/EditorApp.hpp
2025-06-04 09:47:50 -05:00

275 lines
7.3 KiB
C++

#pragma once
#include <ReWindow/types/Window.h>
#include <JUI/Widgets/Slider.hpp>
#include "JGL/JGL.h"
#include "JUI/Widgets/Image.hpp"
#include "JUI/Widgets/Scene.hpp"
#include "JUI/Widgets/UtilityBar.hpp"
#include "JUI/Widgets/Window.hpp"
// TODO: ColorPicker.hpp needs to include Slider.hpp
#include <JUI/Widgets/CommandLine.hpp>
#include "NewMapDialog.hpp"
#include "JUI/Widgets/ColorPicker.hpp"
#include "Preferences.hpp"
#include <Data/Level.hpp>
#include <Data/Tileset.hpp>
#include <JUI/Widgets/Checkbox.hpp>
#include <App/LayerView.hpp>
#include <App/TilesetView.hpp>
#define GL_VER_MAJOR 2
#define GL_VER_MINOR 1
using namespace ReWindow;
using namespace JUI::UDimLiterals;
#include <App/EditorCamera.hpp>
// TODO: Support loading an entity_prefab.json file which defines template entities to copy.
// TODO: Support sprites for these?
class Action {
public:
std::string label;
};
class SetTileAction: public Action {
public:
int tile_id;
int prior_tile_id;
Vector2i cell;
SetTileAction(const Vector2i& cell, int tileID, int priorTileID);
};
class BucketFillAction: public Action {
public:
int tile_id;
Vector2i cell;
std::vector<SetTileAction> effected_tiles;
BucketFillAction();
};
class UndoAction : public Action {};
class RedoAction : public Action {};
class EditHistory {
public:
void Undo(int index = 0);
void Redo(int index = 0);
std::vector<Action*> actions;
};
class EditHistoryLogWindow : public JUI::Window {
public:
};
class EditorApp : public OpenGLWindow {
public:
#pragma region GUI Elements
JUI::Scene* scene = nullptr;
JUI::CommandLine* console = nullptr;
JUI::Window* tileset_viewer = nullptr;
JUI::Rect* cell_indicator = nullptr;
NewMapDialog* nmd = nullptr;
LayerView* layer_view = nullptr;
JUI::Window* bg_color_tool_window = nullptr;
JUI::ColorPicker* bg_color_tool = nullptr;
JUI::UtilityBar* topbar = nullptr;
JUI::Window* app_info_dialog = nullptr;
JUI::Text* topbar_stats = nullptr;
#pragma endregion
#pragma region Map Data
Level* loaded_level;
Tileset* loaded_tileset;
JGL::Texture* loaded_tilesheet;
#pragma endregion
EditorCamera camera;
JUI::Window * CreateAppInfoDialogWindow(JUI::Widget *parent);
Preferences preferences;
int focus_layer_index = 0;
Layer* GetLayer(int index)
{
return loaded_level->layers[index];
}
Layer* GetFocusLayer()
{
return loaded_level->layers[focus_layer_index];
}
bool grid_overlay_enabled = true;
Color4 grid_overlay_color = {255, 255, 255, 64};
Color4 bg_color = Colors::Black;
bool show_cell_pointer_outline = true;
Color4 cell_pointer_outline_color = Colors::Blues::LightSteelBlue;
float cell_pointer_outline_width = 1.f;
int selected_quad = 0;
bool data_ready = false;
struct Quad {
int x;
int y;
int w;
int h;
};
//std::vector<Quad> quads;
/// This provides a mapping from a 1D flat array to a 2D grid.
/// @return The {x,y} coordinate of the grid-cell that maps to the given index.
Vector2i IndexToCell(int index, int width);
void ReplaceFill(int x, int y, int tileid);
void FloodFill(int x, int y, int tileid);
/// This provides a mapping from a 2D grid to a 1D flat array.
/// @return The {x,y} coordinate of the grid-cell that maps to the given index.
int CellToIndex(Vector2i cell, int width);
EditorApp();
~EditorApp() override
{
}
void LoadPreferences();
void SavePreferences();
/// Loads the test.lvl file into the editor.
/// @note Placeholder until FileDialogs are added.
void LoadTestFile();
/// Saves the current editor's data to test.lvl.
/// @note Placeholder until FileDialogs are added.
void SaveCurrentLevel() const;
void LoadLevel(const std::filesystem::path& level_meta_path);
void CreateTestLevel() {
loaded_level = new Level();
loaded_level->name = "TestLevel";
loaded_level->author = "dawsh";
loaded_level->cols = 64;
loaded_level->rows = 64;
loaded_level->tileset_path = "tileset.json";
auto layer = new Layer();
layer->name = "Layer 1";
layer->cols = 64;
layer->rows = 64;
layer->cell_height = 16;
layer->cell_width = 16;
layer->binary_path = "layers/1.bin";
layer->InitGrid();
layer->Save();
loaded_level->layers.push_back(layer);
loaded_tileset = new Tileset();
loaded_tileset->name = "MegaCommando";
loaded_tileset->author = "dawsh";
loaded_tileset->tex_height = 1280;
loaded_tileset->tex_width = 1024;
loaded_tileset->tile_width = 16;
loaded_tileset->tile_height = 16;
loaded_tileset->tile_spacing = 0;
loaded_tileset->cols = 80;
loaded_tileset->rows = 60;
loaded_tileset->file_path = "tileset.json";
loaded_tileset->texture_path = "../megacommando.png";
loaded_tilesheet = new JGL::Texture("../megacommando.png");
write_file_contents("tileset.json", json::deparse(loaded_tileset->Serialize()));
//layer_view->UpdateComponents(loaded_level);
data_ready = true;
SaveCurrentLevel();
}
void SizeCellIndicatorToTilesetSize();
/// Creates a JUI widget that displays the Tileset, and lets you select a tile from it.
JUI::Window* CreateTilesetViewerWindow(JUI::Widget* parent);
void ParseCmdLineMessage(const std::string& message);
void BindConsoleCallbacks();
/// Create all JUI elements required for this program.
void CreateWidgets();
/// Toggles the level grid.
void ToggleGrid();
bool Open() override;
Vector2i GetTilesetCellFromMouse();
Vector2i GetGridCellFromMouse();
void CameraUpdate(float elapsed);
int GetTile(const Vector2i& cell);
int GetTile(int x, int y);
void SetTile(int x, int y, int tileID);
void SetTile(const Vector2i& cell, int tileID);
void PlaceTileBrush(const Vector2i& cell);
void EraseTile(const Vector2i& cell);
bool IsMouseFocusedAnyActiveWidget();
void Update(float elapsed);
/// Draws a uniform grid of dashes lines at the boundaries of each tile.
/// @param bounds The viewport in which to draw. Grid lines will not be drawn beyond this box.
/// @param color The color with which to draw the grid lines.
void DrawGrid(const AABB2D& bounds, const Color4& color);
void DrawGrid(const Color4& color = {255,255,255,128});
/// Draws a colored outline on the cell that the mouse-pointer is over.
void DrawCellPointerOutline();
void DrawTiles();
void DrawLayer(const Layer* layer) const;
void DrawLevel(const Level* level) const;
void Draw();
// TODO: Closing the app nominally doesn't work on Linux.
void OnClosing() override;
/// Performs a single step of the entire program logic. Update, then Draw, then Swapbuffers.
void OnRefresh(float elapsed) override;
enum JUI::MouseButton ToJUIEnum(const MouseButton& btn);
void OnMouseButtonDown(const MouseButtonDownEvent &e) override;
void OnMouseButtonUp(const MouseButtonUpEvent &e) override;
void OnMouseMove(const MouseMoveEvent &e) override;
void OnKeyDown(const KeyDownEvent &e) override;
void OnKeyUp(const KeyUpEvent &e) override;
};