#include "debugdraw.hpp" #include "editor.hpp" #include "model.hpp" #include "scene.hpp" #include "ui.hpp" #include "world.hpp" extern "C" { #include "memory.h" } static struct { Editor_Settings settings; UI* ui; UI::Toolbar* toolbar; UI::Button* mat_btn, * ent_btn, * phy_btn; UI::Modal* mat_win, * ent_win, * phy_win; UI::Label* mat_name; UI::Slider* metalness_input; UI::Slider* roughness_input; UI::Slider* ao_input; UI::Label* ent_handle, * ent_index, * ent_version, * ent_mask; World* world; Entity_Id selected; Model_Instance* selected_inst; int selected_mesh; } editor; static int mat_win_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::destroy) { editor.mat_btn->enable(); editor.mat_win = 0; } return 0; } static void setup_mat_edit() { if (editor.selected_inst) { Mesh* meshes = editor.selected_inst->m->get_meshes(); Mesh& msh = meshes[editor.selected_mesh]; Material* mat = msh.material; editor.metalness_input->enable(); editor.metalness_input->input->set_val(mat->metalness); editor.roughness_input->enable(); editor.roughness_input->input->set_val(mat->roughness); editor.ao_input->enable(); editor.ao_input->input->set_val(mat->ao); editor.mat_name->set_text(mat->name); } else { editor.metalness_input->disable(); editor.roughness_input->disable(); editor.ao_input->disable(); editor.mat_name->set_text(""); } } void setup_ent_debug() { if (editor.selected) { int ind = entity_index(editor.selected); editor.ent_handle->set_hex(editor.selected); editor.ent_version->set_int(entity_version(editor.selected)); editor.ent_index->set_int(ind); editor.ent_mask->set_hex(editor.world->masks[ind]); } else { editor.ent_handle->set_text(""); editor.ent_version->set_text(""); editor.ent_index->set_text(""); editor.ent_mask->set_text(""); } } static int mat_btn_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::click) { editor.mat_win = editor.ui->create_element( editor.ui->root, "Material Editor" ); int rows[] = { 200, 250, 0 }; editor.mat_win->handler = mat_win_handler; editor.mat_btn->disable(); editor.mat_name = editor.ui->create_element( editor.mat_win->contents, "" ); auto container = editor.ui->create_element( editor.mat_win->contents, rows ); #define bind_mat_float(el, name, point) \ editor.ui->create_element( \ container, \ name \ ); \ el = editor.ui->create_element( \ container, \ 0.0f, \ 1.0f \ ); \ el->input->handler = []( \ UI::Element* e, \ const UI::Message& m \ ) { \ if ( \ m.type == UI::Message::Type::input_changed && \ editor.selected_inst \ ) { \ UI::Float_Input* in = (UI::Float_Input*)e; \ Mesh* meshes = editor.selected_inst->m->get_meshes(); \ Mesh& mesh = meshes[editor.selected_mesh]; \ Material* mat = mesh.material; \ mat->point = in->val; \ } \ return 0; \ }; bind_mat_float( editor.metalness_input, "Metalness", metalness ); bind_mat_float( editor.roughness_input, "Roughness", roughness ); bind_mat_float( editor.ao_input, "Ambient Occlusion", ao ); #undef bind_mat_float setup_mat_edit(); } return 0; } static int ent_win_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::destroy) { editor.ent_btn->enable(); editor.ent_win = 0; } return 0; } static int ent_btn_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::click) { auto ui = editor.ui; editor.ent_win = ui->create_element( editor.ui->root, "Entity Debugger" ); editor.ent_win->handler = ent_win_handler; editor.ent_btn->disable(); int rows[] = { 100, 50, 0 }; auto tab = ui->create_element( editor.ent_win->contents, rows ); ui->create_element(tab, "Handle"); editor.ent_handle = ui->create_element(tab, ""); ui->create_element(tab, "Index"); editor.ent_index = ui->create_element(tab, ""); ui->create_element(tab, "Version"); editor.ent_version = ui->create_element(tab, ""); ui->create_element(tab, "Mask"); editor.ent_mask = ui->create_element(tab, ""); setup_ent_debug(); } return 0; } static int phy_win_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::destroy) { editor.phy_btn->enable(); editor.phy_win = 0; } return 0; } static int phy_btn_handler(UI::Element* e, const UI::Message& m) { (void)e; if (m.type == UI::Message::Type::click) { auto ui = editor.ui; editor.phy_win = ui->create_element( editor.ui->root, "Physics Debugger" ); auto cont = editor.phy_win->contents; editor.phy_win->handler = phy_win_handler; editor.phy_btn->disable(); auto cdebug = ui->create_element(cont, "Debug Draw"); cdebug->handler = [](UI::Element* e, const UI::Message& m) { if (m.type == UI::Message::Type::checkbox_changed) { UI::Checkbox* ch = (UI::Checkbox*)e; editor.settings.debug_physics = ch->val; } return 0; }; cdebug->set_val(editor.settings.debug_physics); auto cpause = ui->create_element(cont, "Pause"); cpause->set_val(editor.settings.pause_physics); cpause->handler = [](UI::Element* e, const UI::Message& m) { if (m.type == UI::Message::Type::checkbox_changed) { UI::Checkbox* ch = (UI::Checkbox*)e; editor.settings.pause_physics = ch->val; } return 0; }; } return 0; } void init_editor(UI* ui, World* world) { editor.ui = ui; editor.toolbar = ui->create_element(ui->root); editor.mat_btn = ui->create_element( editor.toolbar, "Edit Material" ); editor.mat_btn->handler = mat_btn_handler; editor.ent_btn = ui->create_element( editor.toolbar, "Entity Debugger" ); editor.ent_btn->handler = ent_btn_handler; editor.phy_btn = ui->create_element( editor.toolbar, "Physics Debugger" ); editor.phy_btn->handler = phy_btn_handler; editor.mat_win = 0; editor.ent_win = 0; editor.phy_win = 0; editor.world = world; zero(&editor.settings, sizeof editor.settings); } void deinit_editor() { } void editor_on_select(Entity_Id e, int m) { if (!editor.ui->hovered) { editor.selected = e; if (e && editor.world->has(e)) { auto& cm = editor.world->get(e); editor.selected_inst = cm.i; editor.selected_mesh = m; } else { editor.selected_inst = 0; editor.selected_mesh = -1; } if (editor.mat_win) { setup_mat_edit(); } if (editor.ent_win) { setup_ent_debug(); } } } void editor_draw(Line_Renderer& lr) { if (editor.selected_inst) { lr.add_box( editor.selected_inst->bounds[editor.selected_mesh] ); } } Editor_Settings& editor_settings() { return editor.settings; }