Documentation
This commit is contained in:
@@ -8,6 +8,8 @@ if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
|||||||
message(FATAL_ERROR "In-source builds are not allowed!")
|
message(FATAL_ERROR "In-source builds are not allowed!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_PARALLEL_LEVEL 8)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
@@ -61,6 +61,20 @@ class EditHistoryLogWindow : public JUI::Window {
|
|||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LayerView : public JUI::Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LayerView() : JUI::Window()
|
||||||
|
{
|
||||||
|
this->SetTitle("Layers");
|
||||||
|
Name("LayerView");
|
||||||
|
}
|
||||||
|
explicit LayerView(Widget* parent) : LayerView()
|
||||||
|
{
|
||||||
|
Parent(parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class EditorApp : public OpenGLWindow {
|
class EditorApp : public OpenGLWindow {
|
||||||
public:
|
public:
|
||||||
EditorCamera camera;
|
EditorCamera camera;
|
||||||
@@ -70,6 +84,7 @@ public:
|
|||||||
JUI::Window* tileset_viewer;
|
JUI::Window* tileset_viewer;
|
||||||
JUI::Rect* cell_indicator;
|
JUI::Rect* cell_indicator;
|
||||||
JGL::Texture* test_tilesheet;
|
JGL::Texture* test_tilesheet;
|
||||||
|
LayerView* layer_view;
|
||||||
|
|
||||||
NewMapDialog* nmd = nullptr;
|
NewMapDialog* nmd = nullptr;
|
||||||
|
|
||||||
@@ -140,6 +155,7 @@ public:
|
|||||||
/// This provides a mapping from a 1D flat array to a 2D grid.
|
/// 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.
|
/// @return The {x,y} coordinate of the grid-cell that maps to the given index.
|
||||||
Vector2i IndexToCell(int index, int width);
|
Vector2i IndexToCell(int index, int width);
|
||||||
|
void ReplaceFill(int x, int y, int tileid);
|
||||||
void FloodFill(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.
|
/// This provides a mapping from a 2D grid to a 1D flat array.
|
||||||
|
@@ -1,8 +1,22 @@
|
|||||||
//
|
#pragma once
|
||||||
// Created by dawsh on 5/12/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef ENTITY_HPP
|
|
||||||
#define ENTITY_HPP
|
|
||||||
|
|
||||||
#endif //ENTITY_HPP
|
/// @class Entity
|
||||||
|
/// @brief Represents an object or interactive element placed on the map, not necessarily tied to the tile grid.
|
||||||
|
/// This can include plater spawn points, enemies, pickups, triggers, boxes (my favorite), or any other
|
||||||
|
/// game specific object that needs to be placed and configured in the level.
|
||||||
|
class Entity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#pragma region json properties
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string type;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
#pragma endregion
|
||||||
|
Entity();
|
||||||
|
Entity(const json::value& json);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
@@ -8,6 +8,11 @@
|
|||||||
|
|
||||||
using namespace JJX;
|
using namespace JJX;
|
||||||
|
|
||||||
|
enum class DataFormat
|
||||||
|
{
|
||||||
|
SignedInt32,
|
||||||
|
};
|
||||||
|
|
||||||
/// @class Layer
|
/// @class Layer
|
||||||
/// @brief Represents a single plane of tiles within a level.
|
/// @brief Represents a single plane of tiles within a level.
|
||||||
///
|
///
|
||||||
@@ -22,117 +27,82 @@ using namespace JJX;
|
|||||||
class Layer
|
class Layer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#pragma region json properties
|
||||||
|
/// The file path to the binary file containing this layer's tile data.
|
||||||
|
/// @note This path is typically relative to the main level's JSON file.
|
||||||
std::string binary_path;
|
std::string binary_path;
|
||||||
|
/// The unique name of the layer (e.g., "Ground", "Decor", "Collisions").
|
||||||
std::string name;
|
std::string name;
|
||||||
|
/// The width of the layer in tiles.
|
||||||
int rows;
|
int rows;
|
||||||
|
/// The height of the layer in tiles.
|
||||||
int cols;
|
int cols;
|
||||||
|
/// The width of the individual cells of this layer, measured in pixels.
|
||||||
int cell_width;
|
int cell_width;
|
||||||
|
/// The height of the individual cells of this layer, measured in pixels.
|
||||||
int cell_height;
|
int cell_height;
|
||||||
int** cells;
|
|
||||||
|
|
||||||
float parallax_x;
|
float parallax_x;
|
||||||
float parallax_y;
|
float parallax_y;
|
||||||
|
|
||||||
|
bool visible;
|
||||||
|
float opacity;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region binary data storage
|
||||||
|
int** cells;
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
/// The default constructor for Layer initializes member variables to default, zero values.
|
/// The default constructor for Layer initializes member variables to default, zero values.
|
||||||
Layer() {}
|
/// @note The tile-ID grid is initialized to a null-pointer, as well.
|
||||||
|
Layer();
|
||||||
|
|
||||||
/// This constructor creates an empty layer of a given size, and cell-size.
|
/// This constructor creates an empty layer of a given size, and cell-size.
|
||||||
Layer(int rows, int cols, int cell_width, int cell_height)
|
/// @note The tile-ID grid is initialized to a null-pointer.
|
||||||
{
|
Layer(int rows, int cols, int cell_width, int cell_height);
|
||||||
this->rows = rows;
|
|
||||||
this->cols = cols;
|
|
||||||
this->cell_width = cell_width;
|
|
||||||
this->cell_height = cell_height;
|
|
||||||
|
|
||||||
InitGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs a Layer object by deserializing metadata from a JSON object.
|
/// Constructs a Layer object by deserializing metadata from a JSON object.
|
||||||
/// The binary tile data will need to be loaded separately using `ReadFromFile()`
|
/// The binary tile data will need to be loaded separately using `ReadFromFile()`
|
||||||
explicit Layer(const json::value& json)
|
explicit Layer(const json::value& json);
|
||||||
|
|
||||||
|
|
||||||
|
/// Destructor for Layer cleans up all dynamically allocated memory for the tile grid.
|
||||||
|
~Layer()
|
||||||
{
|
{
|
||||||
Deserialize(json);
|
DeleteGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Destructor for Layer cleans up
|
/// Constructs a layer object from the JSON contained in the file at the given path.
|
||||||
~Layer() = default;
|
explicit Layer(const std::filesystem::path& path);
|
||||||
|
|
||||||
explicit Layer(const std::filesystem::path& path)
|
/// Serializes the current layer object's metadata into a JSON object.
|
||||||
{
|
/// This does *NOT* include the actual tile grid data, which is stored in a separate binary file.
|
||||||
auto [json, err] = json::parse(read_file_contents(path));
|
json::value Serialize() const;
|
||||||
Deserialize(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
json::value Serialize() const
|
/// Deserializes a JSON object into the current Layer object's metadata.
|
||||||
{
|
/// This also allocates the internal tile grid based on the deserialized width and height,
|
||||||
json::object data;
|
/// but does NOT load the actual tile grid data; use ReadBinaryData() for that.
|
||||||
data["name"] = name;
|
void Deserialize(const json::value& json);
|
||||||
data["binary-path"] = binary_path;
|
|
||||||
data["rows"] = (float)rows;
|
void InitGrid();
|
||||||
data["cols"] = (float)cols;
|
|
||||||
data["cell-width"] = (float)cell_width;
|
void DeleteGrid();
|
||||||
data["cell-height"] = (float)cell_height;
|
|
||||||
|
|
||||||
|
|
||||||
return data;
|
/// Resizes the layer's dimensions and reinitialize the tile data.
|
||||||
}
|
|
||||||
|
|
||||||
void Deserialize(const json::value& json)
|
|
||||||
{
|
|
||||||
name = json["name"].as_string();
|
|
||||||
binary_path = json["binary-path"].as_string();
|
|
||||||
rows = json["rows"].number.value();
|
|
||||||
cols = json["cols"].number.value();
|
|
||||||
cell_width = json["cell-width"].number.value();
|
|
||||||
cell_height = json["cell-height"].number.value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitGrid()
|
|
||||||
{
|
|
||||||
cells = new int*[rows];
|
|
||||||
|
|
||||||
for (int i = 0; i < rows; i++)
|
|
||||||
cells[i] = new int[cols];
|
|
||||||
|
|
||||||
for (int x = 0; x < rows; x++) {
|
|
||||||
for (int y = 0; y < cols; y++) {
|
|
||||||
cells[x][y] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteGrid()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < rows; i++)
|
|
||||||
delete[] cells[i];
|
|
||||||
|
|
||||||
delete[] cells;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Resizes the layer's dimensions and reinitializes the tile data.
|
|
||||||
/// Existing tile data will be lost or truncated.
|
|
||||||
///
|
///
|
||||||
void Resize(int newWidth, int newHeight)
|
/// This method creates a new internal tile grid with the specified dimensions.
|
||||||
{
|
/// Existing tile data is copied to the new grid, preserving data within the
|
||||||
|
/// overlapping region. Any data outside the new bounds is truncated, and
|
||||||
}
|
/// new cells are initialized to -1 (empty tile).
|
||||||
|
///
|
||||||
|
void Resize(int newWidth, int newHeight);
|
||||||
|
|
||||||
|
|
||||||
|
void LoadFromDataBuffer(const int* buffer);
|
||||||
void LoadFromDataBuffer(const int* buffer)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < rows; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < cols; y++)
|
|
||||||
{
|
|
||||||
int index = (x * cols + y);
|
|
||||||
cells[x][y] = buffer[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteToDataBuffer(int* buffer)
|
void WriteToDataBuffer(int* buffer)
|
||||||
{
|
{
|
||||||
@@ -150,6 +120,7 @@ public:
|
|||||||
/// Writes the current tile grid data to a specified raw binary file.
|
/// Writes the current tile grid data to a specified raw binary file.
|
||||||
/// The file path should typically be stored in the layer's JSON metadata.
|
/// The file path should typically be stored in the layer's JSON metadata.
|
||||||
/// @param path
|
/// @param path
|
||||||
|
/// @return True if the binary data was loaded successfully, false otherwise.
|
||||||
bool WriteBinaryData(const std::filesystem::path& path)
|
bool WriteBinaryData(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
int* buffer = new int[rows*cols];
|
int* buffer = new int[rows*cols];
|
||||||
@@ -187,6 +158,4 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
};
|
|
||||||
|
@@ -20,6 +20,7 @@ public:
|
|||||||
int cols;
|
int cols;
|
||||||
std::vector<Layer> layers;
|
std::vector<Layer> layers;
|
||||||
std::string tileset_path;
|
std::string tileset_path;
|
||||||
|
json::value metadata;
|
||||||
|
|
||||||
Level() {}
|
Level() {}
|
||||||
|
|
||||||
|
@@ -49,7 +49,11 @@ int main()
|
|||||||
|
|
||||||
Layer layer(128, 128, 16, 16);
|
Layer layer(128, 128, 16, 16);
|
||||||
layer.binary_path = "test.lvl";
|
layer.binary_path = "test.lvl";
|
||||||
layer.ReadBinaryData();
|
layer.Load();
|
||||||
|
|
||||||
|
layer.Resize(64, 64);
|
||||||
|
|
||||||
|
layer.Save();
|
||||||
|
|
||||||
level.layers.push_back(layer);
|
level.layers.push_back(layer);
|
||||||
|
|
||||||
|
@@ -20,6 +20,48 @@ Vector2i EditorApp::IndexToCell(int index, int width)
|
|||||||
return {x, y};
|
return {x, y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorApp::ReplaceFill(int x, int y, int tileid)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<Vector2i> matching_adjacent_cells;
|
||||||
|
|
||||||
|
int replace = GetTile(x, y);
|
||||||
|
SetTile(x, y, tileid);
|
||||||
|
|
||||||
|
int range = 1;
|
||||||
|
|
||||||
|
bool exhausted = false;
|
||||||
|
|
||||||
|
while (!exhausted)
|
||||||
|
{
|
||||||
|
int stopped = 0;
|
||||||
|
if (GetTile(x-range, y) == replace)
|
||||||
|
matching_adjacent_cells.push_back({x-range, y});
|
||||||
|
else
|
||||||
|
stopped++;
|
||||||
|
if (GetTile(x+range, y) == replace)
|
||||||
|
matching_adjacent_cells.push_back({x+range, y});
|
||||||
|
else
|
||||||
|
stopped++;
|
||||||
|
if (GetTile(x, y-range) == replace)
|
||||||
|
matching_adjacent_cells.push_back({x, y-range});
|
||||||
|
else
|
||||||
|
stopped++;
|
||||||
|
if (GetTile(x, y+range) == replace)
|
||||||
|
matching_adjacent_cells.push_back({x, y+range});
|
||||||
|
else
|
||||||
|
stopped++;
|
||||||
|
|
||||||
|
if (stopped == 4)
|
||||||
|
exhausted = true;
|
||||||
|
|
||||||
|
range++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& coords : matching_adjacent_cells)
|
||||||
|
SetTile(coords, tileid);
|
||||||
|
}
|
||||||
|
|
||||||
void EditorApp::FloodFill(int x, int y, int tileid)
|
void EditorApp::FloodFill(int x, int y, int tileid)
|
||||||
{
|
{
|
||||||
@@ -32,10 +74,6 @@ void EditorApp::FloodFill(int x, int y, int tileid)
|
|||||||
if (GetTile(x, y-1) == -1) FloodFill(x, y-1, tileid);
|
if (GetTile(x, y-1) == -1) FloodFill(x, y-1, tileid);
|
||||||
if (GetTile(x, y+1) == -1) FloodFill(x, y+1, tileid);
|
if (GetTile(x, y+1) == -1) FloodFill(x, y+1, tileid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int EditorApp::CellToIndex(Vector2i cell, int width)
|
int EditorApp::CellToIndex(Vector2i cell, int width)
|
||||||
@@ -94,7 +132,13 @@ void EditorApp::LoadTestFile()
|
|||||||
|
|
||||||
//if (!std::filesystem::exists("test_level/metadata.json"))
|
//if (!std::filesystem::exists("test_level/metadata.json"))
|
||||||
|
|
||||||
|
Level test_level = Level(std::filesystem::path("level.json"));
|
||||||
|
grid_rows = test_level.layers[0].rows;
|
||||||
|
grid_cols = test_level.layers[0].cols;
|
||||||
|
|
||||||
|
PopulateQuads();
|
||||||
|
|
||||||
|
InitGrid();
|
||||||
//std::string level_metadata_text = read_file_contents("test_level/metadata.json");
|
//std::string level_metadata_text = read_file_contents("test_level/metadata.json");
|
||||||
|
|
||||||
std::ifstream input;
|
std::ifstream input;
|
||||||
@@ -163,14 +207,14 @@ void EditorApp::LoadMisc()
|
|||||||
tileset_width = tileset.rows;//texture_size.x / grid_pixel_width;
|
tileset_width = tileset.rows;//texture_size.x / grid_pixel_width;
|
||||||
tileset_height = tileset.cols;//texture_size.y / grid_pixel_height;
|
tileset_height = tileset.cols;//texture_size.y / grid_pixel_height;
|
||||||
|
|
||||||
PopulateQuads();
|
|
||||||
|
|
||||||
InitGrid();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (std::filesystem::exists("test.lvl"))
|
if (std::filesystem::exists("test.lvl"))
|
||||||
LoadTestFile();
|
LoadTestFile();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JUI::Window* EditorApp::CreateTilesetViewerWindow(JUI::Widget* parent)
|
JUI::Window* EditorApp::CreateTilesetViewerWindow(JUI::Widget* parent)
|
||||||
@@ -279,6 +323,9 @@ void EditorApp::CreateWidgets()
|
|||||||
nmd = new NewMapDialog(scene);
|
nmd = new NewMapDialog(scene);
|
||||||
nmd->Close();
|
nmd->Close();
|
||||||
|
|
||||||
|
layer_view = new LayerView(scene);
|
||||||
|
layer_view->Open();
|
||||||
|
|
||||||
auto* topbar = new JUI::UtilityBar(scene);
|
auto* topbar = new JUI::UtilityBar(scene);
|
||||||
|
|
||||||
auto* file = topbar->AddSubmenu("File");
|
auto* file = topbar->AddSubmenu("File");
|
||||||
@@ -424,10 +471,10 @@ int EditorApp::GetTile(const Vector2i& cell)
|
|||||||
if (cell.y < 0) return -2;
|
if (cell.y < 0) return -2;
|
||||||
|
|
||||||
// out of bounds horizontally
|
// out of bounds horizontally
|
||||||
if (cell.x > grid_rows) return -2;
|
if (cell.x >= grid_rows) return -2;
|
||||||
|
|
||||||
// out of bounds vertically
|
// out of bounds vertically
|
||||||
if (cell.y > grid_cols) return -2;
|
if (cell.y >= grid_cols) return -2;
|
||||||
|
|
||||||
return grid[cell.x][cell.y];
|
return grid[cell.x][cell.y];
|
||||||
}
|
}
|
||||||
@@ -443,10 +490,10 @@ void EditorApp::SetTile(const Vector2i& cell, int tileID)
|
|||||||
if (cell.y < 0) return;
|
if (cell.y < 0) return;
|
||||||
|
|
||||||
// out of bounds horizontally
|
// out of bounds horizontally
|
||||||
if (cell.x > grid_rows) return;
|
if (cell.x >= grid_rows) return;
|
||||||
|
|
||||||
// out of bounds vertically
|
// out of bounds vertically
|
||||||
if (cell.y > grid_cols) return;
|
if (cell.y >= grid_cols) return;
|
||||||
|
|
||||||
grid[cell.x][cell.y] = tileID;
|
grid[cell.x][cell.y] = tileID;
|
||||||
}
|
}
|
||||||
@@ -467,6 +514,8 @@ void EditorApp::PlaceTileBrush(const Vector2i& cell)
|
|||||||
|
|
||||||
if (IsKeyDown(Keys::B))
|
if (IsKeyDown(Keys::B))
|
||||||
FloodFill(cell.x, cell.y, selected_quad);
|
FloodFill(cell.x, cell.y, selected_quad);
|
||||||
|
else if (IsKeyDown(Keys::R))
|
||||||
|
ReplaceFill(cell.x, cell.y, selected_quad);
|
||||||
else
|
else
|
||||||
SetTile(cell, selected_quad);
|
SetTile(cell, selected_quad);
|
||||||
}
|
}
|
||||||
@@ -548,7 +597,7 @@ void EditorApp::DrawGrid(const Color4& color)
|
|||||||
float sw = GetWidth();
|
float sw = GetWidth();
|
||||||
float sh = GetHeight();
|
float sh = GetHeight();
|
||||||
|
|
||||||
DrawGrid({{0,0}, {sw, sh}}, color);
|
DrawGrid({{0,0}, {static_cast<float>(grid_rows*grid_pixel_width), static_cast<float>(grid_cols*grid_pixel_height)}}, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorApp::DrawCellPointerOutline()
|
void EditorApp::DrawCellPointerOutline()
|
||||||
@@ -568,11 +617,16 @@ void EditorApp::DrawTiles()
|
|||||||
|
|
||||||
auto quad_idx = grid[gx][gy];
|
auto quad_idx = grid[gx][gy];
|
||||||
|
|
||||||
|
Vector2 pos(gx*grid_pixel_width, gy*grid_pixel_height);
|
||||||
|
|
||||||
|
//if ((gx+gy) % 2 == 0)
|
||||||
|
//J2D::FillRect(Colors::Purples::Fuchsia, pos, {16, 16});
|
||||||
|
|
||||||
if (quad_idx < 0)
|
if (quad_idx < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto quad = quads[quad_idx];
|
auto quad = quads[quad_idx];
|
||||||
Vector2 pos(gx*grid_pixel_width, gy*grid_pixel_height);
|
|
||||||
J2D::DrawPartialSprite(test_tilesheet, pos,
|
J2D::DrawPartialSprite(test_tilesheet, pos,
|
||||||
Vector2(quad.x, quad.y), Vector2(quad.w, quad.h));
|
Vector2(quad.x, quad.y), Vector2(quad.w, quad.h));
|
||||||
}
|
}
|
||||||
|
116
src/Layer.cpp
116
src/Layer.cpp
@@ -1 +1,117 @@
|
|||||||
#include <Layer.hpp>
|
#include <Layer.hpp>
|
||||||
|
|
||||||
|
Layer::Layer(): rows(0), cols(0), cell_width(0), cell_height(0), parallax_x(0), parallax_y(0), cells(nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Layer::Layer(int rows, int cols, int cell_width, int cell_height): cells(nullptr), parallax_x(0), parallax_y(0)
|
||||||
|
{
|
||||||
|
this->rows = rows;
|
||||||
|
this->cols = cols;
|
||||||
|
this->cell_width = cell_width;
|
||||||
|
this->cell_height = cell_height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Layer::Layer(const json::value& json)
|
||||||
|
{
|
||||||
|
Deserialize(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
Layer::Layer(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
auto [json, err] = json::parse(read_file_contents(path));
|
||||||
|
Deserialize(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
json::value Layer::Serialize() const
|
||||||
|
{
|
||||||
|
json::object data;
|
||||||
|
data["name"] = name;
|
||||||
|
data["binary-path"] = binary_path;
|
||||||
|
data["rows"] = (float)rows;
|
||||||
|
data["cols"] = (float)cols;
|
||||||
|
data["cell-width"] = (float)cell_width;
|
||||||
|
data["cell-height"] = (float)cell_height;
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::Deserialize(const json::value& json)
|
||||||
|
{
|
||||||
|
name = json["name"].as_string();
|
||||||
|
binary_path = json["binary-path"].as_string();
|
||||||
|
rows = json["rows"].number.value();
|
||||||
|
cols = json["cols"].number.value();
|
||||||
|
cell_width = json["cell-width"].number.value();
|
||||||
|
cell_height = json["cell-height"].number.value();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::InitGrid()
|
||||||
|
{
|
||||||
|
cells = new int*[rows];
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
cells[i] = new int[cols];
|
||||||
|
|
||||||
|
for (int x = 0; x < rows; x++) {
|
||||||
|
for (int y = 0; y < cols; y++) {
|
||||||
|
cells[x][y] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::DeleteGrid()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
delete[] cells[i];
|
||||||
|
|
||||||
|
delete[] cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::Resize(int newWidth, int newHeight) {
|
||||||
|
|
||||||
|
// If dimensions are unchanged, do nothing.
|
||||||
|
if (newWidth == rows && newHeight == cols)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int best_fit_rows = J3ML::Math::Min(rows, newWidth);
|
||||||
|
int best_fit_cols = J3ML::Math::Min(cols, newHeight);
|
||||||
|
|
||||||
|
int old_data_length = rows*cols;
|
||||||
|
int* old_data_contiguous = new int[old_data_length];
|
||||||
|
|
||||||
|
for (int x = 0; x < best_fit_rows; x++) {
|
||||||
|
for (int y = 0; y < best_fit_cols; y++) {
|
||||||
|
int index = (x * best_fit_cols + y);
|
||||||
|
old_data_contiguous[index] = cells[x][y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteGrid();
|
||||||
|
this->rows = newWidth;
|
||||||
|
this->cols = newHeight;
|
||||||
|
InitGrid();
|
||||||
|
|
||||||
|
for (int x = 0; x < best_fit_rows; x++) {
|
||||||
|
for (int y = 0; y < best_fit_cols; y++) {
|
||||||
|
int index = (x * best_fit_cols + y);
|
||||||
|
cells[x][y] = old_data_contiguous[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] old_data_contiguous;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::LoadFromDataBuffer(const int* buffer)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < rows; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < cols; y++)
|
||||||
|
{
|
||||||
|
int index = (x * cols + y);
|
||||||
|
cells[x][y] = buffer[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user