Completely remove the defunct UI system
This commit is contained in:
parent
648d2968d4
commit
626e314ec2
16 changed files with 4 additions and 939 deletions
|
@ -6,8 +6,6 @@ set(SRC
|
||||||
include/physics.hpp
|
include/physics.hpp
|
||||||
include/scene.hpp
|
include/scene.hpp
|
||||||
include/imgui_backend.hpp
|
include/imgui_backend.hpp
|
||||||
include/uielement.hpp
|
|
||||||
include/screen.hpp
|
|
||||||
include/object.hpp
|
include/object.hpp
|
||||||
include/debug.hpp
|
include/debug.hpp
|
||||||
include/components.hpp
|
include/components.hpp
|
||||||
|
@ -19,7 +17,6 @@ set(SRC
|
||||||
src/input.cpp
|
src/input.cpp
|
||||||
src/physics.cpp
|
src/physics.cpp
|
||||||
src/imgui_backend.cpp
|
src/imgui_backend.cpp
|
||||||
src/screen.cpp
|
|
||||||
src/scene.cpp
|
src/scene.cpp
|
||||||
src/debug.cpp
|
src/debug.cpp
|
||||||
src/console.cpp)
|
src/console.cpp)
|
||||||
|
|
|
@ -103,17 +103,6 @@ struct Camera {
|
||||||
Matrix4x4 view, perspective;
|
Matrix4x4 view, perspective;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
class Screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UI {
|
|
||||||
int width = 1920, height = 1080;
|
|
||||||
|
|
||||||
std::string ui_path;
|
|
||||||
ui::Screen* screen = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EnvironmentProbe {
|
struct EnvironmentProbe {
|
||||||
bool is_sized = true;
|
bool is_sized = true;
|
||||||
prism::float3 size = prism::float3(10);
|
prism::float3 size = prism::float3(10);
|
||||||
|
|
|
@ -10,11 +10,6 @@
|
||||||
#include "path.hpp"
|
#include "path.hpp"
|
||||||
|
|
||||||
class GFX;
|
class GFX;
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
class Screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Scene;
|
class Scene;
|
||||||
class RenderTarget;
|
class RenderTarget;
|
||||||
class Physics;
|
class Physics;
|
||||||
|
@ -141,22 +136,6 @@ namespace prism {
|
||||||
*/
|
*/
|
||||||
void save_scene(std::string_view path);
|
void save_scene(std::string_view path);
|
||||||
|
|
||||||
/** Load a UI screen from disk. This will not change the current screen.
|
|
||||||
@param path The screen file path.
|
|
||||||
@return Returns a instance of the screen if successful, and nullptr on failure.
|
|
||||||
*/
|
|
||||||
ui::Screen* load_screen(const prism::path& path);
|
|
||||||
|
|
||||||
/** Set the current screen.
|
|
||||||
@param screen The screen object to set as current. Can be null.
|
|
||||||
*/
|
|
||||||
void set_screen(ui::Screen* screen);
|
|
||||||
|
|
||||||
/** Gets the current screen.
|
|
||||||
@return The current screen. Can be null.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] ui::Screen* get_screen() const;
|
|
||||||
|
|
||||||
/** Load a prefab from disk.
|
/** Load a prefab from disk.
|
||||||
@param scene The scene to add the prefab to.
|
@param scene The scene to add the prefab to.
|
||||||
@param path The prefab file path.
|
@param path The prefab file path.
|
||||||
|
@ -231,31 +210,6 @@ namespace prism {
|
||||||
*/
|
*/
|
||||||
void process_mouse_down(int button, prism::Offset offset);
|
void process_mouse_down(int button, prism::Offset offset);
|
||||||
|
|
||||||
/** Pushes a UI event for the current screen. Does nothing if there is no screen set.
|
|
||||||
@param name The name of the event.
|
|
||||||
@param data Data for the event. Defaulted to an empty string.
|
|
||||||
*/
|
|
||||||
void push_event(std::string_view name, std::string_view data = "");
|
|
||||||
|
|
||||||
/** Load a localization file from disk. This will change the current localization.
|
|
||||||
@param path The localization file path.
|
|
||||||
*/
|
|
||||||
void load_localization(std::string_view path);
|
|
||||||
|
|
||||||
/** Queries whether or not the current localization loaded has a key.
|
|
||||||
@param id The key to query.
|
|
||||||
@return Whether or not the locale has the key specified.
|
|
||||||
@note Having no localization loaded will always return false.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool has_localization(std::string_view id) const;
|
|
||||||
|
|
||||||
/** Localizes a string.
|
|
||||||
@param id The locale key to use.
|
|
||||||
@return A localized string if the key is found, or an empty string if not found.
|
|
||||||
@note Having no localization loaded will always return a empty string.
|
|
||||||
*/
|
|
||||||
std::string localize(const std::string& id);
|
|
||||||
|
|
||||||
/** Adds a timer to the list of timers.
|
/** Adds a timer to the list of timers.
|
||||||
@param timer The timer to add.
|
@param timer The timer to add.
|
||||||
@note The timer instance is passed by reference. Use this to keep track of your timers without having to query it's state back.
|
@note The timer instance is passed by reference. Use this to keep track of your timers without having to query it's state back.
|
||||||
|
@ -335,8 +289,6 @@ namespace prism {
|
||||||
|
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
|
||||||
ui::Screen* current_screen = nullptr;
|
|
||||||
|
|
||||||
Scene* current_scene = nullptr;
|
Scene* current_scene = nullptr;
|
||||||
std::vector<std::unique_ptr<Scene>> scenes;
|
std::vector<std::unique_ptr<Scene>> scenes;
|
||||||
std::map<std::string, Scene*> path_to_scene;
|
std::map<std::string, Scene*> path_to_scene;
|
||||||
|
|
|
@ -201,7 +201,7 @@ class GFXFramebuffer;
|
||||||
class GFXTexture;
|
class GFXTexture;
|
||||||
|
|
||||||
/// Represents a scene consisting of Objects with varying Components.
|
/// Represents a scene consisting of Objects with varying Components.
|
||||||
class Scene : public ObjectComponents<Data, Transform, Renderable, Light, Camera, Collision, Rigidbody, UI, EnvironmentProbe> {
|
class Scene : public ObjectComponents<Data, Transform, Renderable, Light, Camera, Collision, Rigidbody, EnvironmentProbe> {
|
||||||
public:
|
public:
|
||||||
/// If loaded from disk, the path to the scene file this originated from.
|
/// If loaded from disk, the path to the scene file this originated from.
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "uielement.hpp"
|
|
||||||
#include "file.hpp"
|
|
||||||
#include "common.hpp"
|
|
||||||
|
|
||||||
class GFXBuffer;
|
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
class Screen {
|
|
||||||
public:
|
|
||||||
Screen() {}
|
|
||||||
Screen(const prism::path path);
|
|
||||||
|
|
||||||
void process_event(const std::string& type, std::string data = "");
|
|
||||||
|
|
||||||
void process_mouse(const int x, const int y);
|
|
||||||
void calculate_sizes();
|
|
||||||
|
|
||||||
std::vector<UIElement> elements;
|
|
||||||
|
|
||||||
UIElement* find_element(const std::string& id);
|
|
||||||
|
|
||||||
using CallbackFunction = std::function<void()>;
|
|
||||||
std::map<std::string, CallbackFunction> listeners;
|
|
||||||
|
|
||||||
bool blurs_background = false;
|
|
||||||
|
|
||||||
void add_listener(const std::string& id, std::function<void()> callback);
|
|
||||||
|
|
||||||
prism::Extent extent;
|
|
||||||
bool view_changed = false;
|
|
||||||
|
|
||||||
GFXBuffer* glyph_buffer = nullptr;
|
|
||||||
GFXBuffer* instance_buffer = nullptr;
|
|
||||||
GFXBuffer* elements_buffer = nullptr;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "assetptr.hpp"
|
|
||||||
|
|
||||||
enum class MetricType {
|
|
||||||
Absolute,
|
|
||||||
Relative,
|
|
||||||
Offset
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Color {
|
|
||||||
Color() : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {}
|
|
||||||
|
|
||||||
Color(const float v) : r(v), g(v), b(v), a(1.0f) {}
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float r, g, b, a;
|
|
||||||
};
|
|
||||||
|
|
||||||
float v[4];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class GFXTexture;
|
|
||||||
class Texture;
|
|
||||||
|
|
||||||
class UIElement {
|
|
||||||
public:
|
|
||||||
struct Metrics {
|
|
||||||
struct Metric {
|
|
||||||
MetricType type = MetricType::Absolute;
|
|
||||||
int value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Metric x, y, width, height;
|
|
||||||
} metrics;
|
|
||||||
|
|
||||||
struct Background {
|
|
||||||
Color color = Color(0.0f);
|
|
||||||
std::string image;
|
|
||||||
|
|
||||||
AssetPtr<Texture> texture;
|
|
||||||
} background;
|
|
||||||
|
|
||||||
enum class TextLocation {
|
|
||||||
TopLeft,
|
|
||||||
Center
|
|
||||||
} text_location = TextLocation::TopLeft;
|
|
||||||
|
|
||||||
std::string id, text, parent;
|
|
||||||
|
|
||||||
bool wrap_text = false;
|
|
||||||
|
|
||||||
float absolute_x = 0.0f, absolute_y = 0.0f, absolute_width = 0.0f, absolute_height = 0.0f;
|
|
||||||
float text_x = 0.0f, text_y = 0.0f;
|
|
||||||
|
|
||||||
bool visible = true;
|
|
||||||
|
|
||||||
std::string on_click_script;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator==(const UIElement& a, const UIElement& b) {
|
|
||||||
return a.id == b.id;
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "json_conversions.hpp"
|
#include "json_conversions.hpp"
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
#include "assertions.hpp"
|
#include "assertions.hpp"
|
||||||
#include "screen.hpp"
|
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "imgui_backend.hpp"
|
#include "imgui_backend.hpp"
|
||||||
|
@ -60,26 +59,12 @@ prism::app* engine::get_app() const {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::load_localization(const std::string_view path) {
|
|
||||||
Expects(!path.empty());
|
|
||||||
|
|
||||||
auto file = prism::open_file(prism::app_domain / path);
|
|
||||||
if(file.has_value()) {
|
|
||||||
nlohmann::json j;
|
|
||||||
file->read_as_stream() >> j;
|
|
||||||
|
|
||||||
strings = j["strings"].get<std::map<std::string, std::string>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::pause() {
|
void engine::pause() {
|
||||||
paused = true;
|
paused = true;
|
||||||
push_event("engine_pause");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::unpause() {
|
void engine::unpause() {
|
||||||
paused = false;
|
paused = false;
|
||||||
push_event("engine_unpause");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool engine::is_paused() const {
|
bool engine::is_paused() const {
|
||||||
|
@ -193,25 +178,6 @@ void engine::save_scene(const std::string_view path) {
|
||||||
out << j;
|
out << j;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui::Screen* engine::load_screen(const prism::path& path) {
|
|
||||||
Expects(!path.empty());
|
|
||||||
|
|
||||||
return new ui::Screen(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::set_screen(ui::Screen* screen) {
|
|
||||||
current_screen = screen;
|
|
||||||
|
|
||||||
screen->extent = windows[0]->extent;
|
|
||||||
screen->calculate_sizes();
|
|
||||||
|
|
||||||
get_renderer()->set_screen(screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::Screen* engine::get_screen() const {
|
|
||||||
return current_screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationChannel engine::load_animation(nlohmann::json a) {
|
AnimationChannel engine::load_animation(nlohmann::json a) {
|
||||||
AnimationChannel animation;
|
AnimationChannel animation;
|
||||||
|
|
||||||
|
@ -454,13 +420,6 @@ void engine::resize(const int identifier, const prism::Extent extent) {
|
||||||
|
|
||||||
gfx->recreate_view(identifier, drawable_extent.width, drawable_extent.height);
|
gfx->recreate_view(identifier, drawable_extent.width, drawable_extent.height);
|
||||||
renderer->resize_render_target(*window->render_target, drawable_extent);
|
renderer->resize_render_target(*window->render_target, drawable_extent);
|
||||||
|
|
||||||
if(identifier == 0) {
|
|
||||||
if(current_screen != nullptr) {
|
|
||||||
current_screen->extent = extent;
|
|
||||||
current_screen->calculate_sizes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::process_key_down(const unsigned int keyCode) {
|
void engine::process_key_down(const unsigned int keyCode) {
|
||||||
|
@ -479,31 +438,9 @@ void engine::process_key_up(const unsigned int keyCode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::process_mouse_down(const int button, const prism::Offset offset) {
|
void engine::process_mouse_down(const int button, const prism::Offset offset) {
|
||||||
if(current_screen != nullptr && button == 0)
|
|
||||||
current_screen->process_mouse(offset.x, offset.y);
|
|
||||||
|
|
||||||
imgui->process_mouse_down(button);
|
imgui->process_mouse_down(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::push_event(const std::string_view name, const std::string_view data) {
|
|
||||||
Expects(!name.empty());
|
|
||||||
|
|
||||||
if(current_screen != nullptr)
|
|
||||||
current_screen->process_event(name.data(), data.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool engine::has_localization(const std::string_view id) const {
|
|
||||||
Expects(!id.empty());
|
|
||||||
|
|
||||||
return strings.count(id.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string engine::localize(const std::string& id) {
|
|
||||||
Expects(!id.empty());
|
|
||||||
|
|
||||||
return strings[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, const Bone* parent_bone) {
|
void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, const Bone* parent_bone) {
|
||||||
if(part.offset_matrices.empty())
|
if(part.offset_matrices.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -769,11 +706,6 @@ void engine::render(const int index) {
|
||||||
GFXCommandBuffer* commandbuffer = gfx->acquire_command_buffer(true);
|
GFXCommandBuffer* commandbuffer = gfx->acquire_command_buffer(true);
|
||||||
|
|
||||||
if(index == 0) {
|
if(index == 0) {
|
||||||
if(current_screen != nullptr && current_screen->view_changed) {
|
|
||||||
renderer->update_screen();
|
|
||||||
current_screen->view_changed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
imgui->render(0);
|
imgui->render(0);
|
||||||
|
|
||||||
app->render(commandbuffer);
|
app->render(commandbuffer);
|
||||||
|
|
|
@ -65,12 +65,6 @@ void load_rigidbody_component(nlohmann::json j, Rigidbody& rigidbody) {
|
||||||
rigidbody.mass = j["mass"];
|
rigidbody.mass = j["mass"];
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_ui_component(nlohmann::json j, UI& ui) {
|
|
||||||
ui.width = j["width"];
|
|
||||||
ui.height = j["height"];
|
|
||||||
ui.ui_path = j["path"];
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_probe_component(nlohmann::json j, EnvironmentProbe& probe) {
|
void load_probe_component(nlohmann::json j, EnvironmentProbe& probe) {
|
||||||
if(j.contains("size"))
|
if(j.contains("size"))
|
||||||
probe.size = j["size"];
|
probe.size = j["size"];
|
||||||
|
@ -104,9 +98,6 @@ Object load_object(Scene& scene, const nlohmann::json obj) {
|
||||||
|
|
||||||
if(obj.contains("rigidbody"))
|
if(obj.contains("rigidbody"))
|
||||||
load_rigidbody_component(obj["rigidbody"], scene.add<Rigidbody>(o));
|
load_rigidbody_component(obj["rigidbody"], scene.add<Rigidbody>(o));
|
||||||
|
|
||||||
if(obj.contains("ui"))
|
|
||||||
load_ui_component(obj["ui"], scene.add<UI>(o));
|
|
||||||
|
|
||||||
if(obj.contains("environment_probe"))
|
if(obj.contains("environment_probe"))
|
||||||
load_probe_component(obj["environment_probe"], scene.add<EnvironmentProbe>(o));
|
load_probe_component(obj["environment_probe"], scene.add<EnvironmentProbe>(o));
|
||||||
|
@ -158,12 +149,6 @@ void save_rigidbody_component(nlohmann::json& j, const Rigidbody& rigidbody) {
|
||||||
j["mass"] = rigidbody.mass;
|
j["mass"] = rigidbody.mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_ui_component(nlohmann::json& j, const UI& ui) {
|
|
||||||
j["width"] = ui.width;
|
|
||||||
j["height"] = ui.height;
|
|
||||||
j["path"] = ui.ui_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_probe_component(nlohmann::json& j, const EnvironmentProbe& probe) {
|
void save_probe_component(nlohmann::json& j, const EnvironmentProbe& probe) {
|
||||||
j["size"] = probe.size;
|
j["size"] = probe.size;
|
||||||
j["is_sized"] = probe.is_sized;
|
j["is_sized"] = probe.is_sized;
|
||||||
|
@ -198,10 +183,7 @@ nlohmann::json save_object(Object obj) {
|
||||||
|
|
||||||
if(scene->has<Rigidbody>(obj))
|
if(scene->has<Rigidbody>(obj))
|
||||||
save_rigidbody_component(j["rigidbody"], scene->get<Rigidbody>(obj));
|
save_rigidbody_component(j["rigidbody"], scene->get<Rigidbody>(obj));
|
||||||
|
|
||||||
if(scene->has<UI>(obj))
|
|
||||||
save_ui_component(j["ui"], scene->get<UI>(obj));
|
|
||||||
|
|
||||||
if(scene->has<EnvironmentProbe>(obj))
|
if(scene->has<EnvironmentProbe>(obj))
|
||||||
save_probe_component(j["environment_probe"], scene->get<EnvironmentProbe>(obj));
|
save_probe_component(j["environment_probe"], scene->get<EnvironmentProbe>(obj));
|
||||||
|
|
||||||
|
|
|
@ -1,191 +0,0 @@
|
||||||
#include "screen.hpp"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <string_view>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
#include "file.hpp"
|
|
||||||
#include "font.hpp"
|
|
||||||
#include "engine.hpp"
|
|
||||||
#include "string_utils.hpp"
|
|
||||||
#include "log.hpp"
|
|
||||||
#include "assertions.hpp"
|
|
||||||
#include "uielement.hpp"
|
|
||||||
|
|
||||||
void ui::Screen::calculate_sizes() {
|
|
||||||
unsigned int numChildren = 0;
|
|
||||||
|
|
||||||
int actualWidth = extent.width, actualHeight = extent.height;
|
|
||||||
int offsetX = 0, offsetY = 0;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < elements.size(); i++) {
|
|
||||||
auto& element = elements[i];
|
|
||||||
|
|
||||||
auto id = "ui_" + element.id;
|
|
||||||
//if(engine->has_localization(id))
|
|
||||||
// element.text = engine->localize(id);
|
|
||||||
|
|
||||||
UIElement* parent = nullptr;
|
|
||||||
if(!element.parent.empty())
|
|
||||||
parent = find_element(element.parent);
|
|
||||||
|
|
||||||
const auto& fillAbsolute = [parent](const auto& metric, auto& absolute, auto base, auto offset) {
|
|
||||||
switch(metric.type) {
|
|
||||||
case MetricType::Absolute:
|
|
||||||
absolute = offset + metric.value;
|
|
||||||
break;
|
|
||||||
case MetricType::Relative:
|
|
||||||
absolute = offset + ((base - offset) * (metric.value / 100.0f));
|
|
||||||
break;
|
|
||||||
case MetricType::Offset:
|
|
||||||
{
|
|
||||||
if(parent == nullptr)
|
|
||||||
absolute = base - metric.value;
|
|
||||||
else
|
|
||||||
absolute = parent->absolute_height - metric.value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fillAbsolute(element.metrics.x, element.absolute_x, offsetX + actualWidth, offsetX);
|
|
||||||
fillAbsolute(element.metrics.y, element.absolute_y, offsetY + actualHeight, offsetY);
|
|
||||||
|
|
||||||
fillAbsolute(element.metrics.width, element.absolute_width, actualWidth, 0);
|
|
||||||
fillAbsolute(element.metrics.height, element.absolute_height, actualHeight, 0);
|
|
||||||
|
|
||||||
if(parent) {
|
|
||||||
const float heightPerRow = actualWidth / (float)elements.size();
|
|
||||||
|
|
||||||
element.absolute_x = (float)numChildren * heightPerRow;
|
|
||||||
element.absolute_y = actualHeight - 50.0f;
|
|
||||||
element.absolute_width = (float)heightPerRow;
|
|
||||||
element.absolute_height = (float)50.0f;
|
|
||||||
|
|
||||||
numChildren++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(element.text_location == UIElement::TextLocation::Center) {
|
|
||||||
if(get_string_width(element.text) < element.absolute_width)
|
|
||||||
element.text_x = (element.absolute_width / 2.0f) - (get_string_width(element.text) / 2.0f);
|
|
||||||
|
|
||||||
if(get_font_height() < element.absolute_height)
|
|
||||||
element.text_y = (element.absolute_height / 2.0f) - (get_font_height() / 2.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui::Screen::process_mouse(const int x, const int y) {
|
|
||||||
Expects(x >= 0);
|
|
||||||
Expects(y >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIElement* ui::Screen::find_element(const std::string& id) {
|
|
||||||
Expects(!id.empty());
|
|
||||||
|
|
||||||
UIElement* foundElement = nullptr;
|
|
||||||
for(auto& element : elements) {
|
|
||||||
if(element.id == id)
|
|
||||||
foundElement = &element;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expects(foundElement != nullptr);
|
|
||||||
|
|
||||||
return foundElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::Screen::Screen(const prism::path path) {
|
|
||||||
auto file = prism::open_file(path);
|
|
||||||
if(!file.has_value()) {
|
|
||||||
prism::log::error(System::Core, "Failed to load UI from {}!", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlohmann::json j;
|
|
||||||
file->read_as_stream() >> j;
|
|
||||||
|
|
||||||
for(auto& element : j["elements"]) {
|
|
||||||
UIElement ue;
|
|
||||||
ue.id = element["id"];
|
|
||||||
|
|
||||||
if(element.contains("on_click"))
|
|
||||||
ue.on_click_script = element["on_click"];
|
|
||||||
|
|
||||||
if(element.contains("text"))
|
|
||||||
ue.text = element["text"];
|
|
||||||
|
|
||||||
if(element.contains("parent"))
|
|
||||||
ue.parent = element["parent"];
|
|
||||||
|
|
||||||
if(element.contains("metrics")) {
|
|
||||||
const auto& metrics = element["metrics"];
|
|
||||||
|
|
||||||
const auto parseMetric = [](const std::string& str) {
|
|
||||||
UIElement::Metrics::Metric m;
|
|
||||||
|
|
||||||
if(string_contains(str, "px")) {
|
|
||||||
auto v = remove_substring(str, "px");
|
|
||||||
|
|
||||||
if(string_contains(str, "@")) {
|
|
||||||
m.type = MetricType::Offset;
|
|
||||||
m.value = std::stoi(remove_substring(v, "@"));
|
|
||||||
} else {
|
|
||||||
m.type = MetricType::Absolute;
|
|
||||||
m.value = std::stoi(v);
|
|
||||||
}
|
|
||||||
} else if(string_contains(str, "%")) {
|
|
||||||
m.type = MetricType::Relative;
|
|
||||||
m.value = std::stoi(remove_substring(str, "%"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(metrics.contains("x"))
|
|
||||||
ue.metrics.x = parseMetric(metrics["x"]);
|
|
||||||
|
|
||||||
if(metrics.contains("y"))
|
|
||||||
ue.metrics.y = parseMetric(metrics["y"]);
|
|
||||||
|
|
||||||
if(metrics.contains("width"))
|
|
||||||
ue.metrics.width = parseMetric(metrics["width"]);
|
|
||||||
|
|
||||||
if(metrics.contains("height"))
|
|
||||||
ue.metrics.height = parseMetric(metrics["height"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(element.contains("background")) {
|
|
||||||
if(element["background"].contains("color")) {
|
|
||||||
auto tokens = tokenize(element["background"]["color"].get<std::string_view>(), ",");
|
|
||||||
ue.background.color.r = std::stof(tokens[0]);
|
|
||||||
ue.background.color.g = std::stof(tokens[1]);
|
|
||||||
ue.background.color.b = std::stof(tokens[2]);
|
|
||||||
ue.background.color.a = std::stof(tokens[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(element["background"].contains("image")) {
|
|
||||||
ue.background.image = element["background"]["image"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(element.contains("wrap"))
|
|
||||||
ue.wrap_text = element["wrap"];
|
|
||||||
|
|
||||||
if(element.contains("textLocation")) {
|
|
||||||
if(element["textLocation"] == "topLeft")
|
|
||||||
ue.text_location = UIElement::TextLocation::TopLeft;
|
|
||||||
else if(element["textLocation"] == "center")
|
|
||||||
ue.text_location = UIElement::TextLocation::Center;
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.push_back(ue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui::Screen::add_listener(const std::string& id, std::function<void()> callback) {
|
|
||||||
listeners[id] = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui::Screen::process_event(const std::string& type, const std::string data) {
|
|
||||||
|
|
||||||
}
|
|
|
@ -55,21 +55,12 @@ namespace prism {
|
||||||
|
|
||||||
void recreate_all_render_targets();
|
void recreate_all_render_targets();
|
||||||
|
|
||||||
void set_screen(ui::Screen* screen);
|
|
||||||
|
|
||||||
void init_screen(ui::Screen* screen);
|
|
||||||
|
|
||||||
void update_screen();
|
|
||||||
|
|
||||||
struct controller_continuity {
|
struct controller_continuity {
|
||||||
int elementOffset = 0;
|
int elementOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, int index);
|
void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, int index);
|
||||||
|
|
||||||
void render_screen(GFXCommandBuffer* commandBuffer, ui::Screen* screen, prism::Extent extent,
|
|
||||||
controller_continuity& continuity, render_screen_options options = render_screen_options());
|
|
||||||
|
|
||||||
void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera,
|
void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera,
|
||||||
prism::Extent extent, RenderTarget& target, controller_continuity &continuity);
|
prism::Extent extent, RenderTarget& target, controller_continuity &continuity);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include "gfx_commandbuffer.hpp"
|
#include "gfx_commandbuffer.hpp"
|
||||||
#include "math.hpp"
|
#include "math.hpp"
|
||||||
#include "screen.hpp"
|
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "scene.hpp"
|
#include "scene.hpp"
|
||||||
#include "font.hpp"
|
#include "font.hpp"
|
||||||
|
@ -185,48 +184,6 @@ void renderer::recreate_all_render_targets() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer::set_screen(ui::Screen* screen) {
|
|
||||||
Expects(screen != nullptr);
|
|
||||||
|
|
||||||
current_screen = screen;
|
|
||||||
|
|
||||||
init_screen(screen);
|
|
||||||
|
|
||||||
update_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer::init_screen(ui::Screen* screen) {
|
|
||||||
Expects(screen != nullptr);
|
|
||||||
|
|
||||||
std::array<GylphMetric, numGlyphs> metrics = {};
|
|
||||||
for(int i = 0; i < numGlyphs; i++) {
|
|
||||||
GylphMetric& metric = metrics[i];
|
|
||||||
metric.x0_y0 = utility::pack_u32(font.sizes[fontSize][i].x0, font.sizes[fontSize][i].y0);
|
|
||||||
metric.x1_y1 = utility::pack_u32(font.sizes[fontSize][i].x1, font.sizes[fontSize][i].y1);
|
|
||||||
metric.xoff = font.sizes[fontSize][i].xoff;
|
|
||||||
metric.yoff = font.sizes[fontSize][i].yoff;
|
|
||||||
metric.xoff2 = font.sizes[fontSize][i].xoff2;
|
|
||||||
metric.yoff2 = font.sizes[fontSize][i].yoff2;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen->glyph_buffer = gfx->create_buffer(nullptr, instance_alignment + (sizeof(GylphMetric) * numGlyphs), false, GFXBufferUsage::Storage);
|
|
||||||
|
|
||||||
gfx->copy_buffer(screen->glyph_buffer, metrics.data(), instance_alignment, sizeof(GylphMetric) * numGlyphs);
|
|
||||||
|
|
||||||
screen->elements_buffer = gfx->create_buffer(nullptr, sizeof(ElementInstance) * 50, true, GFXBufferUsage::Storage);
|
|
||||||
|
|
||||||
screen->instance_buffer = gfx->create_buffer(nullptr, sizeof(StringInstance) * 50, true, GFXBufferUsage::Storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer::update_screen() {
|
|
||||||
if(current_screen != nullptr) {
|
|
||||||
for(auto& element : current_screen->elements) {
|
|
||||||
if(!element.background.image.empty())
|
|
||||||
element.background.texture = assetm->get<Texture>(prism::app_domain / element.background.image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, int index) {
|
void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, int index) {
|
||||||
const auto extent = target.extent;
|
const auto extent = target.extent;
|
||||||
const auto render_extent = target.get_render_extent();
|
const auto render_extent = target.get_render_extent();
|
||||||
|
@ -403,10 +360,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
||||||
commandbuffer->draw(0, 4, 0, 1);
|
commandbuffer->draw(0, 4, 0, 1);
|
||||||
|
|
||||||
commandbuffer->pop_group();
|
commandbuffer->pop_group();
|
||||||
|
|
||||||
if(current_screen != nullptr)
|
|
||||||
render_screen(commandbuffer, current_screen, extent, continuity);
|
|
||||||
|
|
||||||
commandbuffer->push_group("Extra Passes");
|
commandbuffer->push_group("Extra Passes");
|
||||||
|
|
||||||
for(auto& pass : passes)
|
for(auto& pass : passes)
|
||||||
|
@ -533,18 +487,6 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& screens = scene.get_all<UI>();
|
|
||||||
for(const auto& [obj, screen] : screens) {
|
|
||||||
if(!screen.screen)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
render_screen_options options = {};
|
|
||||||
options.render_world = true;
|
|
||||||
options.mvp = camera.perspective * camera.view * scene.get<Transform>(obj).model;
|
|
||||||
|
|
||||||
render_screen(command_buffer, screen.screen, extent, continuity, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkyPushConstant pc;
|
SkyPushConstant pc;
|
||||||
pc.view = matrix_from_quat(scene.get<Transform>(camera_object).rotation);
|
pc.view = matrix_from_quat(scene.get<Transform>(camera_object).rotation);
|
||||||
pc.aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height);
|
pc.aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height);
|
||||||
|
@ -568,136 +510,6 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
|
||||||
gfx->copy_buffer(target.sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
|
gfx->copy_buffer(target.sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen, prism::Extent extent, controller_continuity& continuity, render_screen_options options) {
|
|
||||||
std::array<GlyphInstance, maxInstances> instances;
|
|
||||||
std::vector<ElementInstance> elementInstances;
|
|
||||||
std::array<StringInstance, 50> stringInstances = {};
|
|
||||||
|
|
||||||
int stringLen = 0;
|
|
||||||
int numElements = 0;
|
|
||||||
|
|
||||||
for(auto [i, element] : utility::enumerate(screen->elements)) {
|
|
||||||
if(!element.visible)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ElementInstance instance;
|
|
||||||
|
|
||||||
instance.position = utility::pack_u32(utility::to_fixed(element.absolute_x), utility::to_fixed(element.absolute_y));
|
|
||||||
instance.size = utility::pack_u32(utility::to_fixed(element.absolute_width), utility::to_fixed(element.absolute_height));
|
|
||||||
instance.color[0] = element.background.color.r;
|
|
||||||
instance.color[1] = element.background.color.g;
|
|
||||||
instance.color[2] = element.background.color.b;
|
|
||||||
instance.color[3] = element.background.color.a;
|
|
||||||
|
|
||||||
elementInstances.push_back(instance);
|
|
||||||
|
|
||||||
stringInstances[i].xy = utility::pack_u32(utility::to_fixed(element.absolute_x + element.text_x), utility::to_fixed(element.absolute_y + element.text_y));
|
|
||||||
|
|
||||||
float advance = 0.0f;
|
|
||||||
float yadvance = 0.0f;
|
|
||||||
|
|
||||||
bool do_y_advance = false; // so we can not advance the text by a space if we're wrapping per word
|
|
||||||
|
|
||||||
for(size_t j = 0; j < element.text.length(); j++) {
|
|
||||||
auto index = element.text[j] - 32;
|
|
||||||
|
|
||||||
if(do_y_advance) {
|
|
||||||
advance = 0.0f;
|
|
||||||
yadvance += font.ascentSizes[fontSize];
|
|
||||||
do_y_advance = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(element.wrap_text) {
|
|
||||||
if(element.text[j] == ' ') {
|
|
||||||
std::string t;
|
|
||||||
float temp_advance = 0.0f;
|
|
||||||
for(size_t k = j + 1; k < element.text.length() + j; k++) {
|
|
||||||
t += element.text[k];
|
|
||||||
auto index = element.text[k] - 32;
|
|
||||||
temp_advance += font.sizes[fontSize][index].xadvance;
|
|
||||||
|
|
||||||
if(element.text[k] == ' ')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((temp_advance + advance) >= element.absolute_width)
|
|
||||||
do_y_advance = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GlyphInstance& instance = instances[stringLen + j];
|
|
||||||
instance.position = utility::pack_u32(utility::to_fixed(advance), utility::to_fixed(yadvance));
|
|
||||||
instance.index = utility::pack_u32(index, 0);
|
|
||||||
instance.instance = i;
|
|
||||||
|
|
||||||
advance += font.sizes[fontSize][index].xadvance;
|
|
||||||
|
|
||||||
if(element.text[j] == '\n') {
|
|
||||||
advance = 0.0f;
|
|
||||||
yadvance += font.ascentSizes[fontSize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stringLen += static_cast<int>(element.text.length());
|
|
||||||
numElements++;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx->copy_buffer(screen->glyph_buffer, instances.data(), 0, instance_alignment);
|
|
||||||
gfx->copy_buffer(screen->instance_buffer, stringInstances.data(), 0, sizeof(StringInstance) * 50);
|
|
||||||
gfx->copy_buffer(screen->elements_buffer, elementInstances.data(), sizeof(ElementInstance) * continuity.elementOffset, sizeof(ElementInstance) * elementInstances.size());
|
|
||||||
|
|
||||||
const prism::float2 windowSize = {static_cast<float>(extent.width), static_cast<float>(extent.height)};
|
|
||||||
|
|
||||||
for(auto [i, element] : utility::enumerate(screen->elements)) {
|
|
||||||
if(!element.visible)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
UIPushConstant pc;
|
|
||||||
pc.screenSize = windowSize;
|
|
||||||
|
|
||||||
if(options.render_world) {
|
|
||||||
commandbuffer->set_graphics_pipeline(world_general_pipeline);
|
|
||||||
pc.mvp = options.mvp;
|
|
||||||
} else {
|
|
||||||
commandbuffer->set_graphics_pipeline(general_pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.background.texture) {
|
|
||||||
commandbuffer->bind_texture(element.background.texture->handle, 2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
commandbuffer->bind_texture(dummy_texture, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandbuffer->set_push_constant(&pc, sizeof(UIPushConstant));
|
|
||||||
|
|
||||||
commandbuffer->bind_shader_buffer(screen->elements_buffer, 0, 0, sizeof(ElementInstance) * 50);
|
|
||||||
commandbuffer->draw(0, 4, i + continuity.elementOffset, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIPushConstant pc;
|
|
||||||
pc.screenSize = windowSize;
|
|
||||||
|
|
||||||
if(options.render_world) {
|
|
||||||
commandbuffer->set_graphics_pipeline(world_text_pipeline);
|
|
||||||
pc.mvp = options.mvp;
|
|
||||||
} else {
|
|
||||||
commandbuffer->set_graphics_pipeline(text_pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandbuffer->set_push_constant(&pc, sizeof(UIPushConstant));
|
|
||||||
|
|
||||||
commandbuffer->bind_shader_buffer(screen->glyph_buffer, 0, 0, instance_alignment);
|
|
||||||
commandbuffer->bind_shader_buffer(screen->glyph_buffer, instance_alignment, 1, sizeof(GylphMetric) * numGlyphs);
|
|
||||||
commandbuffer->bind_shader_buffer(screen->instance_buffer, 0, 2, sizeof(StringInstance) * 50);
|
|
||||||
commandbuffer->bind_texture(font_texture, 3);
|
|
||||||
|
|
||||||
if(stringLen > 0)
|
|
||||||
commandbuffer->draw(0, 4, 0, stringLen);
|
|
||||||
|
|
||||||
continuity.elementOffset += numElements;
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer::create_mesh_pipeline(Material& material) const {
|
void renderer::create_mesh_pipeline(Material& material) const {
|
||||||
GFXShaderConstant materials_constant = {};
|
GFXShaderConstant materials_constant = {};
|
||||||
materials_constant.type = GFXShaderConstant::Type::Integer;
|
materials_constant.type = GFXShaderConstant::Type::Integer;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "gfx_commandbuffer.hpp"
|
#include "gfx_commandbuffer.hpp"
|
||||||
#include "imgui_utility.hpp"
|
#include "imgui_utility.hpp"
|
||||||
#include "screen.hpp"
|
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "scenecapture.hpp"
|
#include "scenecapture.hpp"
|
||||||
|
@ -459,20 +458,6 @@ void editRigidbody(Rigidbody& rigidbody) {
|
||||||
ImGui::DragInt("Mass", &rigidbody.mass);
|
ImGui::DragInt("Mass", &rigidbody.mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editUI(UI& ui) {
|
|
||||||
ImGui::DragInt("Width", &ui.width);
|
|
||||||
ImGui::DragInt("Height", &ui.height);
|
|
||||||
ImGui::InputText("Path", &ui.ui_path);
|
|
||||||
|
|
||||||
if(ImGui::Button("Reload")) {
|
|
||||||
ui.screen = engine->load_screen(prism::app_domain / ui.ui_path);
|
|
||||||
engine->get_renderer()->init_screen(ui.screen);
|
|
||||||
ui.screen->extent.width = ui.width;
|
|
||||||
ui.screen->extent.height = ui.height;
|
|
||||||
ui.screen->calculate_sizes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void editProbe(EnvironmentProbe& probe) {
|
void editProbe(EnvironmentProbe& probe) {
|
||||||
ImGui::Checkbox("Is Sized", &probe.is_sized);
|
ImGui::Checkbox("Is Sized", &probe.is_sized);
|
||||||
if(probe.is_sized)
|
if(probe.is_sized)
|
||||||
|
@ -608,11 +593,6 @@ void CommonEditor::drawPropertyEditor() {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::Selectable("UI")) {
|
|
||||||
scene->add<UI>(selected_object);
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::Selectable("Environment Probe")) {
|
if(ImGui::Selectable("Environment Probe")) {
|
||||||
scene->add<EnvironmentProbe>(selected_object);
|
scene->add<EnvironmentProbe>(selected_object);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
@ -638,10 +618,7 @@ void CommonEditor::drawPropertyEditor() {
|
||||||
|
|
||||||
if(componentHeader<Rigidbody>(*scene, selected_object, "Rigidbody"))
|
if(componentHeader<Rigidbody>(*scene, selected_object, "Rigidbody"))
|
||||||
editRigidbody(scene->get<Rigidbody>(selected_object));
|
editRigidbody(scene->get<Rigidbody>(selected_object));
|
||||||
|
|
||||||
if(componentHeader<UI>(*scene, selected_object, "UI"))
|
|
||||||
editUI(scene->get<UI>(selected_object));
|
|
||||||
|
|
||||||
if(componentHeader<EnvironmentProbe>(*scene, selected_object, "Environment Probe"))
|
if(componentHeader<EnvironmentProbe>(*scene, selected_object, "Environment Probe"))
|
||||||
editProbe(scene->get<EnvironmentProbe>(selected_object));
|
editProbe(scene->get<EnvironmentProbe>(selected_object));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,11 @@ set(SRC
|
||||||
include/prismeditor.hpp
|
include/prismeditor.hpp
|
||||||
include/materialeditor.hpp
|
include/materialeditor.hpp
|
||||||
include/sceneeditor.hpp
|
include/sceneeditor.hpp
|
||||||
include/uieditor.hpp
|
|
||||||
include/prefabeditor.hpp
|
include/prefabeditor.hpp
|
||||||
|
|
||||||
src/prismeditor.cpp
|
src/prismeditor.cpp
|
||||||
src/materialeditor.cpp
|
src/materialeditor.cpp
|
||||||
src/sceneeditor.cpp
|
src/sceneeditor.cpp
|
||||||
src/uieditor.cpp
|
|
||||||
src/prefabeditor.cpp)
|
src/prefabeditor.cpp)
|
||||||
|
|
||||||
add_platform_executable(
|
add_platform_executable(
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "prismeditor.hpp"
|
|
||||||
|
|
||||||
#include "screen.hpp"
|
|
||||||
|
|
||||||
class UIEditor : public Editor {
|
|
||||||
public:
|
|
||||||
UIEditor();
|
|
||||||
|
|
||||||
ui::Screen* screen = nullptr;
|
|
||||||
UIElement* current_element = nullptr;
|
|
||||||
|
|
||||||
bool has_menubar() const override;
|
|
||||||
std::string get_title() const override;
|
|
||||||
|
|
||||||
Scene* get_scene() const override;
|
|
||||||
|
|
||||||
void setup_windows(ImGuiID dockspace) override;
|
|
||||||
|
|
||||||
void edit_metric(const char* label, UIElement::Metrics::Metric* metric);
|
|
||||||
std::string save_metric(UIElement::Metrics::Metric metric);
|
|
||||||
|
|
||||||
void save(std::string path);
|
|
||||||
|
|
||||||
void draw(CommonEditor* editor) override;
|
|
||||||
};
|
|
|
@ -11,11 +11,9 @@
|
||||||
#include "json_conversions.hpp"
|
#include "json_conversions.hpp"
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "string_utils.hpp"
|
#include "string_utils.hpp"
|
||||||
#include "screen.hpp"
|
|
||||||
#include "sceneeditor.hpp"
|
#include "sceneeditor.hpp"
|
||||||
#include "materialeditor.hpp"
|
#include "materialeditor.hpp"
|
||||||
#include "prefabeditor.hpp"
|
#include "prefabeditor.hpp"
|
||||||
#include "uieditor.hpp"
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
||||||
std::string get_filename(const std::string path) {
|
std::string get_filename(const std::string path) {
|
||||||
|
@ -164,15 +162,6 @@ void PrismEditor::open_asset(const prism::path path) {
|
||||||
|
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
|
|
||||||
editors.push_back(editor);
|
|
||||||
} else if(path.extension() == ".json") {
|
|
||||||
UIEditor* editor = new UIEditor();
|
|
||||||
editor->path = path.string();
|
|
||||||
setup_editor(editor);
|
|
||||||
|
|
||||||
editor->screen = engine->load_screen(path);
|
|
||||||
editor->screen->calculate_sizes();
|
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,14 +222,6 @@ void PrismEditor::drawUI() {
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::MenuItem("UI")) {
|
|
||||||
UIEditor* editor = new UIEditor();
|
|
||||||
editor->modified = true;
|
|
||||||
setup_editor(editor);
|
|
||||||
|
|
||||||
editors.push_back(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
#include "uieditor.hpp"
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
|
||||||
|
|
||||||
#include "engine.hpp"
|
|
||||||
#include "imgui_utility.hpp"
|
|
||||||
|
|
||||||
UIEditor::UIEditor() : Editor() {
|
|
||||||
screen = new ui::Screen();
|
|
||||||
screen->extent.width = 1280;
|
|
||||||
screen->extent.height = 720;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UIEditor::has_menubar() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string UIEditor::get_title() const {
|
|
||||||
return path.empty() ? "New UI" : get_filename(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Scene* UIEditor::get_scene() const {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEditor::setup_windows(ImGuiID dockspace) {
|
|
||||||
ImGuiID dock_main_id = dockspace;
|
|
||||||
|
|
||||||
ImGuiID dock_id_left, dock_id_right;
|
|
||||||
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.60f, &dock_id_left, &dock_id_right);
|
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Properties").c_str(), dock_id_right);
|
|
||||||
|
|
||||||
ImGui::DockBuilderSplitNode(dock_id_left, ImGuiDir_Left, 0.30f, &dock_id_left, &dock_id_right);
|
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Outliner").c_str(), dock_id_left);
|
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Preview").c_str(), dock_id_right);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEditor::edit_metric(const char* label, UIElement::Metrics::Metric* metric) {
|
|
||||||
if(ImGui::DragInt(label, &metric->value, 1.0f, 0, 0, metric->type == MetricType::Absolute ? "%d" : "%d%%"))
|
|
||||||
screen->calculate_sizes();
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(label);
|
|
||||||
|
|
||||||
if(ImGui::ComboEnum("T", &metric->type))
|
|
||||||
screen->calculate_sizes();
|
|
||||||
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string UIEditor::save_metric(UIElement::Metrics::Metric metric) {
|
|
||||||
return std::to_string(metric.value) + (metric.type == MetricType::Absolute ? "px" : "%");
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEditor::save(std::string path) {
|
|
||||||
nlohmann::json j;
|
|
||||||
|
|
||||||
for (auto& element : screen->elements) {
|
|
||||||
nlohmann::json e;
|
|
||||||
e["id"] = element.id;
|
|
||||||
e["text"] = element.text;
|
|
||||||
e["visible"] = element.visible;
|
|
||||||
e["wrapText"] = element.wrap_text;
|
|
||||||
|
|
||||||
nlohmann::json m;
|
|
||||||
m["x"] = save_metric(element.metrics.x);
|
|
||||||
m["y"] = save_metric(element.metrics.y);
|
|
||||||
m["width"] = save_metric(element.metrics.width);
|
|
||||||
m["height"] = save_metric(element.metrics.height);
|
|
||||||
|
|
||||||
e["metrics"] = m;
|
|
||||||
|
|
||||||
if(element.text_location == UIElement::TextLocation::Center) {
|
|
||||||
e["textLocation"] = "center";
|
|
||||||
} else {
|
|
||||||
e["textLocation"] = "topLeft";
|
|
||||||
}
|
|
||||||
|
|
||||||
j["elements"].push_back(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream out(path);
|
|
||||||
out << std::setw(4) << j;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEditor::draw(CommonEditor*) {
|
|
||||||
if (ImGui::BeginMenuBar()) {
|
|
||||||
if (ImGui::BeginMenu("File")) {
|
|
||||||
if(ImGui::MenuItem("Save", "CTRL+S")) {
|
|
||||||
if (path.empty()) {
|
|
||||||
platform::save_dialog([this](std::string path) {
|
|
||||||
this->path = path;
|
|
||||||
|
|
||||||
save(path);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
save(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::MenuItem("Save as...", "CTRL+S")) {
|
|
||||||
platform::save_dialog([this](std::string path) {
|
|
||||||
this->path = path;
|
|
||||||
|
|
||||||
save(path);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if(ImGui::MenuItem("Close"))
|
|
||||||
wants_to_close = true;
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(begin("Outliner")) {
|
|
||||||
if(ImGui::Button("Add Element")) {
|
|
||||||
screen->elements.push_back(UIElement());
|
|
||||||
current_element = &screen->elements.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& element : screen->elements) {
|
|
||||||
if(ImGui::Selectable(element.id.c_str()))
|
|
||||||
current_element = &element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
if(begin("Properties")) {
|
|
||||||
if(current_element != nullptr) {
|
|
||||||
ImGui::InputText("ID", ¤t_element->id);
|
|
||||||
|
|
||||||
edit_metric("X", ¤t_element->metrics.x);
|
|
||||||
edit_metric("Y", ¤t_element->metrics.y);
|
|
||||||
edit_metric("Width", ¤t_element->metrics.width);
|
|
||||||
edit_metric("Height", ¤t_element->metrics.height);
|
|
||||||
|
|
||||||
ImGui::InputText("Text", ¤t_element->text);
|
|
||||||
|
|
||||||
ImGui::ColorEdit4("Background color", current_element->background.color.v);
|
|
||||||
|
|
||||||
ImGui::Checkbox("Visible", ¤t_element->visible);
|
|
||||||
ImGui::Checkbox("Wrap text", ¤t_element->wrap_text);
|
|
||||||
|
|
||||||
bool setCenter = current_element->text_location == UIElement::TextLocation::Center;
|
|
||||||
ImGui::Checkbox("Center Text", &setCenter);
|
|
||||||
|
|
||||||
current_element->text_location = setCenter ? UIElement::TextLocation::Center : UIElement::TextLocation::TopLeft;
|
|
||||||
|
|
||||||
if(ImGui::Button("Delete")) {
|
|
||||||
utility::erase(screen->elements, *current_element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::Button("Duplicate")) {
|
|
||||||
UIElement element = *current_element;
|
|
||||||
element.id += " (duplicate)";
|
|
||||||
|
|
||||||
screen->elements.push_back(element);
|
|
||||||
current_element = &screen->elements.back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
if(begin("Preview")) {
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
static int width = 1280, height = 720;
|
|
||||||
static int scale = 3;
|
|
||||||
|
|
||||||
bool c = ImGui::InputInt("Width", &width);
|
|
||||||
c |= ImGui::InputInt("Height", &height);
|
|
||||||
c |= ImGui::InputInt("Scale", &scale);
|
|
||||||
|
|
||||||
if(c) {
|
|
||||||
screen->extent.width = width;
|
|
||||||
screen->extent.height = height;
|
|
||||||
screen->calculate_sizes();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImVec2 p = ImGui::GetCursorScreenPos();
|
|
||||||
|
|
||||||
draw_list->AddRect(ImVec2(p.x, p.y), ImVec2(p.x + (width / scale), p.y + (height / scale)), IM_COL32_WHITE);
|
|
||||||
|
|
||||||
for(auto& element : screen->elements) {
|
|
||||||
if(element.absolute_width > 0 && element.absolute_height > 0) {
|
|
||||||
draw_list->AddRect(
|
|
||||||
ImVec2(p.x + (element.absolute_x / scale), p.y + (element.absolute_y / scale)),
|
|
||||||
ImVec2(p.x + ((element.absolute_x + element.absolute_width) / scale), p.y + ((element.absolute_y + element.absolute_height) / scale)),
|
|
||||||
IM_COL32_WHITE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!element.text.empty()) {
|
|
||||||
if(element.text_location == UIElement::TextLocation::Center) {
|
|
||||||
auto textSize = ImGui::CalcTextSize(element.text.c_str());
|
|
||||||
|
|
||||||
draw_list->AddText(ImVec2(p.x + (element.absolute_x + (element.absolute_width / 2)) / scale - (textSize.x / 2), p.y + (element.absolute_y + (element.absolute_height / 2)) / scale - (textSize.y / 2)), IM_COL32_WHITE, element.text.c_str());
|
|
||||||
} else {
|
|
||||||
draw_list->AddText(ImVec2(p.x + (element.absolute_x / scale), p.y + (element.absolute_y / scale)), IM_COL32_WHITE, element.text.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
Reference in a new issue