Archived
1
Fork 0

Completely remove the defunct UI system

This commit is contained in:
redstrate 2021-09-13 23:10:26 -04:00
parent 648d2968d4
commit 626e314ec2
16 changed files with 4 additions and 939 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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"];
@ -105,9 +99,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;
@ -199,9 +184,6 @@ 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));

View file

@ -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) {
}

View file

@ -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);

View file

@ -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();
@ -404,9 +361,6 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
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;

View file

@ -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();
@ -639,9 +619,6 @@ 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));
} }

View file

@ -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(

View file

@ -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;
};

View file

@ -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();
} }

View file

@ -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", &current_element->id);
edit_metric("X", &current_element->metrics.x);
edit_metric("Y", &current_element->metrics.y);
edit_metric("Width", &current_element->metrics.width);
edit_metric("Height", &current_element->metrics.height);
ImGui::InputText("Text", &current_element->text);
ImGui::ColorEdit4("Background color", current_element->background.color.v);
ImGui::Checkbox("Visible", &current_element->visible);
ImGui::Checkbox("Wrap text", &current_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();
}