Various Random Edits...
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include <EditorApp.hpp>
|
||||
|
||||
#include "NewMapDialog.hpp"
|
||||
|
||||
void EditorApp::PopulateQuads()
|
||||
{
|
||||
quads.reserve(tileset_width*tileset_height);
|
||||
@@ -26,24 +28,42 @@ EditorApp::EditorApp(): OpenGLWindow("Editor App", 1776, 1000, GL_VER_MAJOR, GL_
|
||||
camera.DefaultState();
|
||||
}
|
||||
|
||||
|
||||
std::string read_file_contents(const std::filesystem::path& file_path)
|
||||
void EditorApp::LoadPreferences()
|
||||
{
|
||||
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);
|
||||
if (std::filesystem::exists("preferences.json"))
|
||||
{
|
||||
|
||||
char* buffer = new char[data_length];
|
||||
input.read(buffer, data_length);
|
||||
input.close();
|
||||
auto text = read_file_contents("preferences.json");
|
||||
|
||||
std::string result = std::string(buffer);
|
||||
delete[] buffer;
|
||||
return result;
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
auto [data , errcode] = json::parse(text);
|
||||
|
||||
if (!errcode.empty())
|
||||
{
|
||||
std::cerr << "Problem!1!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
preferences = Preferences(data);
|
||||
camera.translation.goal = preferences.recent_camera_state.translation;
|
||||
camera.rotation.goal = preferences.recent_camera_state.rotation;
|
||||
camera.scale.goal = preferences.recent_camera_state.scale;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorApp::SavePreferences()
|
||||
{
|
||||
|
||||
preferences.recent_camera_state.translation = camera.translation.goal;
|
||||
preferences.recent_camera_state.rotation = camera.rotation.goal;
|
||||
preferences.recent_camera_state.scale = camera.scale.goal;
|
||||
|
||||
write_file_contents("preferences.json", json::deparse(preferences.Serialize()));
|
||||
}
|
||||
|
||||
|
||||
void EditorApp::LoadTestFile()
|
||||
{
|
||||
if (!std::filesystem::exists("test_level"))
|
||||
@@ -157,15 +177,85 @@ JUI::Window* EditorApp::CreateTilesetViewerWindow(JUI::Widget* parent)
|
||||
return wind;
|
||||
}
|
||||
|
||||
namespace misc {
|
||||
std::vector<std::string> string_expand(const std::string& input, char delimiter = ' ');
|
||||
bool string_matches(const std::string& x, const std::vector<std::string>& v);
|
||||
|
||||
std::vector<std::string> misc::string_expand(const std::string& input, char delimiter)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss (input);
|
||||
std::string item;
|
||||
|
||||
while (getline(ss, item, delimiter)) {
|
||||
result.push_back(item);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
auto misc::string_matches(const std::string &x, const std::vector<std::string> &v) -> bool {
|
||||
|
||||
return std::find(v.begin(), v.end(), x) != v.end();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EditorApp::ParseCmdLineMessage(const std::string &message) {
|
||||
auto tokens = misc::string_expand(message);
|
||||
|
||||
if (tokens.size() == 0) {
|
||||
console->Log("No command input!", Colors::Red);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string cmd = tokens[0];
|
||||
|
||||
// Remove 0th element from tokens before passing to command delegates.
|
||||
tokens.erase(tokens.begin());
|
||||
|
||||
|
||||
|
||||
if (misc::string_matches(cmd, {"reset"})) {
|
||||
|
||||
}
|
||||
|
||||
console->Log(std::format("No such command: {}", cmd), Colors::Red);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void EditorApp::CreateWidgets()
|
||||
{
|
||||
scene = new JUI::Scene();
|
||||
|
||||
console = new JUI::CommandLine(scene);
|
||||
console->Close();
|
||||
BindConsoleCallbacks();
|
||||
|
||||
nmd = new NewMapDialog(scene);
|
||||
nmd->Close();
|
||||
|
||||
auto* topbar = new JUI::UtilityBar(scene);
|
||||
|
||||
auto* file = topbar->AddSubmenu("File");
|
||||
file->SetFont(JGL::Fonts::Jupiteroid);
|
||||
file->AddButton("New");
|
||||
|
||||
|
||||
auto* new_map = file->AddButton("New Map", [this] () mutable {
|
||||
nmd->Open();
|
||||
});
|
||||
|
||||
file->AddButton("Open");
|
||||
file->AddButton("Save", [this]{SaveTestFile();});
|
||||
file->AddButton("Save As");
|
||||
@@ -187,6 +277,9 @@ void EditorApp::CreateWidgets()
|
||||
view->AddSeparator(2_px);
|
||||
view->AddButton("Toggle Grid", [this]{ToggleGrid();});
|
||||
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();});
|
||||
|
||||
auto* level = topbar->AddSubmenu("Level");
|
||||
auto* layer = topbar->AddSubmenu("Layer");
|
||||
@@ -215,6 +308,8 @@ void EditorApp::ToggleGrid()
|
||||
|
||||
bool EditorApp::Open()
|
||||
{
|
||||
LoadPreferences();
|
||||
|
||||
if (!OpenGLWindow::Open()) return false;
|
||||
|
||||
auto size = GetSize();
|
||||
@@ -269,8 +364,8 @@ Vector2i EditorApp::GetGridCellFromMouse()
|
||||
|
||||
void EditorApp::CameraUpdate(float elapsed)
|
||||
{
|
||||
float move_rate = 40;
|
||||
float zoom_rate = 0.1f;
|
||||
float move_rate = 120;
|
||||
float zoom_rate = 0.2f;
|
||||
|
||||
if (IsKeyDown(Keys::LeftArrow))
|
||||
camera.translation.goal.x -= move_rate*elapsed;
|
||||
@@ -292,6 +387,11 @@ void EditorApp::CameraUpdate(float elapsed)
|
||||
|
||||
void EditorApp::SetTile(const Vector2i& cell, int tileID)
|
||||
{
|
||||
|
||||
if (cell.x < 0) return;
|
||||
|
||||
if (cell.y < 0) return;
|
||||
|
||||
// out of bounds horizontally
|
||||
if (cell.x > grid_rows) return;
|
||||
|
||||
@@ -303,6 +403,9 @@ void EditorApp::SetTile(const Vector2i& cell, int tileID)
|
||||
|
||||
void EditorApp::PlaceTileBrush(const Vector2i& cell)
|
||||
{
|
||||
if (cell.x < 0) return;
|
||||
|
||||
if (cell.y < 0) return;
|
||||
|
||||
// out of bounds horizontally
|
||||
if (cell.x > grid_rows) return;
|
||||
@@ -315,6 +418,10 @@ void EditorApp::PlaceTileBrush(const Vector2i& cell)
|
||||
|
||||
void EditorApp::EraseTile(const Vector2i& cell)
|
||||
{
|
||||
if (cell.x < 0) return;
|
||||
|
||||
if (cell.y < 0) return;
|
||||
|
||||
// out of bounds horizontally
|
||||
if (cell.x > grid_rows) return;
|
||||
|
||||
@@ -456,5 +563,6 @@ void EditorApp::Draw()
|
||||
|
||||
void EditorApp::OnClosing()
|
||||
{
|
||||
SavePreferences();
|
||||
SaveTestFile();
|
||||
}
|
||||
|
90
src/Utils.cpp
Normal file
90
src/Utils.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <Colors.hpp>
|
||||
#include <Utils.hpp>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
|
||||
|
||||
Color4 JsonConversions::parse_color(const JJX::json::value& v)
|
||||
{
|
||||
if (v.type == json::value_type::string)
|
||||
return Color4::FromHex(v.string.value());
|
||||
else if (v.type == json::value_type::array)
|
||||
{
|
||||
auto color_array = v.as_array();
|
||||
int r = color_array[0].number.value();
|
||||
int g = color_array[1].number.value();
|
||||
int b = color_array[2].number.value();
|
||||
int a = 255;
|
||||
if (color_array.value::array.value().size() == 4)
|
||||
a = color_array[3].number.value();
|
||||
return Color4(r, g, b, a);
|
||||
}
|
||||
else if (v.type == json::value_type::object)
|
||||
{
|
||||
auto color_obj = v.operator std::map<std::string, json::value>();
|
||||
int r = color_obj["r"].number.value();
|
||||
int g = color_obj["g"].number.value();
|
||||
int b = color_obj["b"].number.value();
|
||||
|
||||
int a = 255;
|
||||
|
||||
if (color_obj.contains("a"))
|
||||
a = color_obj["a"].number.value();
|
||||
|
||||
return Color4(r, g, b, a);
|
||||
}
|
||||
return Colors::Transparent;
|
||||
}
|
||||
|
||||
JJX::json::value JsonConversions::deparse_color_to_hex(const Color4& color)
|
||||
{
|
||||
return JJX::json::string(color.ToHexAlpha());
|
||||
}
|
||||
|
||||
std::vector<std::string> JsonConversions::parse_string_list(const JJX::json::value& v)
|
||||
{
|
||||
// TODO: Log an error if the json value is an invalid type.
|
||||
if (v.type == json::value_type::string)
|
||||
{
|
||||
return {v.string.value()};
|
||||
}
|
||||
else if (v.type == json::value_type::array)
|
||||
{
|
||||
std::vector<std::string> retval;
|
||||
|
||||
for (auto& token : v.array.value())
|
||||
retval.push_back(token.string.value());
|
||||
return retval;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
JJX::json::value JsonConversions::deparse_string_list(const std::vector<std::string>& list)
|
||||
{
|
||||
json::array strlist;
|
||||
for (auto& str : list)
|
||||
strlist.push_back(str);
|
||||
|
||||
return strlist;
|
||||
}
|
||||
|
||||
std::string read_file_contents(const std::filesystem::path& file_path)
|
||||
{
|
||||
std::ifstream file (file_path);
|
||||
std::ostringstream sstr;
|
||||
sstr << file.rdbuf();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
bool write_file_contents(const std::filesystem::path& file_path, const std::string& contents)
|
||||
{
|
||||
std::ofstream output(file_path);
|
||||
|
||||
if (output.is_open()) {
|
||||
output << contents;
|
||||
output.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
Reference in New Issue
Block a user