#include Layer::Layer(): rows(0), cols(0), cell_width(0), cell_height(0), parallax_x(0), parallax_y(0), cells(nullptr), visible(true), order(0) { } 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; this->visible = true; } Layer::Layer(const json::value& json) { Deserialize(json); } Layer::~Layer() { DeleteGrid(); } 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; data["order"] = (float)order; 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(); order = json["order"].number.value_or(0); } void Layer::InitGrid() { if (grid_allocated) return; // TODO: Throw double allocation. 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; } } grid_allocated = true; } void Layer::DeleteGrid() { if (!grid_allocated) return; for (int i = 0; i < rows; i++) delete[] cells[i]; delete[] cells; grid_allocated = false; } 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]; } } } void Layer::WriteToDataBuffer(int* buffer) const { //int* buffer = new int[rows*cols]; for (int x = 0; x < rows; x++) { for (int y = 0; y < cols; y++) { int index = (x*cols + y); buffer[index] = cells[x][y]; } } } bool Layer::WriteBinaryData(const std::filesystem::path& path) const { int* buffer = new int[rows*cols]; WriteToDataBuffer(buffer); std::ofstream output; output.open(path, std::ios::out | std::ios::binary); output.write(reinterpret_cast(buffer), rows * cols * sizeof(int)); output.close(); delete[] buffer; return true; } bool Layer::Save() { return WriteBinaryData(binary_path); } bool Layer::Load() { if (!std::filesystem::exists(binary_path)) { InitGrid(); return true; } return ReadBinaryData(binary_path); } bool Layer::ReadBinaryData(const std::filesystem::path& path) { std::ifstream input; input.open(path, 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(); InitGrid(); LoadFromDataBuffer(reinterpret_cast(buffer)); delete[] buffer; return true; }