diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 6a8399d..2482791 100755 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,14 +1,14 @@ set(CMAKE_FOLDER "Tools") -if(NOT NEEDS_HOSTED_SHADER_COMPILER) +if (NOT NEEDS_HOSTED_SHADER_COMPILER) add_subdirectory(shadercompiler) -endif() +endif () -if(BUILD_TOOLS) +if (BUILD_TOOLS) add_subdirectory(common) add_subdirectory(assetpipeline) add_subdirectory(fontcompiler) add_subdirectory(editor) add_subdirectory(modelcompiler) add_subdirectory(cutsceneeditor) -endif() +endif () diff --git a/tools/assetpipeline/src/main.cpp b/tools/assetpipeline/src/main.cpp index 4bef7cb..76b1921 100644 --- a/tools/assetpipeline/src/main.cpp +++ b/tools/assetpipeline/src/main.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include int main(int argc, char* argv[]) { @@ -11,8 +11,8 @@ int main(int argc, char* argv[]) { std::string gameDirectory = argv[2]; fmt::print("Game directory to output compiled assets in: {}\n", gameDirectory); - for(auto const& dir_entry : std::filesystem::recursive_directory_iterator{dataDirectory}) { - if(dir_entry.path().extension() == ".fbx") { + for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{dataDirectory}) { + if (dir_entry.path().extension() == ".fbx") { fmt::print("Found fbx: {}\n", dir_entry.path().c_str()); @@ -22,7 +22,7 @@ int main(int argc, char* argv[]) { fmt::print("Equivalent file in the game directory: {}\n", new_game_path.c_str()); - if(!exists(new_game_path)) { + if (!exists(new_game_path)) { fmt::print("Compiled version does not exist!\n"); std::vector model_compiler_args; @@ -34,7 +34,7 @@ int main(int argc, char* argv[]) { model_compiler_args.emplace_back(new_game_path.c_str()); std::string compiled_command; - for(const auto& arg : model_compiler_args) { + for (const auto& arg : model_compiler_args) { compiled_command += arg + " "; } diff --git a/tools/common/CMakeLists.txt b/tools/common/CMakeLists.txt index 59e8219..50d414f 100755 --- a/tools/common/CMakeLists.txt +++ b/tools/common/CMakeLists.txt @@ -1,16 +1,16 @@ set(SRC - include/commoneditor.hpp - include/debugpass.hpp - include/undostack.hpp - - src/commoneditor.cpp - src/debugpass.cpp - src/undostack.cpp) + include/commoneditor.hpp + include/debugpass.hpp + include/undostack.hpp + + src/commoneditor.cpp + src/debugpass.cpp + src/undostack.cpp) add_library(EditorCommon ${SRC}) target_include_directories(EditorCommon PUBLIC include) target_link_libraries(EditorCommon PUBLIC - Renderer - imgui - Core) + Renderer + imgui + Core) set_engine_properties(EditorCommon) diff --git a/tools/common/include/commoneditor.hpp b/tools/common/include/commoneditor.hpp index 3f3e8cd..7600255 100755 --- a/tools/common/include/commoneditor.hpp +++ b/tools/common/include/commoneditor.hpp @@ -4,39 +4,39 @@ #include #include "app.hpp" +#include "assertions.hpp" +#include "asset.hpp" +#include "components.hpp" +#include "debugpass.hpp" +#include "engine.hpp" +#include "file.hpp" +#include "imgui_backend.hpp" +#include "log.hpp" +#include "math.hpp" +#include "object.hpp" +#include "platform.hpp" +#include "renderer.hpp" +#include "scene.hpp" +#include "undostack.hpp" #include "utility.hpp" #include -#include "math.hpp" -#include #include -#include "platform.hpp" -#include "file.hpp" -#include "object.hpp" -#include "undostack.hpp" -#include "components.hpp" -#include "engine.hpp" -#include "debugpass.hpp" -#include "assertions.hpp" -#include "log.hpp" -#include "asset.hpp" -#include "scene.hpp" -#include "renderer.hpp" -#include "imgui_backend.hpp" +#include class TransformCommand : public Command { public: prism::Object transformed; - + Transform old_transform, new_transform; - + std::string fetch_name() override { return "Transform " + engine->get_scene()->get(transformed).name; } - + void undo() override { engine->get_scene()->get(transformed) = old_transform; } - + void execute() override { engine->get_scene()->get(transformed) = new_transform; } @@ -45,17 +45,17 @@ public: class RenameCommand : public Command { public: prism::Object object; - + std::string old_name, new_name; - + std::string fetch_name() override { return "Rename " + old_name + " to " + new_name; } - + void undo() override { engine->get_scene()->get(object).name = old_name; } - + void execute() override { engine->get_scene()->get(object).name = new_name; } @@ -64,18 +64,19 @@ public: class ChangeParentCommand : public Command { public: prism::Object object; - + prism::Object old_parent; prism::Object new_parent; - + std::string fetch_name() override { - return "Change parent of " + engine->get_scene()->get(object).name + " to " + engine->get_scene()->get(new_parent).name; + return "Change parent of " + engine->get_scene()->get(object).name + " to " + + engine->get_scene()->get(new_parent).name; } - + void undo() override { engine->get_scene()->get(object).parent = old_parent; } - + void execute() override { engine->get_scene()->get(object).parent = new_parent; } @@ -89,18 +90,17 @@ enum class AssetType { Scene }; -template -AssetType get_asset_type() { - if constexpr(std::is_same::value) { +template AssetType get_asset_type() { + if constexpr (std::is_same::value) { return AssetType::Mesh; - } else if constexpr(std::is_same::value) { + } else if constexpr (std::is_same::value) { return AssetType::Material; - } else if constexpr(std::is_same::value) { + } else if constexpr (std::is_same::value) { return AssetType::Texture; - } else if constexpr(std::is_same::value) { + } else if constexpr (std::is_same::value) { return AssetType::Scene; } - + return AssetType::Unknown; } @@ -108,19 +108,19 @@ constexpr int thumbnail_resolution = 256; class CommonEditor : public prism::app { public: - explicit CommonEditor(std::string_view id); + explicit CommonEditor(std::string_view id); - void initialize_render() override; + void initialize_render() override; - void prepare_quit() override; + void prepare_quit() override; bool should_quit() override; - virtual void drawUI() {} + virtual void drawUI() {} - void begin_frame() override; + void begin_frame() override; void update(float deltaTime) override; - + virtual void renderEditor([[maybe_unused]] GFXCommandBuffer* command_buffer) {} void render(GFXCommandBuffer* command_buffer) override { @@ -130,150 +130,170 @@ public: virtual void updateEditor([[maybe_unused]] float deltaTime) {} virtual void object_selected([[maybe_unused]] prism::Object object) {} + virtual void asset_selected([[maybe_unused]] const std::filesystem::path& path, [[maybe_unused]] AssetType type) {} - bool wants_no_scene_rendering() override { return true; } - bool is_multimodal() override { return true; } + bool wants_no_scene_rendering() override { + return true; + } + + bool is_multimodal() override { + return true; + } void createDockArea(); void drawViewport(Scene* scene); void drawAssets(); - // options - int getDefaultX() const; - int getDefaultY() const; - int getDefaultWidth() const; - int getDefaultHeight() const; + // options + int getDefaultX() const; + int getDefaultY() const; + int getDefaultWidth() const; + int getDefaultHeight() const; - void addOpenedFile(std::string_view path); - void clearOpenedFiles(); - std::vector getOpenedFiles() const; + void addOpenedFile(std::string_view path); + void clearOpenedFiles(); + std::vector getOpenedFiles() const; void drawOutline(); void drawPropertyEditor(); void drawConsole(); - + void set_undo_stack(UndoStack* stack); prism::Object selected_object = prism::NullObject; - + GFXTexture* get_material_preview(Material& material); GFXTexture* get_mesh_preview(Mesh& mesh); GFXTexture* get_texture_preview(Texture& texture); GFXTexture* generate_common_preview(Scene& scene, prism::float3 camera_position); - template - GFXTexture* get_asset_thumbnail(AssetPtr& asset) { + template GFXTexture* get_asset_thumbnail(AssetPtr& asset) { Expects(asset.handle != nullptr); - - if(asset_thumbnails.count(asset->path)) { + + if (asset_thumbnails.count(asset->path)) { return asset_thumbnails[asset->path]; } else { - if constexpr(std::is_same_v) { + if constexpr (std::is_same_v) { auto texture = get_material_preview(*asset.handle); - + asset_thumbnails[asset->path] = texture; - + return texture; - } else if constexpr(std::is_same_v) { + } else if constexpr (std::is_same_v) { auto texture = get_mesh_preview(*asset.handle); - + asset_thumbnails[asset->path] = texture; - + return texture; - } else if constexpr(std::is_same_v) { + } else if constexpr (std::is_same_v) { auto texture = get_texture_preview(*asset.handle); - + asset_thumbnails[asset->path] = texture; - + return texture; } else { return engine->get_renderer()->dummy_texture; } } } - + GFXTexture* get_asset_thumbnail(const prism::path& path) { - if(asset_thumbnails.count(path.string())) { + if (asset_thumbnails.count(path.string())) { return asset_thumbnails[path.string()]; } else { auto [asset, block] = assetm->load_asset_generic(path); - + // store as dummy texture, as to stop infinite reload because of failure (e.g. out of date model) - if(asset == nullptr) { + if (asset == nullptr) { asset_thumbnails[path.string()] = engine->get_renderer()->dummy_texture; return engine->get_renderer()->dummy_texture; } - - if(can_load_asset(path)) { + + if (can_load_asset(path)) { auto ptr = AssetPtr(static_cast(asset), block); return get_asset_thumbnail(ptr); - } else if(can_load_asset(path)) { + } else if (can_load_asset(path)) { auto ptr = AssetPtr(static_cast(asset), block); - + return get_asset_thumbnail(ptr); - } else if(can_load_asset(path)) { + } else if (can_load_asset(path)) { auto ptr = AssetPtr(static_cast(asset), block); - + return get_asset_thumbnail(ptr); } else { return engine->get_renderer()->dummy_texture; } } } - + bool has_asset_edit_changed = false; - - template - bool edit_asset(const char* name, AssetPtr& asset) { + + template bool edit_asset(const char* name, AssetPtr& asset) { ImGui::PushID(&asset); - + auto draw_list = ImGui::GetWindowDrawList(); const auto window_pos = ImGui::GetCursorScreenPos(); - + const float thumbnail_size = 35.0f; const auto line_height = ImGui::GetTextLineHeight(); const float item_width = ImGui::CalcItemWidth(); const float inner_spacing = ImGui::GetStyle().ItemInnerSpacing.x; - + const auto frame_color = ImGui::GetStyle().Colors[ImGuiCol_FrameBg]; const auto text_color = ImGui::GetStyle().Colors[ImGuiCol_Text]; - const ImRect edit_rect = ImRect(window_pos, ImVec2(window_pos.x + thumbnail_size, window_pos.y + thumbnail_size)); - - if(asset) - draw_list->AddImageRounded(get_asset_thumbnail(asset), edit_rect.Min, edit_rect.Max, ImVec2(0, 0), ImVec2(1, 1), IM_COL32_WHITE, 3.0f); - - ImRect path_rect = ImRect(ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y), ImVec2(window_pos.x + item_width - inner_spacing, window_pos.y + 20.0f)); + const ImRect edit_rect = + ImRect(window_pos, ImVec2(window_pos.x + thumbnail_size, window_pos.y + thumbnail_size)); + + if (asset) + draw_list->AddImageRounded( + get_asset_thumbnail(asset), + edit_rect.Min, + edit_rect.Max, + ImVec2(0, 0), + ImVec2(1, 1), + IM_COL32_WHITE, + 3.0f); + + ImRect path_rect = ImRect( + ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y), + ImVec2(window_pos.x + item_width - inner_spacing, window_pos.y + 20.0f)); + + draw_list->AddText( + ImVec2(window_pos.x + item_width, window_pos.y + (thumbnail_size / 2.0f) - (line_height / 2.0f)), + ImColor(text_color), + name); - draw_list->AddText(ImVec2(window_pos.x + item_width, window_pos.y + (thumbnail_size / 2.0f) - (line_height / 2.0f)), ImColor(text_color), name); - draw_list->AddRectFilled(path_rect.Min, path_rect.Max, ImColor(frame_color), 3.0f); - - ImRect clear_rect = ImRect(ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y + 20.0f), ImVec2(window_pos.x + thumbnail_size + 30.0f, window_pos.y + 40.0f)); - + + ImRect clear_rect = ImRect( + ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y + 20.0f), + ImVec2(window_pos.x + thumbnail_size + 30.0f, window_pos.y + 40.0f)); + draw_list->AddRectFilled(clear_rect.Min, clear_rect.Max, ImColor(255, 0, 0, 255), 3.0f); - + std::string path; - if(asset) + if (asset) path = asset->path; else path = "None"; - + ImGui::PushClipRect(path_rect.Min, path_rect.Max, false); - draw_list->AddText(ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y), ImColor(text_color), path.c_str()); + draw_list->AddText( + ImVec2(window_pos.x + thumbnail_size + 10.0f, window_pos.y), ImColor(text_color), path.c_str()); ImGui::Dummy(ImVec2(thumbnail_size, thumbnail_size + 10.0f)); - + ImGui::ItemAdd(path_rect, ImGui::GetID("path")); - + ImGui::PopClipRect(); - if(ImGui::IsItemClicked()) { + if (ImGui::IsItemClicked()) { current_asset_type = get_asset_type(); open_asset_popup = true; on_asset_select = [&asset, this](auto p) { @@ -281,20 +301,20 @@ public: has_asset_edit_changed = true; }; } - + ImGui::ItemAdd(edit_rect, ImGui::GetID("edit")); - - if(ImGui::IsItemClicked()) + + if (ImGui::IsItemClicked()) asset_selected(asset->path, get_asset_type()); - + ImGui::ItemAdd(clear_rect, ImGui::GetID("clear")); - if(ImGui::IsItemClicked()) + if (ImGui::IsItemClicked()) asset.clear(); - + ImGui::PopID(); - - if(has_asset_edit_changed) { + + if (has_asset_edit_changed) { has_asset_edit_changed = false; return true; } else { @@ -302,63 +322,66 @@ public: } } - template - void open_asset(const AssetType type, const std::function& func_ptr) { + template void open_asset(const AssetType type, const std::function& func_ptr) { current_asset_type = type; open_asset_popup = true; on_asset_select = func_ptr; } - + DebugPass* debugPass = nullptr; int viewport_width = 1, viewport_height = 1; - + protected: struct ViewportRenderTarget { Scene* scene = nullptr; RenderTarget* target = nullptr; }; - + std::unordered_map viewport_render_targets; - + private: void load_options(); void save_options(); - + void load_thumbnail_cache(); void save_thumbnail_cache(); - - std::string id; + + std::string id; std::string iniFileName; - + std::unordered_map asset_thumbnails; - + bool accepting_viewport_input = false, doing_viewport_input = false; int viewport_x = 1, viewport_y = 1; - + bool transforming_axis = false; SelectableObject::Axis axis; prism::float3 last_object_position; - + bool open_asset_popup = false; AssetType current_asset_type; std::function on_asset_select; - + UndoStack* current_stack = nullptr; - int defaultX, defaultY, defaultWidth, defaultHeight; - std::vector lastOpenedFiles; + int defaultX, defaultY, defaultWidth, defaultHeight; + std::vector lastOpenedFiles; void walkObject(prism::Object object, prism::Object parentObject = prism::NullObject); - + void editTransform(prism::Object object, Transform transform); void editRenderable(Renderable& mesh); }; -inline void editPath(const char* label, std::string& path, bool editable = true, const std::function on_selected = nullptr) { +inline void editPath( + const char* label, + std::string& path, + bool editable = true, + const std::function on_selected = nullptr) { ImGui::PushID(label); - if(!editable) { + if (!editable) { ImGui::Text("%s: %s", label, path.c_str()); } else { ImGui::InputText(label, &path); @@ -366,11 +389,11 @@ inline void editPath(const char* label, std::string& path, bool editable = true, ImGui::SameLine(); - if(ImGui::Button("...")) { + if (ImGui::Button("...")) { engine->get_imgui().open_dialog(false, [&path, &on_selected](std::string p) { path = prism::get_relative_path(prism::domain::game, p).string(); - if(on_selected != nullptr) + if (on_selected != nullptr) on_selected(); }); } @@ -381,18 +404,18 @@ inline void editPath(const char* label, std::string& path, bool editable = true, class SelectionCommand : public Command { public: CommonEditor* editor = nullptr; - + prism::Object new_selection; prism::Object old_selection; - + std::string fetch_name() override { return "Change selection to " + engine->get_scene()->get(new_selection).name; } - + void undo() override { editor->selected_object = old_selection; } - + void execute() override { editor->selected_object = new_selection; } diff --git a/tools/common/include/debugpass.hpp b/tools/common/include/debugpass.hpp index 3fca93e..1f9d255 100755 --- a/tools/common/include/debugpass.hpp +++ b/tools/common/include/debugpass.hpp @@ -4,15 +4,15 @@ #include #include -#include "pass.hpp" -#include "gfx_renderpass.hpp" -#include "gfx_pipeline.hpp" -#include "gfx_texture.hpp" +#include "assetptr.hpp" #include "gfx_buffer.hpp" #include "gfx_framebuffer.hpp" +#include "gfx_pipeline.hpp" +#include "gfx_renderpass.hpp" +#include "gfx_texture.hpp" #include "matrix.hpp" #include "object.hpp" -#include "assetptr.hpp" +#include "pass.hpp" class Texture; class Mesh; @@ -22,22 +22,22 @@ struct SelectableObject { Object, Handle } type = Type::Object; - + Matrix4x4 axis_model; - + enum class Axis { X, Y, Z } axis = Axis::X; - + enum class RenderType { Mesh, Sphere } render_type = RenderType::Mesh; - + float sphere_size = 1.0f; - + prism::Object object = prism::NullObject; }; @@ -47,31 +47,31 @@ public: void create_render_target_resources(RenderTarget& target) override; - void render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) override; + void render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) override; void get_selected_object(int x, int y, const std::function& callback); void draw_arrow(GFXCommandBuffer* commandBuffer, prism::float3 color, Matrix4x4 model); - + GFXTexture* get_requested_texture(PassTextureType type) override { - if(type == PassTextureType::SelectionSobel) + if (type == PassTextureType::SelectionSobel) return sobelTexture; - + return nullptr; } - + GFXTexture* selectTexture = nullptr; GFXTexture* selectDepthTexture = nullptr; GFXTexture* sobelTexture = nullptr; prism::Object selected_object = prism::NullObject; - + private: void createOffscreenResources(); - + prism::Extent extent; - + std::vector selectable_objects; - + AssetPtr pointTexture, spotTexture, sunTexture, probeTexture; AssetPtr cubeMesh, arrowMesh, sphereMesh; @@ -83,7 +83,7 @@ private: GFXRenderPass* selectRenderPass = nullptr; GFXFramebuffer* selectFramebuffer = nullptr; GFXBuffer* selectBuffer = nullptr; - + GFXPipeline* sobelPipeline = nullptr; GFXFramebuffer* sobelFramebuffer = nullptr; GFXRenderPass* sobelRenderPass = nullptr; diff --git a/tools/common/include/undostack.hpp b/tools/common/include/undostack.hpp index c192876..99e28cc 100755 --- a/tools/common/include/undostack.hpp +++ b/tools/common/include/undostack.hpp @@ -1,53 +1,52 @@ #pragma once +#include #include #include -#include class Command { public: std::string stored_name; - + std::string get_name() { - if(stored_name.empty()) + if (stored_name.empty()) stored_name = fetch_name(); - + return stored_name; } - + virtual std::string fetch_name() = 0; - + virtual void undo() = 0; virtual void execute() = 0; }; class UndoStack { public: - template - T& new_command() { + template T& new_command() { // if we are in the middle of the stack currently, wipe out everything and start fresh // TODO: only do it up to the point we're modifing - if(stack_position != (command_stack.size() - 1)) { + if (stack_position != (command_stack.size() - 1)) { command_stack.clear(); stack_position = -1; } - + stack_position++; - + return static_cast(*command_stack.emplace_back(std::make_unique())); } - - //void push_command(Command* command); - + + // void push_command(Command* command); + void undo(); void redo(); - + // useful for undo Command* get_last_command(); - + // useful for redo Command* get_next_command(); - + std::vector> command_stack; int stack_position = -1; }; diff --git a/tools/common/src/commoneditor.cpp b/tools/common/src/commoneditor.cpp index 31b825b..21fc7b0 100755 --- a/tools/common/src/commoneditor.cpp +++ b/tools/common/src/commoneditor.cpp @@ -1,22 +1,22 @@ #include "commoneditor.hpp" -#include -#include -#include -#include #include +#include +#include +#include +#include #include "engine.hpp" #include "file.hpp" -#include "platform.hpp" -#include "transform.hpp" -#include "log.hpp" -#include "shadowpass.hpp" #include "gfx.hpp" #include "gfx_commandbuffer.hpp" #include "imgui_utility.hpp" #include "input.hpp" +#include "log.hpp" +#include "platform.hpp" #include "scenecapture.hpp" +#include "shadowpass.hpp" +#include "transform.hpp" const std::map imToPl = { {ImGuiKey_Tab, InputButton::Tab}, @@ -39,39 +39,38 @@ const std::map imToPl = { {ImGuiKey_V, InputButton::V}, {ImGuiKey_X, InputButton::X}, {ImGuiKey_Y, InputButton::Y}, - {ImGuiKey_Z, InputButton::Z} -}; + {ImGuiKey_Z, InputButton::Z}}; CommonEditor::CommonEditor(const std::string_view id) : id(id) { ImGuiIO& io = ImGui::GetIO(); - + iniFileName = (prism::get_writeable_directory() / "imgui.ini").string(); - + io.IniFilename = iniFileName.c_str(); - + ImGui::LoadIniSettingsFromDisk(io.IniFilename); - + load_options(); - + auto input = engine->get_input(); input->add_binding("movementX"); input->add_binding("movementY"); - + input->add_binding_button("movementX", InputButton::A, -1.0f); input->add_binding_button("movementX", InputButton::D, 1.0f); - + input->add_binding_button("movementY", InputButton::W, -1.0f); input->add_binding_button("movementY", InputButton::S, 1.0f); - + input->add_binding("lookX"); input->add_binding("lookY"); - + input->add_binding_axis("lookX", prism::axis::MouseX); input->add_binding_axis("lookY", prism::axis::MouseY); - + input->add_binding("cameraLook"); input->add_binding_button("cameraLook", InputButton::MouseRight); - + input->add_binding("cameraSelect"); input->add_binding_button("cameraSelect", InputButton::MouseLeft); } @@ -87,48 +86,51 @@ static bool willCaptureMouse = false; static float previous_intersect = 0.0; void CommonEditor::update(float deltaTime) { - if(engine->get_scene() != nullptr) { + if (engine->get_scene() != nullptr) { prism::float3 offset; - + willCaptureMouse = engine->get_input()->is_repeating("cameraLook") && accepting_viewport_input; - + platform::capture_mouse(willCaptureMouse); - - if(willCaptureMouse) { - if(engine->get_scene() != nullptr && !engine->get_scene()->get_all().empty()) { + + if (willCaptureMouse) { + if (engine->get_scene() != nullptr && !engine->get_scene()->get_all().empty()) { yaw += engine->get_input()->get_value("lookX") * 50.0f * deltaTime; pitch += engine->get_input()->get_value("lookY") * 50.0f * deltaTime; - + const float speed = 7.00f; prism::float3 forward, right; - forward = normalize(angle_axis(yaw, prism::float3(0, 1, 0)) * angle_axis(pitch, prism::float3(1, 0, 0)) * prism::float3(0, 0, 1)); + forward = normalize( + angle_axis(yaw, prism::float3(0, 1, 0)) * angle_axis(pitch, prism::float3(1, 0, 0)) * + prism::float3(0, 0, 1)); right = normalize(angle_axis(yaw, prism::float3(0, 1, 0)) * prism::float3(1, 0, 0)); - + float movX = engine->get_input()->get_value("movementX"); float movY = engine->get_input()->get_value("movementY"); - + auto [obj, cam] = engine->get_scene()->get_all()[0]; - + engine->get_scene()->get(obj).position += right * movX * speed * deltaTime; engine->get_scene()->get(obj).position += forward * -movY * speed * deltaTime; - - engine->get_scene()->get(obj).rotation = angle_axis(yaw, prism::float3(0, 1, 0)) * angle_axis(pitch, prism::float3(1, 0, 0)); + + engine->get_scene()->get(obj).rotation = + angle_axis(yaw, prism::float3(0, 1, 0)) * angle_axis(pitch, prism::float3(1, 0, 0)); } } - + doing_viewport_input = willCaptureMouse; - - if(debugPass != nullptr) { - if(engine->get_input()->is_pressed("cameraSelect") && accepting_viewport_input && !transforming_axis) { + + if (debugPass != nullptr) { + if (engine->get_input()->is_pressed("cameraSelect") && accepting_viewport_input && !transforming_axis) { debugPass->get_selected_object(viewport_x, viewport_y, [this](SelectableObject object) { - if(object.object == prism::NullObject) { + if (object.object == prism::NullObject) { object_selected(prism::NullObject); return; } - - if(object.type == SelectableObject::Type::Handle) { + + if (object.type == SelectableObject::Type::Handle) { transforming_axis = true; axis = object.axis; previous_intersect = 0.0; @@ -138,23 +140,24 @@ void CommonEditor::update(float deltaTime) { } }); } - - if(transforming_axis) { - if(!engine->get_input()->is_pressed("cameraSelect", true)) + + if (transforming_axis) { + if (!engine->get_input()->is_pressed("cameraSelect", true)) transforming_axis = false; - + auto [obj, cam] = engine->get_scene()->get_all()[0]; - + const auto width = viewport_width; const auto height = viewport_height; - prism::float2 n = prism::float2(((viewport_x / (float)width) * 2) - 1, - ((viewport_y / (float)height) * 2) - 1); // [-1, 1] mouse coordinates + prism::float2 n = prism::float2( + ((viewport_x / (float)width) * 2) - 1, + ((viewport_y / (float)height) * 2) - 1); // [-1, 1] mouse coordinates n.y = -n.y; - + n.x = std::clamp(n.x, -1.0f, 1.0f); n.y = std::clamp(n.y, -1.0f, 1.0f); - + const Matrix4x4 view_proj_inverse = inverse(cam.perspective * cam.view); prism::float4 ray_start = view_proj_inverse * prism::float4(n.x, n.y, 0.0f, 1.0f); @@ -162,19 +165,19 @@ void CommonEditor::update(float deltaTime) { prism::float4 ray_end = view_proj_inverse * prism::float4(n.x, n.y, 1.0f, 1.0f); ray_end *= 1.0f / ray_end.w; - + prism::ray camera_ray; camera_ray.origin = ray_start.xyz; camera_ray.direction = normalize(ray_end.xyz - ray_start.xyz); camera_ray.t = std::numeric_limits::max(); - + auto& transform = engine->get_scene()->get(selected_object); - + prism::ray transform_ray; transform_ray.origin = last_object_position; transform_ray.t = std::numeric_limits::max(); - - switch(axis) { + + switch (axis) { case SelectableObject::Axis::X: transform_ray.direction = prism::float3(1, 0, 0); break; @@ -185,18 +188,18 @@ void CommonEditor::update(float deltaTime) { transform_ray.direction = prism::float3(0, 0, 1); break; } - + prism::closest_distance_between_lines(camera_ray, transform_ray); - + const float current_intersect = transform_ray.t; - if(previous_intersect == 0.0) + if (previous_intersect == 0.0) previous_intersect = current_intersect; - + const float delta = current_intersect - previous_intersect; - + previous_intersect = current_intersect; - - switch(axis) { + + switch (axis) { case SelectableObject::Axis::X: transform.position.x -= delta; break; @@ -210,15 +213,15 @@ void CommonEditor::update(float deltaTime) { } } } - + updateEditor(deltaTime); } void CommonEditor::prepare_quit() { save_options(); - + ImGui::SaveIniSettingsToDisk(iniFileName.c_str()); - + save_thumbnail_cache(); } @@ -232,26 +235,26 @@ std::map asset_files; void cacheAssetFilesystem(); -void CommonEditor::begin_frame() { +void CommonEditor::begin_frame() { drawUI(); - - if(open_asset_popup) { + + if (open_asset_popup) { ImGui::OpenPopup("Select Asset"); open_asset_popup = false; } - - if(ImGui::BeginPopupModal("Select Asset", nullptr, ImGuiWindowFlags_NoMove)) { - if(!filesystem_cached) + + if (ImGui::BeginPopupModal("Select Asset", nullptr, ImGuiWindowFlags_NoMove)) { + if (!filesystem_cached) cacheAssetFilesystem(); - + ImGui::SetWindowSize(ImVec2(500, 500)); - + ImGui::BeginChild("assetbox", ImVec2(-1, 400), true); - + int column = 0; - for(auto& [p, a_type] : asset_files) { - if(current_asset_type == a_type) { - if(ImGui::ImageButton(get_asset_thumbnail(prism::game_domain / p), ImVec2(64, 64))) { + for (auto& [p, a_type] : asset_files) { + if (current_asset_type == a_type) { + if (ImGui::ImageButton(get_asset_thumbnail(prism::game_domain / p), ImVec2(64, 64))) { on_asset_select(p); ImGui::CloseCurrentPopup(); } @@ -263,19 +266,19 @@ void CommonEditor::begin_frame() { } column++; - - if(column != 5) + + if (column != 5) ImGui::SameLine(); else column = 0; } } - + ImGui::EndChild(); - - if(ImGui::Button("Cancel")) + + if (ImGui::Button("Cancel")) ImGui::CloseCurrentPopup(); - + ImGui::EndPopup(); } } @@ -309,67 +312,68 @@ std::vector CommonEditor::getOpenedFiles() const { } void CommonEditor::walkObject(prism::Object object, prism::Object) { - static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; - + static ImGuiTreeNodeFlags base_flags = + ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; + auto& data = engine->get_scene()->get(object); - if(data.editor_object) + if (data.editor_object) return; - + const auto text_color = ImGui::GetStyle().Colors[ImGuiCol_Text]; const auto active_color = ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]; - + ImGui::PushStyleColor(ImGuiCol_Text, selected_object == object ? active_color : text_color); - + bool is_open = ImGui::TreeNodeEx((void*)object, base_flags, "%s", data.name.c_str()); - - if(ImGui::IsItemClicked()) { - if(current_stack != nullptr) { + + if (ImGui::IsItemClicked()) { + if (current_stack != nullptr) { auto& command = current_stack->new_command(); command.editor = this; command.old_selection = selected_object; command.new_selection = object; } - + selected_object = object; } - + if (ImGui::BeginPopupContextItem()) { - if(ImGui::Button("Delete")) { + if (ImGui::Button("Delete")) { engine->get_scene()->remove_object(object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Button("Duplicate")) { + + if (ImGui::Button("Duplicate")) { prism::Object obj = engine->get_scene()->duplicate_object(object); engine->get_scene()->get(obj).name += "duplicate"; - + selected_object = obj; - + ImGui::CloseCurrentPopup(); } - + ImGui::EndPopup(); } - - if(is_open) { - for(auto& child : engine->get_scene()->children_of(object)) + + if (is_open) { + for (auto& child : engine->get_scene()->children_of(object)) walkObject(child); - + ImGui::TreePop(); } - + ImGui::PopStyleColor(); } void CommonEditor::drawOutline() { - if(engine->get_scene() != nullptr) { + if (engine->get_scene() != nullptr) { ImGui::BeginChild("outlineinner", ImVec2(-1, -1), true); - - for(auto& object : engine->get_scene()->get_objects()) { - if(engine->get_scene()->get(object).parent == prism::NullObject) + + for (auto& object : engine->get_scene()->get_objects()) { + if (engine->get_scene()->get(object).parent == prism::NullObject) walkObject(object); } - + ImGui::EndChild(); } else { ImGui::TextDisabled("No scene loaded."); @@ -381,9 +385,9 @@ Transform stored_transform; bool IsItemActiveLastFrame() { ImGuiContext& g = *GImGui; // TODO: uh oh this is broken now :-( - //if (g.ActiveIdPreviousFrame) + // if (g.ActiveIdPreviousFrame) // return g.ActiveIdPreviousFrame == g.CurrentWindow->DC.LastItemId; - + return false; } @@ -399,13 +403,13 @@ void CommonEditor::editTransform(prism::Object object, Transform transform) { changed |= ImGui::DragFloat3("Scale", transform.scale.ptr()); is_done_editing |= ImGui::IsItemDeactivatedAfterEdit(); started_edit |= ImGui::IsItemActive() && !IsItemActiveLastFrame(); - + if (started_edit) stored_transform = transform; - - if(changed) + + if (changed) engine->get_scene()->get(object) = transform; - + if (is_done_editing && current_stack != nullptr) { auto& command = current_stack->new_command(); command.transformed = object; @@ -416,26 +420,26 @@ void CommonEditor::editTransform(prism::Object object, Transform transform) { void CommonEditor::editRenderable(Renderable& mesh) { edit_asset("Mesh", mesh.mesh); - - for(auto [i, material] : utility::enumerate(mesh.materials)) { + + for (auto [i, material] : utility::enumerate(mesh.materials)) { std::string str = "Material " + std::to_string(i); edit_asset(str.c_str(), material); } - - if(ImGui::Button("Add material")) + + if (ImGui::Button("Add material")) mesh.materials.emplace_back(); } void editLight(Light& light) { ImGui::ColorEdit3("Color", light.color.ptr()); - + ImGui::ComboEnum("Type", &light.type); ImGui::DragFloat("Size", &light.size, 0.1f, 0.0f, 1000.0f); ImGui::DragFloat("Power", &light.power, 0.5f, 0.0f, 100.0f); - - if(light.type == Light::Type::Spot) + + if (light.type == Light::Type::Spot) ImGui::DragFloat("Spot Size", &light.spot_size, 0.5f, 40.0f, 56.0f); - + ImGui::Checkbox("Enable shadows", &light.enable_shadows); ImGui::Checkbox("Use dynamic shadows", &light.use_dynamic_shadows); } @@ -446,10 +450,10 @@ void editCamera(Camera& camera) { void editCollision(Collision& collision) { ImGui::DragFloat3("Size", collision.size.ptr()); - + ImGui::Checkbox("Is Trigger", &collision.is_trigger); - - if(collision.is_trigger) + + if (collision.is_trigger) ImGui::InputText("Trigger ID", &collision.trigger_id); } @@ -459,166 +463,172 @@ void editRigidbody(Rigidbody& rigidbody) { void editProbe(EnvironmentProbe& probe) { ImGui::Checkbox("Is Sized", &probe.is_sized); - if(probe.is_sized) + if (probe.is_sized) ImGui::DragFloat3("Size", probe.size.ptr()); - + ImGui::SliderFloat("Intensity", &probe.intensity, 0.0f, 1.0f); } template bool componentHeader(Scene& scene, prism::Object& object, const char* name, const bool removable = true) { - if(!scene.has(object)) + if (!scene.has(object)) return false; - + const auto draw_list = ImGui::GetWindowDrawList(); const auto window_pos = ImGui::GetCursorScreenPos(); const auto window_size = ImGui::GetWindowSize(); const auto state_store = ImGui::GetStateStorage(); - + auto is_open = state_store->GetBoolRef(ImGui::GetID((std::string(name) + "_open").c_str()), true); - if(is_open == nullptr) + if (is_open == nullptr) return false; - + const auto window_padding = ImGui::GetStyle().WindowPadding; const auto frame_padding = ImGui::GetStyle().FramePadding; const auto widget_color = ImGui::GetStyle().Colors[ImGuiCol_Button]; const auto text_color = ImGui::GetStyle().Colors[ImGuiCol_Text]; - + const auto header_start = window_pos; const auto header_end = ImVec2(window_pos.x + window_size.x - (window_padding.x * 2), window_pos.y + 25); - + const auto button_size = removable ? 25 : 0; - + const auto line_height = ImGui::GetTextLineHeight(); - + draw_list->AddRectFilled(header_start, header_end, ImColor(widget_color), 5.0f); - draw_list->AddText(ImVec2(header_start.x + frame_padding.x, header_start.y + (25.0f / 2.0f) - (line_height / 2.0f)), ImColor(text_color), name); - + draw_list->AddText( + ImVec2(header_start.x + frame_padding.x, header_start.y + (25.0f / 2.0f) - (line_height / 2.0f)), + ImColor(text_color), + name); + ImGui::Dummy(ImVec2(window_size.x - window_pos.x, 25)); - + ImGui::ItemAdd(ImRect(header_start, ImVec2(header_end.x - button_size, header_end.y)), ImGui::GetID(name)); - + if (ImGui::IsItemClicked()) { *is_open = !(*is_open); } - - if(removable) { - draw_list->AddText(ImVec2(header_end.x - (button_size / 2.0f), header_start.y + (25.0f / 2.0f) - (line_height / 2.0f)), ImColor(text_color), "X"); - + + if (removable) { + draw_list->AddText( + ImVec2(header_end.x - (button_size / 2.0f), header_start.y + (25.0f / 2.0f) - (line_height / 2.0f)), + ImColor(text_color), + "X"); + ImGui::ItemAdd(ImRect(ImVec2(header_end.x - button_size, header_start.y), header_end), ImGui::GetID(name)); - + if (ImGui::IsItemClicked()) { // remove engine->get_scene()->remove(object); return false; } } - + return *is_open; } void CommonEditor::drawPropertyEditor() { auto scene = engine->get_scene(); - if(scene != nullptr) { - if(selected_object != prism::NullObject) { - if(!scene->has(selected_object)) { + if (scene != nullptr) { + if (selected_object != prism::NullObject) { + if (!scene->has(selected_object)) { selected_object = prism::NullObject; return; } - - if(scene->is_object_prefab(selected_object)) { + + if (scene->is_object_prefab(selected_object)) { ImGui::TextDisabled("Cannot edit prefab, so certain data is uneditable."); } else { auto& data = scene->get(selected_object); - + ImGui::InputText("Name", &data.name); - + static std::string stored_name; - if(ImGui::IsItemActive() && !IsItemActiveLastFrame()) + if (ImGui::IsItemActive() && !IsItemActiveLastFrame()) stored_name = data.name; - - if(ImGui::IsItemDeactivatedAfterEdit() && current_stack != nullptr) { + + if (ImGui::IsItemDeactivatedAfterEdit() && current_stack != nullptr) { auto& command = current_stack->new_command(); command.object = selected_object; command.new_name = data.name; command.old_name = stored_name; } - + std::string preview_value = data.parent == prism::NullObject ? "None" : scene->get(data.parent).name; - if(ImGui::BeginCombo("Parent", preview_value.c_str())) { + if (ImGui::BeginCombo("Parent", preview_value.c_str())) { for (auto& object : scene->get_objects()) { // dont allow selecting a node to be the parent of itself if (object == selected_object) continue; - + if (ImGui::Selectable(scene->get(object).name.c_str(), data.parent == object)) data.parent = object; } - + ImGui::Separator(); - + if (ImGui::Selectable("None", data.parent == prism::NullObject)) data.parent = prism::NullObject; - + ImGui::EndCombo(); } - + if (ImGui::Button("Add Component...")) ImGui::OpenPopup("add_popup"); - + if (ImGui::BeginPopup("add_popup")) { - if(ImGui::Selectable("Renderable")) { + if (ImGui::Selectable("Renderable")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Selectable("Light")) { + + if (ImGui::Selectable("Light")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Selectable("Camera")) { + + if (ImGui::Selectable("Camera")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Selectable("Collision")) { + + if (ImGui::Selectable("Collision")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Selectable("Rigidbody")) { + + if (ImGui::Selectable("Rigidbody")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - - if(ImGui::Selectable("Environment Probe")) { + + if (ImGui::Selectable("Environment Probe")) { scene->add(selected_object); ImGui::CloseCurrentPopup(); } - + ImGui::EndPopup(); } - - if(componentHeader(*scene, selected_object, "Transform", false)) + + if (componentHeader(*scene, selected_object, "Transform", false)) editTransform(selected_object, scene->get(selected_object)); - - if(componentHeader(*scene, selected_object, "Renderable")) + + if (componentHeader(*scene, selected_object, "Renderable")) editRenderable(scene->get(selected_object)); - - if(componentHeader(*scene, selected_object, "Light")) + + if (componentHeader(*scene, selected_object, "Light")) editLight(scene->get(selected_object)); - - if(componentHeader(*scene, selected_object, "Camera")) + + if (componentHeader(*scene, selected_object, "Camera")) editCamera(scene->get(selected_object)); - - if(componentHeader(*scene, selected_object, "Collision")) + + if (componentHeader(*scene, selected_object, "Collision")) editCollision(scene->get(selected_object)); - - if(componentHeader(*scene, selected_object, "Rigidbody")) + + if (componentHeader(*scene, selected_object, "Rigidbody")) editRigidbody(scene->get(selected_object)); - if(componentHeader(*scene, selected_object, "Environment Probe")) + if (componentHeader(*scene, selected_object, "Environment Probe")) editProbe(scene->get(selected_object)); } } else { @@ -636,168 +646,167 @@ void CommonEditor::createDockArea() { ImGui::SetNextWindowViewport(viewport->ID); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - + ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking | - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus; - + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::Begin("dockspace", nullptr, window_flags); ImGui::PopStyleVar(); ImGui::PopStyleVar(2); - + ImGuiID dockspace_id = ImGui::GetID("dockspace"); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode); } void CommonEditor::drawViewport(Scene* scene) { const auto size = ImGui::GetContentRegionAvail(); - const auto real_size = ImVec2(static_cast(size.x * platform::get_monitor_dpi()), static_cast(size.y * platform::get_monitor_dpi())); - - if(real_size.x <= 0 || real_size.y <= 0) + const auto real_size = ImVec2( + static_cast(size.x * platform::get_monitor_dpi()), static_cast(size.y * platform::get_monitor_dpi())); + + if (real_size.x <= 0 || real_size.y <= 0) return; - + auto window = ImGui::GetCurrentWindowRead(); auto window_id = window->ID; - - if(!viewport_render_targets.count(window_id)) { + + if (!viewport_render_targets.count(window_id)) { ViewportRenderTarget new_target; new_target.target = engine->get_renderer()->allocate_render_target(real_size); - + viewport_render_targets[window_id] = new_target; } - + auto target = &viewport_render_targets[window_id]; - - if(real_size.x != target->target->extent.width || real_size.y != target->target->extent.height) + + if (real_size.x != target->target->extent.width || real_size.y != target->target->extent.height) engine->get_renderer()->resize_render_target(*target->target, real_size); - + target->scene = scene; - + viewport_width = size.x; viewport_height = size.y; - + const auto mouse_pos = ImGui::GetMousePos(); const auto real_pos = ImGui::GetCursorScreenPos(); - + viewport_x = mouse_pos.x - real_pos.x; viewport_y = mouse_pos.y - real_pos.y; - + ImGui::Image((ImTextureID)target->target->offscreenColorTexture, size); - + accepting_viewport_input = ImGui::IsWindowHovered(); - - if(doing_viewport_input) + + if (doing_viewport_input) ImGui::SetWindowFocus(); } -void CommonEditor::set_undo_stack(UndoStack *stack) { +void CommonEditor::set_undo_stack(UndoStack* stack) { current_stack = stack; } bool mesh_readable(const prism::path& path) { auto file = prism::open_file(path); - if(!file.has_value()) { + if (!file.has_value()) { prism::log("Failed to load mesh from {}!", path.string()); return false; } - + int version = 0; file->read(&version); - + return version == 5 || version == 6; } bool material_readable(const prism::path& path) { auto file = prism::open_file(path); - if(!file.has_value()) { + if (!file.has_value()) { prism::log("Failed to load material from {}!", path.string()); return false; } - + nlohmann::json j; file->read_as_stream() >> j; - + return j.count("version") && j["version"] == 2; } void cacheAssetFilesystem() { asset_files.clear(); - + auto data_directory = "data"; - if(!std::filesystem::exists(data_directory)) + if (!std::filesystem::exists(data_directory)) return; - for(auto& p : std::filesystem::recursive_directory_iterator(data_directory)) { - if(p.path().extension() == ".model" && mesh_readable(p.path())) { + for (auto& p : std::filesystem::recursive_directory_iterator(data_directory)) { + if (p.path().extension() == ".model" && mesh_readable(p.path())) { asset_files[std::filesystem::relative(p, data_directory)] = AssetType::Mesh; - } else if(p.path().extension() == ".material" && material_readable(p.path())) { + } else if (p.path().extension() == ".material" && material_readable(p.path())) { asset_files[std::filesystem::relative(p, data_directory)] = AssetType::Material; - } else if(p.path().extension() == ".png") { + } else if (p.path().extension() == ".png") { asset_files[std::filesystem::relative(p, data_directory)] = AssetType::Texture; - } else if(p.path().extension() == ".scene") { + } else if (p.path().extension() == ".scene") { asset_files[std::filesystem::relative(p, data_directory)] = AssetType::Scene; } } - + filesystem_cached = true; } void CommonEditor::drawAssets() { - if(!filesystem_cached) + if (!filesystem_cached) cacheAssetFilesystem(); - + const float window_width = ImGui::GetWindowWidth(); const float item_spacing = ImGui::GetStyle().ItemSpacing.x; const float frame_padding = ImGui::GetStyle().FramePadding.x; const float window_padding = ImGui::GetStyle().WindowPadding.x; - + const float column_width = 64.0f + item_spacing + (frame_padding * 2.0f); - + const int max_columns = std::floor((window_width - window_padding) / column_width); - + int column = 0; - for(auto& [p, type] : asset_files) { + for (auto& [p, type] : asset_files) { ImGui::PushID(&p); - - if(ImGui::ImageButton(get_asset_thumbnail(prism::game_domain / p), ImVec2(64, 64))) + + if (ImGui::ImageButton(get_asset_thumbnail(prism::game_domain / p), ImVec2(64, 64))) asset_selected(prism::game_domain / p, type); - if(ImGui::BeginPopupContextItem()) { + if (ImGui::BeginPopupContextItem()) { ImGui::TextDisabled("%s", p.string().c_str()); ImGui::Separator(); - if(ImGui::Button("Regenerate thumbnail")) { + if (ImGui::Button("Regenerate thumbnail")) { asset_thumbnails.erase(asset_thumbnails.find((prism::game_domain / p).string())); } ImGui::EndPopup(); } - + column++; - - if(column >= max_columns) { + + if (column >= max_columns) { column = 0; } else { ImGui::SameLine(); } - + ImGui::PopID(); } } GFXTexture* CommonEditor::get_material_preview(Material& material) { Scene scene; - + auto sphere = scene.add_object(); scene.add(sphere).mesh = assetm->get(prism::base_domain / "models" / "sphere.model"); - scene.get(sphere).materials.push_back(assetm->get(prism::game_domain / material.path)); // we throw away our material handle here :-( - + scene.get(sphere).materials.push_back( + assetm->get(prism::game_domain / material.path)); // we throw away our material handle here :-( + scene.get(sphere).rotation = euler_to_quat(prism::float3(radians(90.0f), 0, 0)); return generate_common_preview(scene, prism::float3(0, 0, 3)); @@ -805,204 +814,216 @@ GFXTexture* CommonEditor::get_material_preview(Material& material) { GFXTexture* CommonEditor::get_mesh_preview(Mesh& mesh) { Scene scene; - + auto mesh_obj = scene.add_object(); scene.add(mesh_obj).mesh = assetm->get(prism::game_domain / mesh.path); - + float biggest_component = 0.0f; - for(const auto& part : scene.get(mesh_obj).mesh->parts) { + for (const auto& part : scene.get(mesh_obj).mesh->parts) { const auto find_biggest_component = [&biggest_component](const prism::float3 vec) { - for(auto& component : vec.data) { - if(std::fabs(component) > biggest_component) + for (auto& component : vec.data) { + if (std::fabs(component) > biggest_component) biggest_component = component; } }; - + find_biggest_component(part.bounding_box.min); find_biggest_component(part.bounding_box.max); - - scene.get(mesh_obj).materials.push_back(assetm->get(prism::game_domain / "materials" / "Material.material")); + + scene.get(mesh_obj).materials.push_back( + assetm->get(prism::game_domain / "materials" / "Material.material")); } - + return generate_common_preview(scene, prism::float3(biggest_component * 2.0f)); } GFXTexture* CommonEditor::get_texture_preview(Texture& texture) { auto gfx = engine->get_gfx(); - + GFXTextureCreateInfo texture_create_info = {}; texture_create_info.label = "Preview of " + texture.path; texture_create_info.width = thumbnail_resolution; texture_create_info.height = thumbnail_resolution; texture_create_info.format = GFXPixelFormat::RGBA8_UNORM; texture_create_info.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled; - + auto final_texture = gfx->create_texture(texture_create_info); - + GFXFramebufferCreateInfo framebuffer_create_info = {}; framebuffer_create_info.attachments = {final_texture}; framebuffer_create_info.render_pass = engine->get_renderer()->unorm_render_pass; - + auto final_framebuffer = gfx->create_framebuffer(framebuffer_create_info); - + auto renderer = engine->get_renderer(); GFXCommandBuffer* command_buffer = gfx->acquire_command_buffer(false); - + GFXRenderPassBeginInfo begin_info = {}; begin_info.render_area.extent = {thumbnail_resolution, thumbnail_resolution}; begin_info.framebuffer = final_framebuffer; begin_info.render_pass = renderer->unorm_render_pass; - + command_buffer->set_render_pass(begin_info); - + Viewport viewport = {}; viewport.width = thumbnail_resolution; viewport.height = thumbnail_resolution; - + command_buffer->set_viewport(viewport); - + command_buffer->set_graphics_pipeline(renderer->render_to_unorm_texture_pipeline); - + command_buffer->bind_texture(texture.handle, 1); command_buffer->bind_texture(renderer->dummy_texture, 2); command_buffer->bind_texture(renderer->dummy_texture, 3); command_buffer->bind_texture(renderer->dummy_texture, 4); - + struct PostPushConstants { prism::float4 viewport; prism::float4 options; } pc; + pc.options.w = 1.0; - pc.viewport = prism::float4(1.0 / (float)thumbnail_resolution, 1.0 / (float)thumbnail_resolution, thumbnail_resolution, thumbnail_resolution); - + pc.viewport = prism::float4( + 1.0 / (float)thumbnail_resolution, + 1.0 / (float)thumbnail_resolution, + thumbnail_resolution, + thumbnail_resolution); + command_buffer->set_push_constant(&pc, sizeof(PostPushConstants)); - + command_buffer->draw(0, 4, 0, 1); - + gfx->submit(command_buffer, nullptr); - + return final_texture; } GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const prism::float3 camera_position) { auto gfx = engine->get_gfx(); - + // setup scene scene.reset_environment(); scene.reset_shadows(); - + auto camera = scene.add_object(); scene.add(camera); - + camera_look_at(scene, camera, camera_position, prism::float3(0)); - + auto light = scene.add_object(); scene.get(light).position = prism::float3(5); scene.add(light).type = Light::Type::Sun; - + auto probe = scene.add_object(); scene.add(probe).is_sized = false; scene.get(probe).position = prism::float3(3); - + engine->update_scene(scene); - + scene.get(camera).perspective = prism::infinite_perspective(radians(45.0f), 1.0f, 0.1f); scene.get(camera).view = inverse(scene.get(camera).model); - + auto renderer = engine->get_renderer(); - + RenderTarget* target = renderer->allocate_render_target({thumbnail_resolution, thumbnail_resolution}); - + renderer->shadow_pass->create_scene_resources(scene); renderer->scene_capture->create_scene_resources(scene); - + // setup render GFXTextureCreateInfo texture_create_info = {}; texture_create_info.width = thumbnail_resolution; texture_create_info.height = thumbnail_resolution; texture_create_info.format = GFXPixelFormat::RGBA8_UNORM; texture_create_info.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst; - + auto final_texture = gfx->create_texture(texture_create_info); - + texture_create_info = {}; texture_create_info.width = thumbnail_resolution; texture_create_info.height = thumbnail_resolution; texture_create_info.format = GFXPixelFormat::RGBA_32F; texture_create_info.usage = GFXTextureUsage::Attachment; - + auto offscreen_color_texture = gfx->create_texture(texture_create_info); - + texture_create_info = {}; texture_create_info.width = thumbnail_resolution; texture_create_info.height = thumbnail_resolution; texture_create_info.format = GFXPixelFormat::DEPTH_32F; texture_create_info.usage = GFXTextureUsage::Attachment; - + auto offscreen_depth_texture = gfx->create_texture(texture_create_info); - + GFXFramebufferCreateInfo framebuffer_create_info = {}; framebuffer_create_info.attachments = {offscreen_color_texture, offscreen_depth_texture}; framebuffer_create_info.render_pass = renderer->offscreen_render_pass; - + auto offscreen_framebuffer = gfx->create_framebuffer(framebuffer_create_info); - + framebuffer_create_info = {}; framebuffer_create_info.attachments = {final_texture}; framebuffer_create_info.render_pass = renderer->unorm_render_pass; - + auto final_framebuffer = gfx->create_framebuffer(framebuffer_create_info); - + GFXCommandBuffer* command_buffer = gfx->acquire_command_buffer(false); - + renderer->shadow_pass->render(command_buffer, scene); - if(render_options.enable_ibl) + if (render_options.enable_ibl) renderer->scene_capture->render(command_buffer, &scene); - + GFXRenderPassBeginInfo begin_info = {}; begin_info.framebuffer = offscreen_framebuffer; begin_info.render_pass = renderer->offscreen_render_pass; begin_info.render_area.extent = {thumbnail_resolution, thumbnail_resolution}; - + command_buffer->set_render_pass(begin_info); - + prism::renderer::controller_continuity continuity; - renderer->render_camera(command_buffer, scene, camera, scene.get(camera), begin_info.render_area.extent, *target, continuity); - + renderer->render_camera( + command_buffer, scene, camera, scene.get(camera), begin_info.render_area.extent, *target, continuity); + // render post begin_info.framebuffer = final_framebuffer; begin_info.render_pass = renderer->unorm_render_pass; - + command_buffer->set_render_pass(begin_info); - + Viewport viewport = {}; viewport.width = thumbnail_resolution; viewport.height = thumbnail_resolution; - + command_buffer->set_viewport(viewport); - + command_buffer->set_graphics_pipeline(renderer->render_to_unorm_texture_pipeline); - + command_buffer->bind_texture(offscreen_color_texture, 1); command_buffer->bind_texture(renderer->dummy_texture, 2); command_buffer->bind_texture(renderer->dummy_texture, 3); command_buffer->bind_texture(renderer->dummy_texture, 4); - + struct PostPushConstants { prism::float4 viewport; prism::float4 options; } pc; + pc.options.w = 1.0; - pc.viewport = prism::float4(1.0 / (float)thumbnail_resolution, 1.0 / (float)thumbnail_resolution, thumbnail_resolution, thumbnail_resolution); + pc.viewport = prism::float4( + 1.0 / (float)thumbnail_resolution, + 1.0 / (float)thumbnail_resolution, + thumbnail_resolution, + thumbnail_resolution); command_buffer->set_push_constant(&pc, sizeof(PostPushConstants)); - + command_buffer->draw(0, 4, 0, 1); - + gfx->submit(command_buffer, nullptr); - + return final_texture; } @@ -1015,16 +1036,15 @@ void CommonEditor::load_options() { if (i.is_open()) { nlohmann::json j; i >> j; - + defaultX = j["x"]; defaultY = j["y"]; defaultWidth = j["width"]; defaultHeight = j["height"]; - + for (auto& file : j["files"]) lastOpenedFiles.push_back(file.get()); - } - else { + } else { defaultX = -1; defaultY = -1; defaultWidth = 1280; @@ -1035,75 +1055,76 @@ void CommonEditor::load_options() { void CommonEditor::save_options() { const auto& [x, y] = platform::get_window_position(engine->get_main_window()); const auto& [width, height] = platform::get_window_size(engine->get_main_window()); - + nlohmann::json j; j["x"] = x; j["y"] = y; j["width"] = width; j["height"] = height; j["files"] = lastOpenedFiles; - + std::ofstream out(prism::get_writeable_directory() / (id + "options.json")); out << j; } void CommonEditor::load_thumbnail_cache() { auto thumbnail_cache = prism::open_file("./thumbnail-cache"); - if(thumbnail_cache != std::nullopt) { + if (thumbnail_cache != std::nullopt) { int size; thumbnail_cache->read(&size); - - for(int i = 0; i < size; i++) { + + for (int i = 0; i < size; i++) { std::string filename; thumbnail_cache->read_string(filename); - + std::vector image(thumbnail_resolution * thumbnail_resolution * 4); thumbnail_cache->read(image.data(), thumbnail_resolution * thumbnail_resolution * 4); - + GFXTextureCreateInfo info; info.label = "Preview of " + filename; info.width = thumbnail_resolution; info.height = thumbnail_resolution; info.format = GFXPixelFormat::RGBA8_UNORM; info.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst; - + GFXTexture* texture = engine->get_gfx()->create_texture(info); - + engine->get_gfx()->copy_texture(texture, image.data(), image.size()); - + asset_thumbnails[filename] = texture; } } } void CommonEditor::save_thumbnail_cache() { - GFXBuffer* thumbnailBuffer = engine->get_gfx()->create_buffer(nullptr, thumbnail_resolution * thumbnail_resolution * 4, false, GFXBufferUsage::Storage); - + GFXBuffer* thumbnailBuffer = engine->get_gfx()->create_buffer( + nullptr, thumbnail_resolution * thumbnail_resolution * 4, false, GFXBufferUsage::Storage); + FILE* file = fopen("thumbnail-cache", "wb"); - if(file == nullptr) { + if (file == nullptr) { prism::log("Failed to write thumbnail cache!"); return; } - + int size = asset_thumbnails.size(); fwrite(&size, sizeof(int), 1, file); - - for(auto [p, thumbnail] : asset_thumbnails) { + + for (auto [p, thumbnail] : asset_thumbnails) { unsigned int len = strlen(p.c_str()); fwrite(&len, sizeof(unsigned int), 1, file); - + const char* str = p.c_str(); fwrite(str, sizeof(char) * len, 1, file); - + // dump image to memory engine->get_gfx()->copy_texture(thumbnail, thumbnailBuffer); - + uint8_t* map = reinterpret_cast(engine->get_gfx()->get_buffer_contents(thumbnailBuffer)); - + fwrite(map, thumbnail_resolution * thumbnail_resolution * 4, 1, file); - + engine->get_gfx()->release_buffer_contents(thumbnailBuffer, map); } - + fclose(file); } diff --git a/tools/common/src/debugpass.cpp b/tools/common/src/debugpass.cpp index 5160e19..7209e68 100755 --- a/tools/common/src/debugpass.cpp +++ b/tools/common/src/debugpass.cpp @@ -1,13 +1,13 @@ #include "debugpass.hpp" -#include "gfx_commandbuffer.hpp" +#include "asset.hpp" #include "engine.hpp" -#include "scene.hpp" -#include "transform.hpp" #include "file.hpp" #include "gfx.hpp" -#include "asset.hpp" +#include "gfx_commandbuffer.hpp" #include "renderer.hpp" +#include "scene.hpp" +#include "transform.hpp" struct BillPushConstant { Matrix4x4 mvp; @@ -32,13 +32,9 @@ void DebugPass::initialize() { createInfo.vertex_input.attributes.push_back(positionAttribute); - createInfo.shader_input.push_constants = { - {sizeof(Matrix4x4) + sizeof(prism::float4), 0} - }; + createInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}}; - createInfo.shader_input.bindings = { - {1, GFXBindingType::PushConstant} - }; + createInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}}; createInfo.render_pass = engine->get_renderer()->offscreen_render_pass; createInfo.rasterization.polygon_type = GFXPolygonType::Line; @@ -51,7 +47,7 @@ void DebugPass::initialize() { createInfo.rasterization.polygon_type = GFXPolygonType::Fill; arrow_pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo); - + arrowMesh = assetm->get(prism::base_domain / "models/arrow.model"); } @@ -80,20 +76,16 @@ void DebugPass::initialize() { pipelineInfo.vertex_input.attributes.push_back(attribute); - pipelineInfo.shader_input.bindings = { - {1, GFXBindingType::PushConstant} - }; + pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}}; - pipelineInfo.shader_input.push_constants = { - {sizeof(Matrix4x4) + sizeof(prism::float4), 0} - }; + pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}}; pipelineInfo.render_pass = selectRenderPass; pipelineInfo.depth.depth_mode = GFXDepthMode::Less; selectPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo); } - + // sobel { // render pass @@ -101,7 +93,7 @@ void DebugPass::initialize() { renderPassInfo.label = "Sobel"; renderPassInfo.attachments.push_back(GFXPixelFormat::R8_UNORM); renderPassInfo.will_use_in_shader = true; - + sobelRenderPass = engine->get_gfx()->create_render_pass(renderPassInfo); // pipeline @@ -121,46 +113,37 @@ void DebugPass::initialize() { pipelineInfo.vertex_input.attributes.push_back(attribute); - pipelineInfo.shader_input.bindings = { - {1, GFXBindingType::PushConstant} - }; + pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}}; - pipelineInfo.shader_input.push_constants = { - {sizeof(Matrix4x4) + sizeof(prism::float4), 0} - }; + pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}}; pipelineInfo.render_pass = sobelRenderPass; sobelPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo); } - + // billboard { // pipeline GFXGraphicsPipelineCreateInfo pipelineInfo = {}; pipelineInfo.label = "Billboard"; - + pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("billboard.vert")); pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("billboard.frag")); - + pipelineInfo.shader_input.bindings = { - {1, GFXBindingType::PushConstant}, - {2, GFXBindingType::Texture}, - {3, GFXBindingType::StorageBuffer} - }; - - pipelineInfo.shader_input.push_constants = { - {sizeof(BillPushConstant), 0} - }; - + {1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}, {3, GFXBindingType::StorageBuffer}}; + + pipelineInfo.shader_input.push_constants = {{sizeof(BillPushConstant), 0}}; + pipelineInfo.depth.depth_mode = GFXDepthMode::Less; - + pipelineInfo.blending.enable_blending = true; - + pipelineInfo.render_pass = engine->get_renderer()->offscreen_render_pass; - + billboard_pipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo); - + pointTexture = assetm->get(prism::base_domain / "textures/point.png"); spotTexture = assetm->get(prism::base_domain / "textures/spot.png"); sunTexture = assetm->get(prism::base_domain / "textures/sun.png"); @@ -170,7 +153,7 @@ void DebugPass::initialize() { void DebugPass::create_render_target_resources(RenderTarget& target) { this->extent = target.extent; - + createOffscreenResources(); } @@ -184,23 +167,24 @@ void DebugPass::createOffscreenResources() { textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM; textureInfo.usage = GFXTextureUsage::Attachment; textureInfo.samplingMode = SamplingMode::ClampToEdge; - + selectTexture = engine->get_gfx()->create_texture(textureInfo); - + textureInfo.label = "Select Depth"; textureInfo.format = GFXPixelFormat::DEPTH_32F; - + selectDepthTexture = engine->get_gfx()->create_texture(textureInfo); - + GFXFramebufferCreateInfo info; info.attachments = {selectTexture, selectDepthTexture}; info.render_pass = selectRenderPass; selectFramebuffer = engine->get_gfx()->create_framebuffer(info); - selectBuffer = engine->get_gfx()->create_buffer(nullptr, extent.width * extent.height * 4 * sizeof(uint8_t), false, GFXBufferUsage::Storage); + selectBuffer = engine->get_gfx()->create_buffer( + nullptr, extent.width * extent.height * 4 * sizeof(uint8_t), false, GFXBufferUsage::Storage); } - + // sobel { GFXTextureCreateInfo textureInfo = {}; @@ -210,7 +194,7 @@ void DebugPass::createOffscreenResources() { textureInfo.format = GFXPixelFormat::R8_UNORM; textureInfo.usage = GFXTextureUsage::Attachment; textureInfo.samplingMode = SamplingMode::ClampToEdge; - + sobelTexture = engine->get_gfx()->create_texture(textureInfo); GFXFramebufferCreateInfo info; @@ -226,28 +210,29 @@ void DebugPass::draw_arrow(GFXCommandBuffer* commandBuffer, prism::float3 color, Matrix4x4 mvp; prism::float4 color; } pc; + pc.mvp = model; pc.color = color; - + commandBuffer->set_push_constant(&pc, sizeof(PushConstant)); - + commandBuffer->set_vertex_buffer(arrowMesh->position_buffer, 0, 0); commandBuffer->set_index_buffer(arrowMesh->index_buffer, IndexType::UINT32); - + commandBuffer->draw_indexed(arrowMesh->num_indices, 0, 0, 0); } void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { auto [camObj, camera] = scene.get_all()[0]; - + struct PushConstant { Matrix4x4 mvp; prism::float4 color; }; - + Matrix4x4 vp = camera.perspective * camera.view; - commandBuffer->set_graphics_pipeline(primitive_pipeline); + commandBuffer->set_graphics_pipeline(primitive_pipeline); struct DebugPrimitive { prism::float3 position, size; @@ -256,22 +241,22 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { }; std::vector primitives; - + struct DebugBillboard { prism::float3 position; GFXTexture* texture = nullptr; prism::float4 color; }; - + std::vector billboards; - for(auto& obj : scene.get_objects()) { - if(scene.get(obj).editor_object) + for (auto& obj : scene.get_objects()) { + if (scene.get(obj).editor_object) continue; auto& transform = scene.get(obj); - if(scene.has(obj)) { + if (scene.has(obj)) { auto& collision = scene.get(obj); { @@ -284,13 +269,13 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { primitives.push_back(prim); } } - - if(scene.has(obj)) { + + if (scene.has(obj)) { DebugBillboard bill; bill.position = transform.get_world_position(); bill.color = prism::float4(scene.get(obj).color, 1.0f); - - switch(scene.get(obj).type) { + + switch (scene.get(obj).type) { case Light::Type::Point: bill.texture = pointTexture->handle; break; @@ -301,34 +286,34 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { bill.texture = sunTexture->handle; break; } - + billboards.push_back(bill); } - - if(scene.has(obj)) { - if(selected_object == obj) { + + if (scene.has(obj)) { + if (selected_object == obj) { auto& probe = scene.get(obj); - + DebugPrimitive prim; prim.position = transform.get_world_position(); prim.rotation = transform.rotation; prim.size = probe.size / 2.0f; prim.color = prism::float4(0, 1, 1, 1); - + primitives.push_back(prim); } - + DebugBillboard bill; bill.position = transform.get_world_position(); bill.color = prism::float4(1.0f); bill.texture = probeTexture->handle; - + billboards.push_back(bill); } } // draw primitives - for(auto& prim : primitives) { + for (auto& prim : primitives) { PushConstant pc; Matrix4x4 m = prism::translate(Matrix4x4(), prim.position); @@ -345,48 +330,54 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { commandBuffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0); } - + commandBuffer->set_graphics_pipeline(billboard_pipeline); engine->get_gfx()->copy_buffer(scene_info_buffer, &camera.view, 0, sizeof(Matrix4x4)); // draw primitives - for(auto& bill : billboards) { + for (auto& bill : billboards) { Matrix4x4 m = prism::translate(Matrix4x4(), bill.position); - + BillPushConstant pc; pc.mvp = vp * m; pc.color = bill.color; - + commandBuffer->bind_texture(bill.texture, 2); commandBuffer->bind_shader_buffer(scene_info_buffer, 0, 3, sizeof(Matrix4x4)); commandBuffer->set_push_constant(&pc, sizeof(BillPushConstant)); commandBuffer->draw_indexed(4, 0, 0, 0); } - + commandBuffer->set_graphics_pipeline(arrow_pipeline); - + // draw handles for selected object; - if(selected_object != prism::NullObject && engine->get_scene()->has(selected_object)) { + if (selected_object != prism::NullObject && engine->get_scene()->has(selected_object)) { const auto position = engine->get_scene()->get(selected_object).get_world_position(); - + const float base_scale = 0.05f; const float scale_factor = length(position - scene.get(camObj).get_world_position()); - + Matrix4x4 base_model = prism::translate(Matrix4x4(), position); base_model = prism::scale(base_model, base_scale * scale_factor); - + // draw y axis draw_arrow(commandBuffer, prism::float3(0, 1, 0), vp * base_model); - + // draw x axis - draw_arrow(commandBuffer, prism::float3(1, 0, 0), vp * base_model * matrix_from_quat(angle_axis(radians(-90.0f), prism::float3(0, 0, 1)))); - + draw_arrow( + commandBuffer, + prism::float3(1, 0, 0), + vp * base_model * matrix_from_quat(angle_axis(radians(-90.0f), prism::float3(0, 0, 1)))); + // draw z axis - draw_arrow(commandBuffer, prism::float3(0, 0, 1), vp * base_model * matrix_from_quat(angle_axis(radians(90.0f), prism::float3(1, 0, 0)))); + draw_arrow( + commandBuffer, + prism::float3(0, 0, 1), + vp * base_model * matrix_from_quat(angle_axis(radians(90.0f), prism::float3(1, 0, 0)))); } - + // draw sobel GFXRenderPassBeginInfo info = {}; info.framebuffer = sobelFramebuffer; @@ -394,29 +385,29 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { info.render_area.extent = extent; commandBuffer->set_render_pass(info); - - if(selected_object != prism::NullObject && engine->get_scene()->has(selected_object)) { + + if (selected_object != prism::NullObject && engine->get_scene()->has(selected_object)) { commandBuffer->set_graphics_pipeline(sobelPipeline); auto renderable = engine->get_scene()->get(selected_object); - - if(!renderable.mesh) + + if (!renderable.mesh) return; - + struct PC { Matrix4x4 mvp; prism::float4 color; } pc; - + pc.mvp = vp * engine->get_scene()->get(selected_object).model; pc.color = prism::float4(1); - + commandBuffer->set_push_constant(&pc, sizeof(PC)); - + commandBuffer->set_vertex_buffer(renderable.mesh->position_buffer, 0, 0); commandBuffer->set_index_buffer(renderable.mesh->index_buffer, IndexType::UINT32); - - if(renderable.mesh) { + + if (renderable.mesh) { for (auto& part : renderable.mesh->parts) commandBuffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, 0); } @@ -424,45 +415,45 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { } void DebugPass::get_selected_object(int x, int y, const std::function& callback) { - if(engine->get_scene() == nullptr) + if (engine->get_scene() == nullptr) return; - + auto cameras = engine->get_scene()->get_all(); auto& [camObj, camera] = cameras[0]; - + // calculate selectable objects selectable_objects.clear(); - - for(auto& [obj, mesh] : engine->get_scene()->get_all()) { + + for (auto& [obj, mesh] : engine->get_scene()->get_all()) { SelectableObject so; so.type = SelectableObject::Type::Object; so.object = obj; so.render_type = SelectableObject::RenderType::Mesh; - + selectable_objects.push_back(so); } - - for(auto& [obj, mesh] : engine->get_scene()->get_all()) { + + for (auto& [obj, mesh] : engine->get_scene()->get_all()) { SelectableObject so; so.type = SelectableObject::Type::Object; so.object = obj; so.render_type = SelectableObject::RenderType::Sphere; so.sphere_size = 0.5f; - + selectable_objects.push_back(so); } - - for(auto& [obj, mesh] : engine->get_scene()->get_all()) { + + for (auto& [obj, mesh] : engine->get_scene()->get_all()) { SelectableObject so; so.type = SelectableObject::Type::Object; so.object = obj; so.render_type = SelectableObject::RenderType::Sphere; so.sphere_size = 0.5f; - + selectable_objects.push_back(so); } - + // add selections for currently selected object handles const auto add_arrow = [this](SelectableObject::Axis axis, Matrix4x4 model) { SelectableObject so; @@ -470,26 +461,30 @@ void DebugPass::get_selected_object(int x, int y, const std::functionget_scene()->get(selected_object).get_world_position(); - + const float base_scale = 0.05f; const float scale_factor = length(position - engine->get_scene()->get(camObj).position); - + const Matrix4x4 translate_model = prism::translate(Matrix4x4(), position); const Matrix4x4 scale_model = prism::scale(Matrix4x4(), base_scale * scale_factor); - + add_arrow(SelectableObject::Axis::Y, translate_model * scale_model); - - add_arrow(SelectableObject::Axis::X, translate_model * matrix_from_quat(angle_axis(radians(-90.0f), prism::float3(0, 0, 1))) * scale_model); - - add_arrow(SelectableObject::Axis::Z, translate_model * matrix_from_quat(angle_axis(radians(90.0f), prism::float3(1, 0, 0))) * scale_model); + + add_arrow( + SelectableObject::Axis::X, + translate_model * matrix_from_quat(angle_axis(radians(-90.0f), prism::float3(0, 0, 1))) * scale_model); + + add_arrow( + SelectableObject::Axis::Z, + translate_model * matrix_from_quat(angle_axis(radians(90.0f), prism::float3(1, 0, 0))) * scale_model); } - + GFXCommandBuffer* commandBuffer = engine->get_gfx()->acquire_command_buffer(false); GFXRenderPassBeginInfo info = {}; @@ -499,30 +494,30 @@ void DebugPass::get_selected_object(int x, int y, const std::functionset_render_pass(info); - + Viewport viewport = {}; viewport.width = extent.width; viewport.height = extent.height; - + commandBuffer->set_viewport(viewport); commandBuffer->set_graphics_pipeline(selectPipeline); - for(auto [i, object] : utility::enumerate(selectable_objects)) { + for (auto [i, object] : utility::enumerate(selectable_objects)) { AssetPtr mesh; Matrix4x4 model; - if(object.type == SelectableObject::Type::Object) { - if(object.render_type == SelectableObject::RenderType::Mesh) { + if (object.type == SelectableObject::Type::Object) { + if (object.render_type == SelectableObject::RenderType::Mesh) { auto& renderable = engine->get_scene()->get(object.object); - - if(!renderable.mesh) + + if (!renderable.mesh) continue; - + mesh = renderable.mesh; } else { mesh = sphereMesh; } - + model = engine->get_scene()->get(object.object).model; } else { mesh = arrowMesh; @@ -538,8 +533,8 @@ void DebugPass::get_selected_object(int x, int y, const std::functionget_gfx()->submit(commandBuffer, nullptr); - + engine->get_gfx()->copy_texture(selectTexture, selectBuffer); auto mapped_texture = reinterpret_cast(engine->get_gfx()->get_buffer_contents(selectBuffer)); - + const int buffer_position = 4 * (y * extent.width + x); uint8_t a = mapped_texture[buffer_position + 3]; - const int id = mapped_texture[buffer_position] + - mapped_texture[buffer_position + 1] * 256 + - mapped_texture[buffer_position + 2] * 256 * 256; - + const int id = mapped_texture[buffer_position] + mapped_texture[buffer_position + 1] * 256 + + mapped_texture[buffer_position + 2] * 256 * 256; + engine->get_gfx()->release_buffer_contents(selectBuffer, mapped_texture); - if(a != 0) { + if (a != 0) { callback(selectable_objects[id]); } else { SelectableObject o; diff --git a/tools/common/src/undostack.cpp b/tools/common/src/undostack.cpp index b57ea7f..2afdba9 100755 --- a/tools/common/src/undostack.cpp +++ b/tools/common/src/undostack.cpp @@ -1,34 +1,34 @@ #include "undostack.hpp" void UndoStack::undo() { - if(stack_position >= 0) { + if (stack_position >= 0) { command_stack[stack_position]->undo(); stack_position--; } } void UndoStack::redo() { - if((stack_position + 1) < command_stack.size()) { + if ((stack_position + 1) < command_stack.size()) { stack_position++; command_stack[stack_position]->execute(); } } Command* UndoStack::get_last_command() { - if(command_stack.empty()) + if (command_stack.empty()) return nullptr; - - if(stack_position >= 0) + + if (stack_position >= 0) return command_stack[stack_position].get(); return nullptr; } Command* UndoStack::get_next_command() { - if(command_stack.empty()) + if (command_stack.empty()) return nullptr; - - if((stack_position + 1) < command_stack.size()) + + if ((stack_position + 1) < command_stack.size()) return command_stack[stack_position + 1].get(); return nullptr; diff --git a/tools/cutsceneeditor/CMakeLists.txt b/tools/cutsceneeditor/CMakeLists.txt index d660a09..c4df99f 100755 --- a/tools/cutsceneeditor/CMakeLists.txt +++ b/tools/cutsceneeditor/CMakeLists.txt @@ -1,14 +1,14 @@ add_platform_executable( - TARGET CutsceneEditor - APP_CLASS CutsceneEditor - APP_INCLUDE cutsceneeditor.hpp - SKIP_DATA ON - SRC - src/cutsceneeditor.cpp - include/cutsceneeditor.hpp) + TARGET CutsceneEditor + APP_CLASS CutsceneEditor + APP_INCLUDE cutsceneeditor.hpp + SKIP_DATA ON + SRC + src/cutsceneeditor.cpp + include/cutsceneeditor.hpp) target_link_libraries(CutsceneEditor PUBLIC - Core - EditorCommon) + Core + EditorCommon) target_include_directories(CutsceneEditor PUBLIC - include) + include) set_engine_properties(CutsceneEditor) \ No newline at end of file diff --git a/tools/cutsceneeditor/src/cutsceneeditor.cpp b/tools/cutsceneeditor/src/cutsceneeditor.cpp index 620d854..62c0ce2 100755 --- a/tools/cutsceneeditor/src/cutsceneeditor.cpp +++ b/tools/cutsceneeditor/src/cutsceneeditor.cpp @@ -3,11 +3,11 @@ #include #include +#include "cutscene.hpp" #include "engine.hpp" #include "file.hpp" #include "json_conversions.hpp" #include "platform.hpp" -#include "cutscene.hpp" Shot* currentShot = nullptr; AnimationChannel* currentChannel = nullptr; @@ -16,13 +16,15 @@ PositionKeyFrame* currentFrame = nullptr; std::string currentPath; void app_main(prism::engine* engine) { - auto editor = (CommonEditor*)engine->get_app(); + auto editor = (CommonEditor*)engine->get_app(); - platform::open_window("Cutscene Editor", - {editor->getDefaultX(), - editor->getDefaultY(), - static_cast(editor->getDefaultWidth()), - static_cast(editor->getDefaultHeight())}, WindowFlags::Resizable); + platform::open_window( + "Cutscene Editor", + {editor->getDefaultX(), + editor->getDefaultY(), + static_cast(editor->getDefaultWidth()), + static_cast(editor->getDefaultHeight())}, + WindowFlags::Resizable); } CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {} @@ -30,7 +32,7 @@ CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {} static bool has_been_docked = false; void CutsceneEditor::renderEditor(GFXCommandBuffer* command_buffer) { - for(auto [id, render_target] : viewport_render_targets) { + for (auto [id, render_target] : viewport_render_targets) { engine->get_renderer()->render(command_buffer, render_target.scene, *render_target.target, nullptr); } } @@ -42,30 +44,30 @@ void CutsceneEditor::drawUI() { ImGui::End(); - if(!has_been_docked) { + if (!has_been_docked) { const auto size = ImGui::GetMainViewport()->Size; - + ImGui::DockBuilderRemoveNode(editor_dockspace); ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace); ImGui::DockBuilderSetNodeSize(editor_dockspace, size); ImGuiID outline_parent, view; ImGui::DockBuilderSplitNode(editor_dockspace, ImGuiDir_Left, 0.2f, &outline_parent, &view); - + ImGuiID outline, playback; ImGui::DockBuilderSplitNode(outline_parent, ImGuiDir_Down, 0.8f, &outline, &playback); - + ImGui::DockBuilderDockWindow("Outliner", outline); ImGui::DockBuilderDockWindow("Playback Settings", playback); ImGuiID viewport_parent, properties; ImGui::DockBuilderSplitNode(view, ImGuiDir_Left, 0.7f, &viewport_parent, &properties); - + ImGui::DockBuilderDockWindow("Properties", properties); ImGuiID lowerbar, viewport; ImGui::DockBuilderSplitNode(viewport_parent, ImGuiDir_Down, 0.3f, &lowerbar, &viewport); - + ImGui::DockBuilderDockWindow("Viewport", viewport); ImGui::DockBuilderDockWindow("Timeline", lowerbar); @@ -73,370 +75,378 @@ void CutsceneEditor::drawUI() { ImGui::DockBuilderFinish(editor_dockspace); - has_been_docked =true; + has_been_docked = true; } - - if (ImGui::BeginMainMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if(ImGui::MenuItem("New", "CTRL+N")) { + + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("New", "CTRL+N")) { engine->cutscene = std::make_unique(); - - platform::set_window_title(engine->get_main_window(), "Cutscene Editor"); + + platform::set_window_title(engine->get_main_window(), "Cutscene Editor"); } - if(ImGui::MenuItem("Open", "CTRL+O")) { - engine->get_imgui().open_dialog(true, [this](std::string path){ - currentPath = path; - + if (ImGui::MenuItem("Open", "CTRL+O")) { + engine->get_imgui().open_dialog(true, [this](std::string path) { + currentPath = path; + engine->load_cutscene(path); - platform::set_window_title(engine->get_main_window(), ("Cutscene Editor - " + path).c_str()); + platform::set_window_title(engine->get_main_window(), ("Cutscene Editor - " + path).c_str()); - addOpenedFile(path); + addOpenedFile(path); }); } - const auto& recents = getOpenedFiles(); - if (ImGui::BeginMenu("Open Recent...", !recents.empty())) { - for (auto& file : recents) { - if (ImGui::MenuItem(file.c_str())) { - currentPath = file; - + const auto& recents = getOpenedFiles(); + if (ImGui::BeginMenu("Open Recent...", !recents.empty())) { + for (auto& file : recents) { + if (ImGui::MenuItem(file.c_str())) { + currentPath = file; + engine->load_cutscene(file); - platform::set_window_title(0, ("Cutscene Editor - " + file).c_str()); - } - } + platform::set_window_title(0, ("Cutscene Editor - " + file).c_str()); + } + } - ImGui::Separator(); + ImGui::Separator(); - if (ImGui::MenuItem("Clear")) { - clearOpenedFiles(); - } + if (ImGui::MenuItem("Clear")) { + clearOpenedFiles(); + } - ImGui::EndMenu(); - } + ImGui::EndMenu(); + } + + if (ImGui::MenuItem("Save", "CTRL+S")) { + if (currentPath.empty()) { + engine->get_imgui().save_dialog([](std::string path) { + currentPath = path; - if(ImGui::MenuItem("Save", "CTRL+S")) { - if (currentPath.empty()) { - engine->get_imgui().save_dialog([](std::string path) { - currentPath = path; - engine->save_cutscene(path); - - platform::set_window_title(0, ("Cutscene Editor - " + path).c_str()); - }); - } - else { + + platform::set_window_title(0, ("Cutscene Editor - " + path).c_str()); + }); + } else { engine->save_cutscene(currentPath); } } - if (ImGui::MenuItem("Save as...", "CTRL+S")) { + if (ImGui::MenuItem("Save as...", "CTRL+S")) { engine->get_imgui().save_dialog([](std::string path) { - currentPath = path; - + currentPath = path; + engine->save_cutscene(path); - platform::set_window_title(0, ("Cutscene Editor - " + path).c_str()); - }); - } + platform::set_window_title(0, ("Cutscene Editor - " + path).c_str()); + }); + } ImGui::Separator(); - if(ImGui::MenuItem("Quit", "CTRL+Q")) + if (ImGui::MenuItem("Quit", "CTRL+Q")) engine->quit(); ImGui::EndMenu(); } - if (ImGui::BeginMenu("Edit")) - { - if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + if (ImGui::BeginMenu("Edit")) { + if (ImGui::MenuItem("Undo", "CTRL+Z")) { + } + if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) { + } // Disabled item ImGui::Separator(); - if (ImGui::MenuItem("Cut", "CTRL+X")) {} - if (ImGui::MenuItem("Copy", "CTRL+C")) {} - if (ImGui::MenuItem("Paste", "CTRL+V")) {} + if (ImGui::MenuItem("Cut", "CTRL+X")) { + } + if (ImGui::MenuItem("Copy", "CTRL+C")) { + } + if (ImGui::MenuItem("Paste", "CTRL+V")) { + } ImGui::EndMenu(); } - - if(ImGui::BeginMenu("Add...")) { + + if (ImGui::BeginMenu("Add...")) { if (ImGui::MenuItem("Empty")) { auto new_obj = engine->get_scene()->add_object(); engine->get_scene()->get(new_obj).name = "new object"; } - - if(ImGui::MenuItem("Prefab")) { + + if (ImGui::MenuItem("Prefab")) { engine->get_imgui().open_dialog(false, [](std::string path) { engine->add_prefab(*engine->get_scene(), path); }); } - + ImGui::EndMenu(); } - if (ImGui::BeginMenu("Help")) { - if (ImGui::MenuItem("About")) { + if (ImGui::BeginMenu("Help")) { + if (ImGui::MenuItem("About")) { + } - } - - ImGui::EndMenu(); - } + ImGui::EndMenu(); + } ImGui::EndMainMenuBar(); } - - if(ImGui::Begin("Outliner")) { + + if (ImGui::Begin("Outliner")) { drawOutline(); } - + ImGui::End(); - if(ImGui::Begin("Properties")) { + if (ImGui::Begin("Properties")) { drawPropertyEditor(); } - + ImGui::End(); - if(ImGui::Begin("Timeline")) { - if(engine->cutscene != nullptr) { - if(ImGui::Button("Add Shot")) { + if (ImGui::Begin("Timeline")) { + if (engine->cutscene != nullptr) { + if (ImGui::Button("Add Shot")) { engine->cutscene->shots.emplace_back(); currentShot = &engine->cutscene->shots.back(); } - - if(currentShot != nullptr) { + + if (currentShot != nullptr) { ImGui::SameLine(); - if(ImGui::Button("Change scene")) { + if (ImGui::Button("Change scene")) { open_asset(AssetType::Scene, [](prism::path path) { currentShot->scene = engine->load_scene(prism::game_domain / path); }); } - + ImGui::SameLine(); - + ImGui::SetNextItemWidth(25.0f); - + ImGui::DragInt("Begin", ¤tShot->begin, 1.0f, 0, 1000); - + ImGui::SameLine(); - + ImGui::SetNextItemWidth(25.0f); ImGui::DragInt("Length", ¤tShot->length, 1.0f, 0, 1000); - + ImGui::SameLine(); - - if(ImGui::Button("Remove")) { + + if (ImGui::Button("Remove")) { utility::erase(engine->cutscene->shots, *currentShot); currentShot = nullptr; } } - + ImGui::Separator(); - + const auto& draw_list = ImGui::GetWindowDrawList(); const ImVec2 p = ImGui::GetCursorScreenPos(); - + int i = 0; - for(auto& shot : engine->cutscene->shots) { + for (auto& shot : engine->cutscene->shots) { auto a = ImVec2(p.x + (5 * shot.begin), p.y); auto b = ImVec2(p.x + (5 * (shot.begin + shot.length)), p.y + 50); - - if(&shot == currentShot) { + + if (&shot == currentShot) { draw_list->AddRectFilled(a, b, IM_COL32(0, 0, 100, 100)); } - + draw_list->AddRect(a, b, IM_COL32_WHITE); - + std::string name = "Shot " + std::to_string(i); draw_list->AddText(ImVec2(a.x + 2, a.y + 2), IM_COL32_WHITE, name.c_str()); - - if(ImGui::IsMouseClicked(0)) { + + if (ImGui::IsMouseClicked(0)) { auto c = ImGui::GetMousePos(); - if(c.x > a.x && c.x < b.x && c.y > a.y && c.y < b.y) { - if(currentShot == &shot) { + if (c.x > a.x && c.x < b.x && c.y > a.y && c.y < b.y) { + if (currentShot == &shot) { currentShot = nullptr; } else { currentShot = &shot; } } } - + i++; } - - draw_list->AddLine(ImVec2(p.x + (engine->current_cutscene_time * 5), p.y), ImVec2(p.x + (engine->current_cutscene_time * 5), p.y + 75), IM_COL32_WHITE); + + draw_list->AddLine( + ImVec2(p.x + (engine->current_cutscene_time * 5), p.y), + ImVec2(p.x + (engine->current_cutscene_time * 5), p.y + 75), + IM_COL32_WHITE); } else { ImGui::Text("No cutscene loaded."); } } - + ImGui::End(); - if(ImGui::Begin("Animation Editor")) { - if(currentShot != nullptr && currentShot->scene != nullptr) { + if (ImGui::Begin("Animation Editor")) { + if (currentShot != nullptr && currentShot->scene != nullptr) { ImGui::BeginChild("animations", ImVec2(150, -1), true); - - if(ImGui::Button("Add Channel")) { + + if (ImGui::Button("Add Channel")) { currentShot->channels.emplace_back(); currentChannel = ¤tShot->channels.back(); } - + int i = 0; - for(auto& channel : currentShot->channels) { + for (auto& channel : currentShot->channels) { std::string name = "Channel " + std::to_string(i); - if(ImGui::Selectable(name.c_str(), &channel == currentChannel)) + if (ImGui::Selectable(name.c_str(), &channel == currentChannel)) currentChannel = &channel; - + i++; } - - if(currentShot->channels.empty()) + + if (currentShot->channels.empty()) ImGui::TextDisabled("No channels in this shot."); - + ImGui::EndChildFrame(); - + ImGui::SameLine(); - + ImGui::BeginChild("editanim", ImVec2(-1, -1), false); - - if(currentChannel != nullptr) { - if(ImGui::Button("Add Position Frame")) { + + if (currentChannel != nullptr) { + if (ImGui::Button("Add Position Frame")) { currentChannel->positions.emplace_back(); currentFrame = ¤tChannel->positions.back(); } - + ImGui::SameLine(); - + ImGui::SetNextItemWidth(50.0f); - + const char* preview_value = "None"; - if(currentChannel->target != prism::NullObject && currentShot->scene->has(currentChannel->target)) + if (currentChannel->target != prism::NullObject && + currentShot->scene->has(currentChannel->target)) preview_value = currentShot->scene->get(currentChannel->target).name.c_str(); - - if(ImGui::BeginCombo("Target", preview_value)) { - for(auto& object : currentShot->scene->get_objects()) { - if(ImGui::Selectable(currentShot->scene->get(object).name.c_str())) { + + if (ImGui::BeginCombo("Target", preview_value)) { + for (auto& object : currentShot->scene->get_objects()) { + if (ImGui::Selectable(currentShot->scene->get(object).name.c_str())) { currentChannel->target = object; currentChannel->bone = nullptr; } - - if(currentShot->scene->has(object) && !currentShot->scene->get(object).mesh->bones.empty()) { + + if (currentShot->scene->has(object) && + !currentShot->scene->get(object).mesh->bones.empty()) { ImGui::Indent(); - - for(auto& bone : currentShot->scene->get(object).mesh->bones) { - if(ImGui::Selectable(bone.name.c_str())) { + + for (auto& bone : currentShot->scene->get(object).mesh->bones) { + if (ImGui::Selectable(bone.name.c_str())) { currentChannel->bone = &bone; currentChannel->target = prism::NullObject; } } - + ImGui::Unindent(); } } - + ImGui::EndCombo(); } - + ImGui::SameLine(); - - if(ImGui::Button("Remove Channel")) { + + if (ImGui::Button("Remove Channel")) { utility::erase(currentShot->channels, *currentChannel); currentChannel = nullptr; } - - if(currentFrame != nullptr) { + + if (currentFrame != nullptr) { ImGui::SameLine(); - + ImGui::SetNextItemWidth(10.0f); - + ImGui::DragFloat("FT", ¤tFrame->time, 1.0f, 0.0f, 10000.0f); - + ImGui::SameLine(); - + ImGui::SetNextItemWidth(50.0f); ImGui::DragFloat3("FV", currentFrame->value.ptr()); - + ImGui::SameLine(); - - if(ImGui::Button("Remove Keyframe")) { + + if (ImGui::Button("Remove Keyframe")) { utility::erase(currentChannel->positions, *currentFrame); currentFrame = nullptr; } } - - if(currentChannel != nullptr) { + + if (currentChannel != nullptr) { const auto& draw_list = ImGui::GetWindowDrawList(); const ImVec2 p = ImGui::GetCursorScreenPos(); - - for(auto& keyframe : currentChannel->positions) { + + for (auto& keyframe : currentChannel->positions) { ImVec2 c = ImVec2(p.x + (keyframe.time * 5), p.y); - - if(&keyframe == currentFrame) + + if (&keyframe == currentFrame) draw_list->AddCircleFilled(c, 5.0f, IM_COL32(0, 0, 100, 255)); - + draw_list->AddCircle(c, 5.0f, IM_COL32_WHITE); - - if(ImGui::IsMouseClicked(0)) { - ImVec2 a = ImVec2(p.x + (keyframe.time * 5) - 5, p.y - 5); - ImVec2 b = ImVec2(p.x + (keyframe.time * 5) + 5, p.y + 5); - - auto mouse_pos = ImGui::GetMousePos(); - if(mouse_pos.x > a.x && mouse_pos.x < b.x && mouse_pos.y > a.y && mouse_pos.y < b.y) { - if(currentFrame == &keyframe) { - currentFrame = nullptr; - } else { - currentFrame = &keyframe; - } - } - } + + if (ImGui::IsMouseClicked(0)) { + ImVec2 a = ImVec2(p.x + (keyframe.time * 5) - 5, p.y - 5); + ImVec2 b = ImVec2(p.x + (keyframe.time * 5) + 5, p.y + 5); + + auto mouse_pos = ImGui::GetMousePos(); + if (mouse_pos.x > a.x && mouse_pos.x < b.x && mouse_pos.y > a.y && mouse_pos.y < b.y) { + if (currentFrame == &keyframe) { + currentFrame = nullptr; + } else { + currentFrame = &keyframe; + } + } + } } - + ImVec2 shot_start = ImVec2(p.x + (currentShot->begin * 5), p.y + 10.0f); ImVec2 shot_end = ImVec2(p.x + (currentShot->length * 5), p.y + 10.0f); draw_list->AddCircleFilled(shot_start, 2.5f, IM_COL32(255, 0, 0, 255)); draw_list->AddCircleFilled(shot_end, 2.5f, IM_COL32(255, 0, 0, 255)); - draw_list->AddLine(ImVec2(p.x + ((engine->current_cutscene_time - currentShot->begin) * 5), p.y), ImVec2(p.x + ((engine->current_cutscene_time - currentShot->begin) * 5), p.y + 75), IM_COL32_WHITE); + draw_list->AddLine( + ImVec2(p.x + ((engine->current_cutscene_time - currentShot->begin) * 5), p.y), + ImVec2(p.x + ((engine->current_cutscene_time - currentShot->begin) * 5), p.y + 75), + IM_COL32_WHITE); } } else { ImGui::TextDisabled("No animation selected."); } - + ImGui::EndChild(); } else { ImGui::TextDisabled("No shot selected."); } } - + ImGui::End(); - if(ImGui::Begin("Playback Settings")) { - if(ImGui::Button(engine->play_cutscene ? "Stop" : "Play")) { + if (ImGui::Begin("Playback Settings")) { + if (ImGui::Button(engine->play_cutscene ? "Stop" : "Play")) { engine->play_cutscene = !engine->play_cutscene; } - + ImGui::DragFloat("Time", &engine->current_cutscene_time, 1.0f, 0.0f, 1000.0f); } - + ImGui::End(); - if(ImGui::Begin("Viewport")) { - if(currentShot != nullptr && currentShot->scene != nullptr) + if (ImGui::Begin("Viewport")) { + if (currentShot != nullptr && currentShot->scene != nullptr) drawViewport(currentShot->scene); } - + ImGui::End(); - - if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow))) + + if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow))) engine->current_cutscene_time -= 1.0f; - - if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow))) + + if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow))) engine->current_cutscene_time += 1.0f; } diff --git a/tools/editor/CMakeLists.txt b/tools/editor/CMakeLists.txt index 69b6670..c104261 100755 --- a/tools/editor/CMakeLists.txt +++ b/tools/editor/CMakeLists.txt @@ -1,23 +1,23 @@ set(SRC - include/prismeditor.hpp - include/materialeditor.hpp - include/sceneeditor.hpp - include/prefabeditor.hpp - - src/prismeditor.cpp - src/materialeditor.cpp - src/sceneeditor.cpp - src/prefabeditor.cpp) + include/prismeditor.hpp + include/materialeditor.hpp + include/sceneeditor.hpp + include/prefabeditor.hpp + + src/prismeditor.cpp + src/materialeditor.cpp + src/sceneeditor.cpp + src/prefabeditor.cpp) add_platform_executable( - TARGET PrismEditor - APP_CLASS PrismEditor - APP_INCLUDE prismeditor.hpp - SKIP_DATA ON - SRC ${SRC}) + TARGET PrismEditor + APP_CLASS PrismEditor + APP_INCLUDE prismeditor.hpp + SKIP_DATA ON + SRC ${SRC}) target_link_libraries(PrismEditor PUBLIC - Core - EditorCommon) + Core + EditorCommon) target_include_directories(PrismEditor PUBLIC - include) + include) set_engine_properties(PrismEditor) \ No newline at end of file diff --git a/tools/editor/include/materialeditor.hpp b/tools/editor/include/materialeditor.hpp index 3ee240d..f2c4d1a 100755 --- a/tools/editor/include/materialeditor.hpp +++ b/tools/editor/include/materialeditor.hpp @@ -1,7 +1,7 @@ #pragma once -#include "prismeditor.hpp" #include "asset.hpp" +#include "prismeditor.hpp" #include "scene.hpp" class MaterialEditor : public Editor { @@ -17,10 +17,10 @@ public: std::string get_title() const override; Scene* get_scene() const override; - + void setup_windows(ImGuiID dockspace) override; - + void setup_material(); - + void draw(CommonEditor* editor) override; }; diff --git a/tools/editor/include/prefabeditor.hpp b/tools/editor/include/prefabeditor.hpp index f807d2e..0c28ea8 100755 --- a/tools/editor/include/prefabeditor.hpp +++ b/tools/editor/include/prefabeditor.hpp @@ -14,7 +14,7 @@ public: std::string get_title() const override; Scene* get_scene() const override; - + void setup_windows(ImGuiID dockspace) override; void draw(CommonEditor* editor) override; diff --git a/tools/editor/include/prismeditor.hpp b/tools/editor/include/prismeditor.hpp index 25f54c2..1e8092b 100755 --- a/tools/editor/include/prismeditor.hpp +++ b/tools/editor/include/prismeditor.hpp @@ -10,7 +10,7 @@ class Scene; class Editor { public: std::string path; - + bool has_been_docked = false; bool modified = false; bool wants_to_close = false; @@ -19,15 +19,21 @@ public: auto window_class = get_window_class(); return get_title() + "###" + std::to_string(window_class.ClassId); } - + virtual Scene* get_scene() const { return nullptr; } - virtual bool has_menubar() const { return false; } + virtual bool has_menubar() const { + return false; + } + + virtual std::string get_title() const { + return ""; + } - virtual std::string get_title() const { return ""; } virtual void draw([[maybe_unused]] CommonEditor* editor) {} + virtual void setup_windows([[maybe_unused]] ImGuiID dockspace) {} ImGuiWindowClass get_window_class() const { @@ -37,7 +43,7 @@ public: return window_class; } - + std::string get_window_name(std::string title) { return title + "##" + std::to_string((uint64_t)this); } @@ -45,21 +51,21 @@ public: bool begin(std::string title, bool* p_open = nullptr) { return ImGui::Begin(get_window_name(title).c_str(), p_open); } - + UndoStack undo_stack; }; class PrismEditor : public CommonEditor { public: PrismEditor(); - + void renderEditor(GFXCommandBuffer* command_buffer) override; void drawUI() override; void updateEditor(float deltaTime) override; - + void object_selected(prism::Object object) override; void asset_selected(const std::filesystem::path& path, AssetType type) override; - + private: void open_asset(prism::path path); void setup_editor(Editor* editor); diff --git a/tools/editor/include/sceneeditor.hpp b/tools/editor/include/sceneeditor.hpp index 801abf8..474c096 100755 --- a/tools/editor/include/sceneeditor.hpp +++ b/tools/editor/include/sceneeditor.hpp @@ -1,21 +1,21 @@ #pragma once -#include "prismeditor.hpp" #include "engine.hpp" +#include "prismeditor.hpp" class AddObjectCommand : public Command { public: prism::Object id; std::string name; - + std::string fetch_name() override { return "Add object " + name; } - + void undo() override { engine->get_scene()->remove_object(id); } - + void execute() override { engine->get_scene()->add_object_by_id(id); engine->get_scene()->get(id).name = name; diff --git a/tools/editor/src/materialeditor.cpp b/tools/editor/src/materialeditor.cpp index 7d8cb14..60aab94 100755 --- a/tools/editor/src/materialeditor.cpp +++ b/tools/editor/src/materialeditor.cpp @@ -1,8 +1,8 @@ #include "materialeditor.hpp" #include -#include #include +#include #include "engine.hpp" @@ -23,7 +23,7 @@ void MaterialEditor::setup_windows(ImGuiID dockspace) { ImGuiID dock_id_left, dock_id_right; ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.40f, &dock_id_left, &dock_id_right); - + ImGui::DockBuilderDockWindow(get_window_name("Viewport").c_str(), dock_id_left); ImGui::DockBuilderDockWindow(get_window_name("Node Editor").c_str(), dock_id_right); } @@ -38,58 +38,58 @@ void recompile(Material* material) { } void MaterialEditor::draw(CommonEditor* editor) { - if(!material) + if (!material) return; - + if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) { - if(ImGui::MenuItem("Save", "CTRL+S")) { + if (ImGui::MenuItem("Save", "CTRL+S")) { if (path.empty()) { engine->get_imgui().save_dialog([this](std::string path) { this->path = path; - + save_material(*material, path); }); } else { save_material(*material, prism::get_file_path(path)); } } - + if (ImGui::MenuItem("Save as...", "CTRL+S")) { engine->get_imgui().save_dialog([this](std::string path) { this->path = path; - + save_material(*material, path); }); } - + ImGui::Separator(); - - if(ImGui::MenuItem("Close")) + + if (ImGui::MenuItem("Close")) wants_to_close = true; - + ImGui::EndMenu(); } - - if(ImGui::MenuItem("Compile")) + + if (ImGui::MenuItem("Compile")) recompile(*material); ImGui::EndMenuBar(); } - + auto viewport_scene = engine->get_scene(); - - if(viewport_scene != nullptr) { + + if (viewport_scene != nullptr) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - if(begin("Viewport")) + if (begin("Viewport")) editor->drawViewport(viewport_scene); - + ImGui::End(); - + ImGui::PopStyleVar(); } - - if(begin("Node Editor")) { + + if (begin("Node Editor")) { const auto draw_list = ImGui::GetWindowDrawList(); const auto window_pos = ImGui::GetCursorScreenPos(); @@ -97,42 +97,40 @@ void MaterialEditor::draw(CommonEditor* editor) { auto& property = material->colorProperty; - ImGui::PushID(property.name.c_str()); + ImGui::PushID(property.name.c_str()); - if(ImGui::BeginCombo("Type", "test")) { - if(ImGui::Selectable("Vector3")) - property.type = DataType::Vector3; + if (ImGui::BeginCombo("Type", "test")) { + if (ImGui::Selectable("Vector3")) + property.type = DataType::Vector3; - if(ImGui::Selectable("Texture")) - property.type = DataType::AssetTexture; + if (ImGui::Selectable("Texture")) + property.type = DataType::AssetTexture; - if(ImGui::Selectable("Float")) - property.type = DataType::Float; + if (ImGui::Selectable("Float")) + property.type = DataType::Float; - ImGui::EndCombo(); - } + ImGui::EndCombo(); + } - ImGui::TextDisabled("%s", property.name.c_str()); + ImGui::TextDisabled("%s", property.name.c_str()); - switch(property.type) { - case DataType::Vector3: - changed |= ImGui::ColorEdit3("", property.value.ptr()); - break; - case DataType::Float: - changed |= ImGui::DragFloat("", &property.float_value); - break; - case DataType::AssetTexture: - changed |= editor->edit_asset("", property.value_tex); - break; - } + switch (property.type) { + case DataType::Vector3: + changed |= ImGui::ColorEdit3("", property.value.ptr()); + break; + case DataType::Float: + changed |= ImGui::DragFloat("", &property.float_value); + break; + case DataType::AssetTexture: + changed |= editor->edit_asset("", property.value_tex); + break; + } - ImGui::PopID(); + ImGui::PopID(); - if(changed) + if (changed) recompile(*material); - } - ImGui::End(); } diff --git a/tools/editor/src/prefabeditor.cpp b/tools/editor/src/prefabeditor.cpp index 62e998f..48371f3 100755 --- a/tools/editor/src/prefabeditor.cpp +++ b/tools/editor/src/prefabeditor.cpp @@ -1,8 +1,8 @@ #include "prefabeditor.hpp" #include -#include #include +#include #include "engine.hpp" @@ -34,7 +34,7 @@ void PrefabEditor::setup_windows(ImGuiID dockspace) { void PrefabEditor::draw(CommonEditor* editor) { if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) { - if(ImGui::MenuItem("Save", "CTRL+S")) { + if (ImGui::MenuItem("Save", "CTRL+S")) { if (path.empty()) { engine->get_imgui().save_dialog([this](std::string path) { this->path = path; @@ -53,12 +53,12 @@ void PrefabEditor::draw(CommonEditor* editor) { engine->save_prefab(root_object, path); }); } - + ImGui::Separator(); - - if(ImGui::MenuItem("Close")) + + if (ImGui::MenuItem("Close")) wants_to_close = true; - + ImGui::EndMenu(); } @@ -67,13 +67,13 @@ void PrefabEditor::draw(CommonEditor* editor) { auto viewport_scene = engine->get_scene(); - if(viewport_scene != nullptr) { + if (viewport_scene != nullptr) { auto window_class = get_window_class(); - if(showOutliner) { + if (showOutliner) { ImGui::SetNextWindowClass(&window_class); - if(begin("Outliner", &showOutliner)) + if (begin("Outliner", &showOutliner)) editor->drawOutline(); ImGui::End(); @@ -91,7 +91,7 @@ void PrefabEditor::draw(CommonEditor* editor) { ImGui::SetNextWindowClass(&window_class); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - if(begin("Viewport")) + if (begin("Viewport")) editor->drawViewport(viewport_scene); ImGui::End(); diff --git a/tools/editor/src/prismeditor.cpp b/tools/editor/src/prismeditor.cpp index 6201dc0..4b213e0 100755 --- a/tools/editor/src/prismeditor.cpp +++ b/tools/editor/src/prismeditor.cpp @@ -1,17 +1,17 @@ #include "prismeditor.hpp" #include -#include #include +#include #include "engine.hpp" #include "file.hpp" #include "json_conversions.hpp" -#include "platform.hpp" -#include "string_utils.hpp" -#include "sceneeditor.hpp" #include "materialeditor.hpp" +#include "platform.hpp" #include "prefabeditor.hpp" +#include "sceneeditor.hpp" +#include "string_utils.hpp" std::string get_filename(const std::string path) { return path.substr(path.find_last_of("/") + 1, path.length()); @@ -20,21 +20,20 @@ std::string get_filename(const std::string path) { std::vector editors; void app_main(prism::engine* engine) { - CommonEditor* editor = (CommonEditor*)engine->get_app(); + CommonEditor* editor = (CommonEditor*)engine->get_app(); - platform::open_window("Prism Editor", - {editor->getDefaultX(), - editor->getDefaultY(), - static_cast(editor->getDefaultWidth()), - static_cast(editor->getDefaultHeight())}, - WindowFlags::Resizable); + platform::open_window( + "Prism Editor", + {editor->getDefaultX(), + editor->getDefaultY(), + static_cast(editor->getDefaultWidth()), + static_cast(editor->getDefaultHeight())}, + WindowFlags::Resizable); engine->update_physics = false; } -PrismEditor::PrismEditor() : CommonEditor("PrismEditor") { - -} +PrismEditor::PrismEditor() : CommonEditor("PrismEditor") {} void prepScene() { auto scene = engine->get_scene(); @@ -44,13 +43,13 @@ void prepScene() { scene->get(camera).editor_object = true; scene->add(camera); - + camera_look_at(*scene, camera, prism::float3(0, 2, 3), prism::float3(0)); } void prepThreePointLighting() { auto scene = engine->get_scene(); - + auto probe = scene->add_object(); scene->add(probe).is_sized = false; @@ -84,7 +83,7 @@ void prepPrefabScene() { Renderable* prepMaterialScene() { auto scene = engine->get_scene(); - + auto plane = scene->add_object(); scene->get(plane).name = "plane"; scene->get(plane).editor_object = true; @@ -93,24 +92,25 @@ Renderable* prepMaterialScene() { scene->get(plane).scale = prism::float3(50); scene->add(plane).mesh = assetm->get(prism::base_domain / "models/plane.model"); - scene->get(plane).materials.push_back(assetm->get(prism::base_domain / "materials/Material.material")); + scene->get(plane).materials.push_back( + assetm->get(prism::base_domain / "materials/Material.material")); auto sphere = scene->add_object(); scene->get(sphere).name = "sphere"; scene->get(sphere).editor_object = true; scene->get(sphere).rotation = euler_to_quat(prism::float3(radians(90.0f), 0, 0)); - + scene->add(sphere).mesh = assetm->get(prism::base_domain / "models/sphere.model"); prepThreePointLighting(); - + return &scene->get(sphere); } struct OpenAssetRequest { OpenAssetRequest(std::string p, bool is_r) : path(p), is_relative(is_r) {} - + std::string path; bool is_relative; }; @@ -120,7 +120,7 @@ std::vector open_requests; void PrismEditor::setup_editor(Editor*) {} void PrismEditor::open_asset(const prism::path path) { - if(path.extension() == ".prefab") { + if (path.extension() == ".prefab") { PrefabEditor* editor = new PrefabEditor(); editor->path = path.string(); setup_editor(editor); @@ -133,26 +133,26 @@ void PrismEditor::open_asset(const prism::path path) { editor->scene = engine->get_scene(); editors.push_back(editor); - } else if(path.extension() == ".scene") { + } else if (path.extension() == ".scene") { SceneEditor* editor = new SceneEditor(); editor->path = path.string(); setup_editor(editor); - + editor->scene = engine->load_scene(path); prepScene(); editors.push_back(editor); - } else if(path.extension() == ".material") { + } else if (path.extension() == ".material") { MaterialEditor* editor = new MaterialEditor(); editor->path = path.string(); setup_editor(editor); - + engine->create_empty_scene(); prepScene(); editor->renderable = prepMaterialScene(); editor->material = assetm->get(path); - + editor->setup_material(); editor->scene = engine->get_scene(); @@ -162,7 +162,7 @@ void PrismEditor::open_asset(const prism::path path) { } void PrismEditor::renderEditor(GFXCommandBuffer* command_buffer) { - for(auto [id, render_target] : viewport_render_targets) { + for (auto [id, render_target] : viewport_render_targets) { engine->get_renderer()->render(command_buffer, render_target.scene, *render_target.target, nullptr); } } @@ -176,42 +176,42 @@ void PrismEditor::drawUI() { if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { - if(ImGui::BeginMenu("New")) { - if(ImGui::MenuItem("Scene")) { + if (ImGui::BeginMenu("New")) { + if (ImGui::MenuItem("Scene")) { SceneEditor* editor = new SceneEditor(); editor->modified = true; setup_editor(editor); - + engine->create_empty_scene(); editor->scene = engine->get_scene(); prepScene(); editors.push_back(editor); } - - if(ImGui::MenuItem("Prefab")) { + + if (ImGui::MenuItem("Prefab")) { PrefabEditor* editor = new PrefabEditor(); editor->modified = true; setup_editor(editor); - + engine->create_empty_scene(); editor->scene = engine->get_scene(); prepScene(); editors.push_back(editor); } - - if(ImGui::MenuItem("Material")) { + + if (ImGui::MenuItem("Material")) { MaterialEditor* editor = new MaterialEditor(); editor->modified = true; setup_editor(editor); - + engine->create_empty_scene(); prepScene(); editor->material = assetm->add(); editor->renderable = prepMaterialScene(); editor->scene = engine->get_scene(); - + editor->setup_material(); editors.push_back(editor); @@ -220,32 +220,32 @@ void PrismEditor::drawUI() { ImGui::EndMenu(); } - if(ImGui::MenuItem("Open", "CTRL+O")) { + if (ImGui::MenuItem("Open", "CTRL+O")) { engine->get_imgui().open_dialog(true, [this](std::string path) { open_requests.emplace_back(path, false); - addOpenedFile(path); + addOpenedFile(path); }); } - const auto& recents = getOpenedFiles(); - if (ImGui::BeginMenu("Open Recent...", !recents.empty())) { - for (auto& file : recents) { - if (ImGui::MenuItem(file.c_str())) + const auto& recents = getOpenedFiles(); + if (ImGui::BeginMenu("Open Recent...", !recents.empty())) { + for (auto& file : recents) { + if (ImGui::MenuItem(file.c_str())) open_requests.emplace_back(file, false); - } + } - ImGui::Separator(); + ImGui::Separator(); - if (ImGui::MenuItem("Clear")) - clearOpenedFiles(); + if (ImGui::MenuItem("Clear")) + clearOpenedFiles(); - ImGui::EndMenu(); + ImGui::EndMenu(); } ImGui::Separator(); - if(ImGui::MenuItem("Quit", "CTRL+Q")) + if (ImGui::MenuItem("Quit", "CTRL+Q")) engine->quit(); ImGui::EndMenu(); @@ -254,48 +254,48 @@ void PrismEditor::drawUI() { ImGui::EndMainMenuBar(); } - for(auto& editor : editors) { - if(!editor->has_been_docked) { + for (auto& editor : editors) { + if (!editor->has_been_docked) { ImGui::DockBuilderDockWindow(editor->get_window_title().c_str(), dock_id); ImGui::DockBuilderFinish(dock_id); editor->has_been_docked = true; } - + const ImGuiID editor_dockspace = ImGui::GetID(editor); - - if(ImGui::DockBuilderGetNode(editor_dockspace) == nullptr) { - const auto size = ImGui::GetMainViewport()->Size; - ImGui::DockBuilderRemoveNode(editor_dockspace); - ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace); - ImGui::DockBuilderSetNodeSize(editor_dockspace, size); + if (ImGui::DockBuilderGetNode(editor_dockspace) == nullptr) { + const auto size = ImGui::GetMainViewport()->Size; - editor->setup_windows(editor_dockspace); + ImGui::DockBuilderRemoveNode(editor_dockspace); + ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace); + ImGui::DockBuilderSetNodeSize(editor_dockspace, size); - ImGui::DockBuilderFinish(editor_dockspace); + editor->setup_windows(editor_dockspace); + + ImGui::DockBuilderFinish(editor_dockspace); } - + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - + int window_flags = 0; - if(editor->has_menubar()) + if (editor->has_menubar()) window_flags |= ImGuiWindowFlags_MenuBar; - - if(editor->modified) + + if (editor->modified) window_flags |= ImGuiWindowFlags_UnsavedDocument; - + bool should_draw = ImGui::Begin(editor->get_window_title().c_str(), nullptr, window_flags); - + ImGui::PopStyleVar(); - + ImGui::DockSpace(editor_dockspace, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None); - - if(should_draw) { + + if (should_draw) { /*debugPass = editor->debug_pass; if(debugPass != nullptr) debugPass->selected_object = selected_object;*/ - + engine->set_current_scene(editor->get_scene()); set_undo_stack(&editor->undo_stack); editor->draw(this); @@ -303,7 +303,7 @@ void PrismEditor::drawUI() { ImGui::End(); } - + utility::erase_if(editors, [](Editor* editor) { return editor->wants_to_close; }); @@ -318,8 +318,8 @@ void PrismEditor::asset_selected(const std::filesystem::path& path, AssetType) { } void PrismEditor::updateEditor(float) { - for(auto [path, is_relative] : open_requests) + for (auto [path, is_relative] : open_requests) open_asset(path); - + open_requests.clear(); } diff --git a/tools/editor/src/sceneeditor.cpp b/tools/editor/src/sceneeditor.cpp index f8c103a..2795ba4 100755 --- a/tools/editor/src/sceneeditor.cpp +++ b/tools/editor/src/sceneeditor.cpp @@ -1,8 +1,8 @@ #include "sceneeditor.hpp" #include -#include #include +#include #include "engine.hpp" @@ -20,12 +20,12 @@ Scene* SceneEditor::get_scene() const { void SceneEditor::setup_windows(ImGuiID dockspace) { ImGuiID dock_main_id = dockspace; - + ImGuiID dock_id_top, dock_id_bottom; ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, 0.70f, &dock_id_top, &dock_id_bottom); - + ImGui::DockBuilderDockWindow(get_window_name("Assets").c_str(), dock_id_bottom); - + ImGuiID dock_id_left, dock_id_right; ImGui::DockBuilderSplitNode(dock_id_top, ImGuiDir_Left, 0.70f, &dock_id_left, &dock_id_right); @@ -34,7 +34,7 @@ void SceneEditor::setup_windows(ImGuiID dockspace) { ImGui::DockBuilderSplitNode(dock_id_left, ImGuiDir_Left, 0.20f, &dock_id_left, &dock_id_right); ImGui::DockBuilderDockWindow(get_window_name("Outliner").c_str(), dock_id_left); - + ImGui::DockBuilderDockWindow(get_window_name("Viewport").c_str(), dock_id_right); ImGui::DockBuilderDockWindow(get_window_name("Console").c_str(), dock_id_right); } @@ -42,7 +42,7 @@ void SceneEditor::setup_windows(ImGuiID dockspace) { void SceneEditor::draw(CommonEditor* editor) { if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) { - if(ImGui::MenuItem("Save", "CTRL+S")) { + if (ImGui::MenuItem("Save", "CTRL+S")) { if (path.empty()) { engine->get_imgui().save_dialog([this](std::string path) { this->path = path; @@ -50,68 +50,68 @@ void SceneEditor::draw(CommonEditor* editor) { engine->save_scene(path); }); } else { - engine->save_scene(path); + engine->save_scene(path); } } - if(ImGui::MenuItem("Save as...", "CTRL+S")) { + if (ImGui::MenuItem("Save as...", "CTRL+S")) { engine->get_imgui().save_dialog([this](std::string path) { this->path = path; engine->save_scene(path); }); } - + ImGui::Separator(); - - if(ImGui::MenuItem("Close")) + + if (ImGui::MenuItem("Close")) wants_to_close = true; ImGui::EndMenu(); } - + if (ImGui::BeginMenu("Edit")) { std::string previous_stack_name = "Undo"; bool undo_available = false; - + std::string next_stack_name = "Redo"; bool redo_available = false; - + if (auto command = undo_stack.get_last_command()) { undo_available = true; previous_stack_name += " " + command->get_name(); } - + if (auto command = undo_stack.get_next_command()) { redo_available = true; next_stack_name += " " + command->get_name(); } - + if (ImGui::MenuItem(previous_stack_name.c_str(), "CTRL+Z", false, undo_available)) undo_stack.undo(); if (ImGui::MenuItem(next_stack_name.c_str(), "CTRL+Y", false, redo_available)) undo_stack.redo(); - + ImGui::EndMenu(); } - - if(ImGui::BeginMenu("Add...")) { + + if (ImGui::BeginMenu("Add...")) { if (ImGui::MenuItem("Empty")) { auto new_obj = engine->get_scene()->add_object(); engine->get_scene()->get(new_obj).name = "new object"; - + auto& command = undo_stack.new_command(); command.id = new_obj; command.name = engine->get_scene()->get(new_obj).name; } - - if(ImGui::MenuItem("Prefab")) { + + if (ImGui::MenuItem("Prefab")) { engine->get_imgui().open_dialog(false, [](std::string path) { engine->add_prefab(*engine->get_scene(), path); }); } - + ImGui::EndMenu(); } @@ -130,63 +130,62 @@ void SceneEditor::draw(CommonEditor* editor) { } auto viewport_scene = engine->get_scene(); - if(viewport_scene != nullptr) { - if(showSceneSettings) { - if(begin("Scene Settings", &showSceneSettings)) { - + if (viewport_scene != nullptr) { + if (showSceneSettings) { + if (begin("Scene Settings", &showSceneSettings)) { } ImGui::End(); } - if(showOutliner) { - if(begin("Outliner", &showOutliner)) + if (showOutliner) { + if (begin("Outliner", &showOutliner)) editor->drawOutline(); ImGui::End(); } - if(showProperties) { - if(begin("Properties", &showProperties)) + if (showProperties) { + if (begin("Properties", &showProperties)) editor->drawPropertyEditor(); ImGui::End(); } - if(showViewport) { + if (showViewport) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - if(begin("Viewport", &showViewport)) + if (begin("Viewport", &showViewport)) editor->drawViewport(viewport_scene); ImGui::PopStyleVar(); ImGui::End(); } - - if(showUndoStack) { - if(begin("Undo Stack", &showUndoStack)) { - for(auto [i, command] : utility::enumerate(undo_stack.command_stack)) { + + if (showUndoStack) { + if (begin("Undo Stack", &showUndoStack)) { + for (auto [i, command] : utility::enumerate(undo_stack.command_stack)) { std::string name = command->get_name(); - if(i == undo_stack.stack_position) + if (i == undo_stack.stack_position) name = "-> " + name; - + ImGui::Selectable(name.c_str()); } } - + ImGui::End(); } - - if(showAssets) { - if(begin("Assets", &showAssets)) + + if (showAssets) { + if (begin("Assets", &showAssets)) editor->drawAssets(); - + ImGui::End(); } - - if(begin("Console")) + + if (begin("Console")) editor->drawConsole(); - + ImGui::End(); } } diff --git a/tools/fontcompiler/main.cpp b/tools/fontcompiler/main.cpp index ebd64ad..03a62eb 100755 --- a/tools/fontcompiler/main.cpp +++ b/tools/fontcompiler/main.cpp @@ -1,15 +1,12 @@ #include -#include #include #include +#include #include -constexpr std::array sizes_to_pack = { - 36.0f, - 24.0f -}; +constexpr std::array sizes_to_pack = {36.0f, 24.0f}; constexpr int num_glyphs = 95; constexpr int texture_width = 2048, texture_height = 1150; @@ -42,7 +39,7 @@ void load_ttf(const std::string_view path) { } int main(int argc, char* argv[]) { - if(argc != 3) { + if (argc != 3) { std::cout << "Usage: FontCompiler [input ttf] [output fp]" << std::endl; return 0; } @@ -53,14 +50,14 @@ int main(int argc, char* argv[]) { stbtt_PackSetOversampling(&pack_context, 2, 2); stbtt_pack_range ranges[sizes_to_pack.size()]; - for(int i = 0; i < sizes_to_pack.size(); i++) + for (int i = 0; i < sizes_to_pack.size(); i++) ranges[i] = {sizes_to_pack[i], 32, nullptr, 95, packed_chars[i], 0, 0}; stbtt_PackFontRanges(&pack_context, font_data, 0, ranges, sizes_to_pack.size()); stbtt_PackEnd(&pack_context); FILE* file = fopen(argv[2], "wb"); - if(!file) + if (!file) return -1; fwrite(&texture_width, sizeof(int), 1, file); @@ -73,10 +70,10 @@ int main(int argc, char* argv[]) { fwrite(&descent, sizeof(int), 1, file); fwrite(&gap, sizeof(int), 1, file); - for(auto& packed_char : packed_chars) + for (auto& packed_char : packed_chars) fwrite(&packed_char, sizeof(packed_char), 1, file); - for(auto& range : ranges) { + for (auto& range : ranges) { const float f = (ascent + descent) * stbtt_ScaleForPixelHeight(&font_info, range.font_size); fwrite(&f, sizeof(float), 1, file); } diff --git a/tools/modelcompiler/CMakeLists.txt b/tools/modelcompiler/CMakeLists.txt index 988c00f..6d42828 100755 --- a/tools/modelcompiler/CMakeLists.txt +++ b/tools/modelcompiler/CMakeLists.txt @@ -1,16 +1,16 @@ add_platform_executable( - TARGET ModelCompiler - APP_CLASS ModelEditor - APP_INCLUDE modeleditor.hpp - SRC - src/modeleditor.cpp - include/modeleditor.hpp - SKIP_DATA TRUE) + TARGET ModelCompiler + APP_CLASS ModelEditor + APP_INCLUDE modeleditor.hpp + SRC + src/modeleditor.cpp + include/modeleditor.hpp + SKIP_DATA TRUE) target_link_libraries(ModelCompiler PUBLIC - Core - EditorCommon - PRIVATE - assimp) + Core + EditorCommon + PRIVATE + assimp) target_include_directories(ModelCompiler PUBLIC - include) + include) set_engine_properties(ModelCompiler) diff --git a/tools/modelcompiler/include/modeleditor.hpp b/tools/modelcompiler/include/modeleditor.hpp index 71759be..3b635ea 100755 --- a/tools/modelcompiler/include/modeleditor.hpp +++ b/tools/modelcompiler/include/modeleditor.hpp @@ -3,19 +3,19 @@ #include "commoneditor.hpp" class ModelEditor : public CommonEditor { -public: - ModelEditor(); +public: + ModelEditor(); + + void drawUI() override; - void drawUI() override; - struct Flags { bool hide_ui = false; bool compile_static = false; bool export_animations = true; bool export_materials = true; } flags; - + std::string data_path, model_path; - + void compile_model(std::string compiled_model_path); }; diff --git a/tools/modelcompiler/src/modeleditor.cpp b/tools/modelcompiler/src/modeleditor.cpp index dd6e3a5..bb71b27 100755 --- a/tools/modelcompiler/src/modeleditor.cpp +++ b/tools/modelcompiler/src/modeleditor.cpp @@ -1,15 +1,15 @@ #include "modeleditor.hpp" -#include -#include -#include -#include -#include #include #include #include -#include +#include #include +#include +#include +#include +#include +#include #include "engine.hpp" #include "file.hpp" @@ -23,24 +23,23 @@ void app_main(prism::engine* engine) { engine->debug_enabled = false; engine->console_enabled = false; - if(utility::contains(engine->command_line_arguments, "--no_ui")) + if (utility::contains(engine->command_line_arguments, "--no_ui")) editor->flags.hide_ui = true; - if(!editor->flags.hide_ui) { - platform::open_window("Model Compiler", - {editor->getDefaultX(), editor->getDefaultY(), 300, 300}, - WindowFlags::None); + if (!editor->flags.hide_ui) { + platform::open_window( + "Model Compiler", {editor->getDefaultX(), editor->getDefaultY(), 300, 300}, WindowFlags::None); } else { std::string compiled_model_path; - for(auto [i, argument] : utility::enumerate(engine->command_line_arguments)) { - if(argument == "--model-path") + for (auto [i, argument] : utility::enumerate(engine->command_line_arguments)) { + if (argument == "--model-path") editor->model_path = engine->command_line_arguments[i + 1]; - if(argument == "--compiled-model-path") + if (argument == "--compiled-model-path") compiled_model_path = engine->command_line_arguments[i + 1]; - if(argument == "--compile-static") + if (argument == "--compile-static") editor->flags.compile_static = true; } @@ -56,9 +55,9 @@ void app_main(prism::engine* engine) { ModelEditor::ModelEditor() : CommonEditor("ModelEditor") {} void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiString& parent) { - for(int i = 0; i < node->mNumChildren; i++) { + for (int i = 0; i < node->mNumChildren; i++) { aiNode* child = node->mChildren[i]; - if(child->mName == bone->mName) { + if (child->mName == bone->mName) { parent = node->mName; } else { traverseNode(scene, child, bone, parent); @@ -67,9 +66,9 @@ void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiStri } void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiVector3D& pos) { - for(int i = 0; i < node->mNumChildren; i++) { + for (int i = 0; i < node->mNumChildren; i++) { aiNode* child = node->mChildren[i]; - if(child->mName == bone->mName) { + if (child->mName == bone->mName) { aiVector3D scale, position; aiQuaternion rotation; @@ -83,9 +82,9 @@ void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiVect } void traverseNodeScale(const aiScene* scene, aiNode* node, const aiBone* bone, aiVector3D& pos) { - for(int i = 0; i < node->mNumChildren; i++) { + for (int i = 0; i < node->mNumChildren; i++) { aiNode* child = node->mChildren[i]; - if(child->mName == bone->mName) { + if (child->mName == bone->mName) { aiVector3D scale, position; aiQuaternion rotation; @@ -99,9 +98,9 @@ void traverseNodeScale(const aiScene* scene, aiNode* node, const aiBone* bone, a } void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiQuaternion& rot) { - for(int i = 0; i < node->mNumChildren; i++) { + for (int i = 0; i < node->mNumChildren; i++) { aiNode* child = node->mChildren[i]; - if(child->mName == bone->mName) { + if (child->mName == bone->mName) { aiVector3D scale, position; aiQuaternion rotation; @@ -148,7 +147,7 @@ aiVector3D getBoneScale(const aiScene* scene, const aiBone* bone) { void write_string(FILE* file, const aiString& str) { fwrite(&str.length, sizeof(unsigned int), 1, file); - if(str.length > 0) { + if (str.length > 0) { fwrite(str.C_Str(), sizeof(char) * str.length, 1, file); prism::log("writing string {}", str.C_Str()); } @@ -158,7 +157,7 @@ void write_string(FILE* file, const std::string& str) { unsigned int len = str.length(); fwrite(&len, sizeof(unsigned int), 1, file); - if(str.length() > 0) { + if (str.length() > 0) { fwrite(str.c_str(), sizeof(char) * len, 1, file); prism::log("writing string {}", str.c_str()); } @@ -169,13 +168,13 @@ void ModelEditor::compile_model(std::string compiled_model_path) { unsigned int vertex_index = 0, bone_index = 0; float weight = 0.0f; }; - + constexpr int max_weights_per_vertex = 4; - + struct BoneVertexData { std::array ids; std::array weights; - + void add(int boneID, float boneWeight) { for (int i = 0; i < max_weights_per_vertex; i++) { if (weights[i] == 0.0f) { @@ -186,31 +185,27 @@ void ModelEditor::compile_model(std::string compiled_model_path) { } } }; - + Assimp::Importer importer; - unsigned int importer_flags = - aiProcess_Triangulate | - aiProcess_ImproveCacheLocality | - aiProcess_JoinIdenticalVertices | - aiProcess_OptimizeMeshes | - aiProcess_CalcTangentSpace | - aiProcess_GenNormals; + unsigned int importer_flags = aiProcess_Triangulate | aiProcess_ImproveCacheLocality | + aiProcess_JoinIdenticalVertices | aiProcess_OptimizeMeshes | + aiProcess_CalcTangentSpace | aiProcess_GenNormals; - if(flags.compile_static) { + if (flags.compile_static) { importer.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 1.0); - + importer_flags |= aiProcess_GlobalScale; importer_flags |= aiProcess_PreTransformVertices; - + aiMatrix4x4 matrix; - + importer.SetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, matrix); importer.SetPropertyBool(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, true); } - + const aiScene* sc = importer.ReadFile(model_path.c_str(), importer_flags); - + auto name = model_path.substr(model_path.find_last_of("/") + 1, model_path.length()); name = name.substr(0, name.find_last_of(".")); @@ -220,183 +215,183 @@ void ModelEditor::compile_model(std::string compiled_model_path) { int version = 7; fwrite(&version, sizeof(int), 1, file); - + std::vector meshToMaterial; meshToMaterial.resize(sc->mNumMeshes); std::map matNameToIndex; int last_material = 0; - + std::vector positions; - + enum MeshType : int { Static, Skinned } mesh_type = MeshType::Static; - + std::vector normals; std::vector texture_coords; std::vector tangents, bitangents; - + std::vector bone_vertex_data; - - for(unsigned int i = 0; i < sc->mNumMeshes; i++) { + + for (unsigned int i = 0; i < sc->mNumMeshes; i++) { aiMesh* mesh = sc->mMeshes[i]; - - if(mesh->HasBones()) + + if (mesh->HasBones()) mesh_type = MeshType::Skinned; } - + std::vector indices; - + std::vector bone_weights; aiMesh* armature_mesh = nullptr; int vertex_offset = 0; - for(unsigned int i = 0; i < sc->mNumMeshes; i++) { + for (unsigned int i = 0; i < sc->mNumMeshes; i++) { aiMesh* mesh = sc->mMeshes[i]; - if(armature_mesh == nullptr && mesh->mNumBones != 0) { + if (armature_mesh == nullptr && mesh->mNumBones != 0) { armature_mesh = mesh; } - + for (unsigned int v = 0; v < mesh->mNumVertices; v++) { positions.push_back(mesh->mVertices[v]); normals.push_back(mesh->mNormals[v]); - - if(mesh->HasTextureCoords(0)) { + + if (mesh->HasTextureCoords(0)) { texture_coords.emplace_back(mesh->mTextureCoords[0][v].x, mesh->mTextureCoords[0][v].y); } else { texture_coords.emplace_back(0, 0); } - + tangents.push_back(mesh->mTangents[v]); bitangents.push_back(mesh->mBitangents[v]); } - + for (unsigned int e = 0; e < mesh->mNumFaces; e++) { const aiFace& face = mesh->mFaces[e]; - + indices.push_back(face.mIndices[0]); indices.push_back(face.mIndices[1]); indices.push_back(face.mIndices[2]); } - - for(unsigned int b = 0; b < mesh->mNumBones; b++) { - for(int y = 0; y < mesh->mBones[b]->mNumWeights; y++) { + + for (unsigned int b = 0; b < mesh->mNumBones; b++) { + for (int y = 0; y < mesh->mBones[b]->mNumWeights; y++) { BoneWeight bw; bw.bone_index = b; bw.vertex_index = vertex_offset + mesh->mBones[b]->mWeights[y].mVertexId; bw.weight = mesh->mBones[b]->mWeights[y].mWeight; - + bone_weights.push_back(bw); } } - + std::string material = sc->mMaterials[mesh->mMaterialIndex]->GetName().C_Str(); meshToMaterial[i] = material; - - if(!matNameToIndex.count(material)) + + if (!matNameToIndex.count(material)) matNameToIndex[material] = last_material++; - + vertex_offset += mesh->mNumVertices; } - - if(mesh_type == MeshType::Skinned) { + + if (mesh_type == MeshType::Skinned) { bone_vertex_data.resize(positions.size()); - - for(auto bw : bone_weights) + + for (auto bw : bone_weights) bone_vertex_data[bw.vertex_index].add(bw.bone_index, bw.weight); } - + fwrite(&mesh_type, sizeof(int), 1, file); - + int vert_len = positions.size(); fwrite(&vert_len, sizeof(int), 1, file); - + const auto write_buffer = [numVertices = positions.size(), file](auto vec, unsigned int size) { - for(unsigned int i = 0; i < numVertices; i++) { + for (unsigned int i = 0; i < numVertices; i++) { fwrite(&vec[i], size, 1, file); } }; - + write_buffer(positions, sizeof(prism::float3)); write_buffer(normals, sizeof(prism::float3)); write_buffer(texture_coords, sizeof(prism::float2)); write_buffer(tangents, sizeof(prism::float3)); write_buffer(bitangents, sizeof(prism::float3)); - if(mesh_type == MeshType::Skinned) + if (mesh_type == MeshType::Skinned) write_buffer(bone_vertex_data, sizeof(BoneVertexData)); - + int element_len = indices.size(); fwrite(&element_len, sizeof(int), 1, file); - + fwrite(indices.data(), sizeof(uint32_t) * indices.size(), 1, file); - + int bone_len = 0; - if(armature_mesh != nullptr) { + if (armature_mesh != nullptr) { bone_len = armature_mesh->mNumBones; } - + fwrite(&bone_len, sizeof(int), 1, file); - - if(bone_len > 0) { + + if (bone_len > 0) { auto transform = sc->mRootNode->mTransformation; transform.Inverse(); transform.Transpose(); - + fwrite(&transform, sizeof(aiMatrix4x4), 1, file); - + for (unsigned int b = 0; b < armature_mesh->mNumBones; b++) { const aiBone* aBone = armature_mesh->mBones[b]; - + write_string(file, aBone->mName); write_string(file, findBoneParent(sc, aBone)); - + auto pos = getBonePosition(sc, aBone); - + fwrite(&pos, sizeof(float) * 3, 1, file); - + auto rot = getBoneRotation(sc, aBone); - + fwrite(&rot, sizeof(float) * 4, 1, file); - + auto scl = getBoneScale(sc, aBone); - + fwrite(&scl, sizeof(float) * 3, 1, file); } } - + fwrite(&sc->mNumMeshes, sizeof(int), 1, file); - + for (unsigned int i = 0; i < sc->mNumMeshes; i++) { const aiMesh* mesh = sc->mMeshes[i]; write_string(file, mesh->mName); - + float min_x = 0.0f, min_y = 0.0f, min_z = 0.0f; float max_x = 0.0f, max_y = 0.0f, max_z = 0.0f; - for(unsigned int i = 0; i < mesh->mNumVertices; i++) { + for (unsigned int i = 0; i < mesh->mNumVertices; i++) { auto vertex_pos = mesh->mVertices[i]; - - if(vertex_pos.x < min_x) + + if (vertex_pos.x < min_x) min_x = vertex_pos.x; - else if(vertex_pos.x > max_x) + else if (vertex_pos.x > max_x) max_x = vertex_pos.x; - - if(vertex_pos.y < min_y) + + if (vertex_pos.y < min_y) min_y = vertex_pos.y; - else if(vertex_pos.y > max_y) + else if (vertex_pos.y > max_y) max_y = vertex_pos.y; - - if(vertex_pos.z < min_z) + + if (vertex_pos.z < min_z) min_z = vertex_pos.z; - else if(vertex_pos.z > max_z) + else if (vertex_pos.z > max_z) max_z = vertex_pos.z; } - + prism::aabb aabb; aabb.min = prism::float3(min_x, min_y, min_z); aabb.max = prism::float3(max_x, max_y, max_z); @@ -406,14 +401,14 @@ void ModelEditor::compile_model(std::string compiled_model_path) { unsigned int numIndices = mesh->mNumFaces * 3; fwrite(&numIndices, sizeof(int), 1, file); - + int numOffsetMatrices = mesh->mNumBones; fwrite(&numOffsetMatrices, sizeof(int), 1, file); - - for(int b = 0; b < mesh->mNumBones; b++) { + + for (int b = 0; b < mesh->mNumBones; b++) { auto offset = mesh->mBones[b]->mOffsetMatrix; offset.Transpose(); - + fwrite(&offset, sizeof(aiMatrix4x4), 1, file); } @@ -427,20 +422,20 @@ void ModelEditor::compile_model(std::string compiled_model_path) { fmt::print("Finished writing model!\n"); - if(flags.export_materials) { - for(int i = 0; i < sc->mNumMaterials; i++) { + if (flags.export_materials) { + for (int i = 0; i < sc->mNumMaterials; i++) { auto path = data_path + "/materials/" + sc->mMaterials[i]->GetName().C_Str() + ".material"; Material mat; aiColor4D color; - aiGetMaterialColor(sc->mMaterials[i], AI_MATKEY_COLOR_DIFFUSE,&color); + aiGetMaterialColor(sc->mMaterials[i], AI_MATKEY_COLOR_DIFFUSE, &color); mat.colorProperty.type = DataType::Vector3; mat.colorProperty.value = prism::float3(color.r, color.g, color.b); aiString diffuse_path; - if(aiReturn_SUCCESS == aiGetMaterialTexture(sc->mMaterials[i], aiTextureType_DIFFUSE, 0, &diffuse_path)) { + if (aiReturn_SUCCESS == aiGetMaterialTexture(sc->mMaterials[i], aiTextureType_DIFFUSE, 0, &diffuse_path)) { mat.colorProperty.type = DataType::AssetTexture; mat.colorProperty.value_tex.handle = new Texture(); mat.colorProperty.value_tex->path = std::string("textures/") + diffuse_path.C_Str(); @@ -448,7 +443,7 @@ void ModelEditor::compile_model(std::string compiled_model_path) { } aiString normal_path; - if(aiReturn_SUCCESS == aiGetMaterialTexture(sc->mMaterials[i], aiTextureType_NORMALS, 0, &normal_path)) { + if (aiReturn_SUCCESS == aiGetMaterialTexture(sc->mMaterials[i], aiTextureType_NORMALS, 0, &normal_path)) { mat.normalProperty.type = DataType::AssetTexture; mat.normalProperty.value_tex.handle = new Texture(); mat.normalProperty.value_tex->path = std::string("textures/") + normal_path.C_Str(); @@ -459,12 +454,12 @@ void ModelEditor::compile_model(std::string compiled_model_path) { } } - if(flags.export_animations) { - for(auto i = 0; i < sc->mNumAnimations; i++) { + if (flags.export_animations) { + for (auto i = 0; i < sc->mNumAnimations; i++) { const aiAnimation* animation = sc->mAnimations[i]; std::string animName = animation->mName.C_Str(); - if(animName.length() == 0) + if (animName.length() == 0) animName = "default"; std::string finalName = (name + animName + ".anim"); @@ -478,16 +473,19 @@ void ModelEditor::compile_model(std::string compiled_model_path) { fwrite(&animation->mNumChannels, sizeof(unsigned int), 1, file); - for(auto j = 0; j < animation->mNumChannels; j++) { + for (auto j = 0; j < animation->mNumChannels; j++) { const aiNodeAnim* channel = animation->mChannels[j]; write_string(file, channel->mNodeName); fwrite(&channel->mNumPositionKeys, sizeof(unsigned int), 1, file); - for(auto k = 0; k < channel->mNumPositionKeys; k++) { + for (auto k = 0; k < channel->mNumPositionKeys; k++) { PositionKeyFrame key; - key.value = prism::float3(channel->mPositionKeys[k].mValue.x, channel->mPositionKeys[k].mValue.y, channel->mPositionKeys[k].mValue.z); + key.value = prism::float3( + channel->mPositionKeys[k].mValue.x, + channel->mPositionKeys[k].mValue.y, + channel->mPositionKeys[k].mValue.z); key.time = channel->mPositionKeys[k].mTime; fwrite(&key, sizeof(PositionKeyFrame), 1, file); @@ -495,9 +493,13 @@ void ModelEditor::compile_model(std::string compiled_model_path) { fwrite(&channel->mNumRotationKeys, sizeof(unsigned int), 1, file); - for(auto k = 0; k < channel->mNumRotationKeys; k++) { + for (auto k = 0; k < channel->mNumRotationKeys; k++) { RotationKeyFrame key; - key.value = Quaternion(channel->mRotationKeys[k].mValue.x, channel->mRotationKeys[k].mValue.y, channel->mRotationKeys[k].mValue.z, channel->mRotationKeys[k].mValue.w); + key.value = Quaternion( + channel->mRotationKeys[k].mValue.x, + channel->mRotationKeys[k].mValue.y, + channel->mRotationKeys[k].mValue.z, + channel->mRotationKeys[k].mValue.w); key.time = channel->mRotationKeys[k].mTime; fwrite(&key, sizeof(RotationKeyFrame), 1, file); @@ -505,9 +507,12 @@ void ModelEditor::compile_model(std::string compiled_model_path) { fwrite(&channel->mNumScalingKeys, sizeof(unsigned int), 1, file); - for(auto k = 0; k < channel->mNumScalingKeys; k++) { + for (auto k = 0; k < channel->mNumScalingKeys; k++) { ScaleKeyFrame key; - key.value = prism::float3(channel->mScalingKeys[k].mValue.x, channel->mScalingKeys[k].mValue.y, channel->mScalingKeys[k].mValue.z); + key.value = prism::float3( + channel->mScalingKeys[k].mValue.x, + channel->mScalingKeys[k].mValue.y, + channel->mScalingKeys[k].mValue.z); key.time = channel->mScalingKeys[k].mTime; fwrite(&key, sizeof(ScaleKeyFrame), 1, file); @@ -523,31 +528,35 @@ void ModelEditor::drawUI() { auto viewport = ImGui::GetMainViewport(); - ImGui::Begin("mcompile", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration); + ImGui::Begin( + "mcompile", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration); ImGui::SetWindowPos(viewport->Pos, ImGuiCond_Always); ImGui::SetWindowSize(viewport->Size, ImGuiCond_Always); - if(ImGui::Button("Open model to compile...")) { + if (ImGui::Button("Open model to compile...")) { engine->get_imgui().open_dialog(true, [this](std::string path) { model_path = path; }); } - if(ImGui::Button("Open data path...")) { - engine->get_imgui().open_dialog(true, [this](std::string path) { - data_path = path; - }, true); + if (ImGui::Button("Open data path...")) { + engine->get_imgui().open_dialog( + true, + [this](std::string path) { + data_path = path; + }, + true); } ImGui::Checkbox("Compile as static (remove transforms)", &flags.compile_static); ImGui::Checkbox("Export materials", &flags.export_materials); ImGui::Checkbox("Export animations", &flags.export_animations); - if(!model_path.empty() && !data_path.empty()) { + if (!model_path.empty() && !data_path.empty()) { ImGui::Text("%s will be compiled for data path %s", model_path.c_str(), data_path.c_str()); - if(ImGui::Button("Compile")) { + if (ImGui::Button("Compile")) { auto name = model_path.substr(model_path.find_last_of("/") + 1, model_path.length()); name = name.substr(0, name.find_last_of(".")); compile_model(data_path + "/models/" + name + ".model"); diff --git a/tools/shadercompiler/CMakeLists.txt b/tools/shadercompiler/CMakeLists.txt index a361993..b6fbf56 100755 --- a/tools/shadercompiler/CMakeLists.txt +++ b/tools/shadercompiler/CMakeLists.txt @@ -1,8 +1,8 @@ add_executable(ShaderCompilerTool main.cpp) target_link_libraries(ShaderCompilerTool - PRIVATE - ShaderCompiler - Log - Utility) + PRIVATE + ShaderCompiler + Log + Utility) set_engine_properties(ShaderCompilerTool) set_output_dir(ShaderCompilerTool) diff --git a/tools/shadercompiler/DirStackIncluder.h b/tools/shadercompiler/DirStackIncluder.h index 9625198..f8b1368 100755 --- a/tools/shadercompiler/DirStackIncluder.h +++ b/tools/shadercompiler/DirStackIncluder.h @@ -36,10 +36,10 @@ #pragma once -#include -#include -#include #include +#include +#include +#include #include @@ -48,19 +48,15 @@ // Can be overridden to customize. class DirStackFileIncluder : public glslang::TShader::Includer { public: - DirStackFileIncluder() : externalLocalDirectoryCount(0) { } + DirStackFileIncluder() : externalLocalDirectoryCount(0) {} - virtual IncludeResult* includeLocal(const char* headerName, - const char* includerName, - size_t inclusionDepth) override - { + virtual IncludeResult* + includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override { return readLocalPath(headerName, includerName, (int)inclusionDepth); } - virtual IncludeResult* includeSystem(const char* headerName, - const char* /*includerName*/, - size_t /*inclusionDepth*/) override - { + virtual IncludeResult* + includeSystem(const char* headerName, const char* /*includerName*/, size_t /*inclusionDepth*/) override { return readSystemPath(headerName); } @@ -70,21 +66,19 @@ public: // is checked. // - This only applies to the "local" form of #include. // - Makes its own copy of the path. - virtual void pushExternalLocalDirectory(const std::string& dir) - { + virtual void pushExternalLocalDirectory(const std::string& dir) { directoryStack.push_back(dir); externalLocalDirectoryCount = (int)directoryStack.size(); } - virtual void releaseInclude(IncludeResult* result) override - { + virtual void releaseInclude(IncludeResult* result) override { if (result != nullptr) { - delete [] static_cast(result->userData); + delete[] static_cast(result->userData); delete result; } } - virtual ~DirStackFileIncluder() override { } + virtual ~DirStackFileIncluder() override {} protected: typedef char tUserDataElement; @@ -93,8 +87,7 @@ protected: // Search for a valid "local" path based on combining the stack of include // directories and the nominal name of the header. - virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) - { + virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) { // Discard popped include directories, and // initialize when at parse-time first level. directoryStack.resize(depth + externalLocalDirectoryCount); @@ -117,15 +110,13 @@ protected: // Search for a valid path. // Not implemented yet; returning nullptr signals failure to find. - virtual IncludeResult* readSystemPath(const char* /*headerName*/) const - { + virtual IncludeResult* readSystemPath(const char* /*headerName*/) const { return nullptr; } // Do actual reading of the file, filling in a new include result. - virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const - { - char* content = new tUserDataElement [length]; + virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const { + char* content = new tUserDataElement[length]; file.seekg(0, file.beg); file.read(content, length); return new IncludeResult(path, content, length, content); @@ -133,8 +124,7 @@ protected: // If no path markers, return current working directory. // Otherwise, strip file name and return path leading up to it. - virtual std::string getDirectory(const std::string path) const - { + virtual std::string getDirectory(const std::string path) const { size_t last = path.find_last_of("/\\"); return last == std::string::npos ? "." : path.substr(0, last); } diff --git a/tools/shadercompiler/main.cpp b/tools/shadercompiler/main.cpp index 20bf05d..9062ae3 100755 --- a/tools/shadercompiler/main.cpp +++ b/tools/shadercompiler/main.cpp @@ -1,8 +1,8 @@ -#include #include +#include -#include "shadercompiler.hpp" #include "log.hpp" +#include "shadercompiler.hpp" #include "string_utils.hpp" bool has_extension(const std::filesystem::path& path, const std::string_view extension) { @@ -10,11 +10,11 @@ bool has_extension(const std::filesystem::path& path, const std::string_view ext } int main(int argc, char* argv[]) { - if(argc < 2) { + if (argc < 2) { prism::log("Not enough arguments!"); return -1; } - + shader_compiler.set_include_path(std::filesystem::current_path().string()); std::filesystem::path source_path = argv[1]; @@ -22,75 +22,70 @@ int main(int argc, char* argv[]) { ShaderLanguage language = ShaderLanguage::SPIRV; std::string_view shader_language_string = argv[3]; - if(shader_language_string == "spv") { + if (shader_language_string == "spv") { language = ShaderLanguage::SPIRV; - } else if(shader_language_string == "msl") { + } else if (shader_language_string == "msl") { language = ShaderLanguage::MSL; - } else if(shader_language_string == "glsl") { + } else if (shader_language_string == "glsl") { language = ShaderLanguage::GLSL; - } else if(shader_language_string == "hlsl") { + } else if (shader_language_string == "hlsl") { language = ShaderLanguage::HLSL; } CompileOptions options; std::string_view extra_options = argc > 4 ? argv[4] : ""; - if(extra_options == "mobile") + if (extra_options == "mobile") options.is_apple_mobile = true; std::ifstream t(source_path); std::stringstream buffer; buffer << t.rdbuf(); - - if(has_extension(source_path, "nocompile")) { + + if (has_extension(source_path, "nocompile")) { destination_path = remove_substring(destination_path.string(), ".nocompile"); // remove extension std::ofstream out(destination_path); out << buffer.rdbuf(); } else { ShaderStage stage = ShaderStage::Vertex; - if(has_extension(source_path, ".vert")) + if (has_extension(source_path, ".vert")) stage = ShaderStage::Vertex; - else if(has_extension(source_path, ".frag")) + else if (has_extension(source_path, ".frag")) stage = ShaderStage::Fragment; - else if(has_extension(source_path, ".comp")) + else if (has_extension(source_path, ".comp")) stage = ShaderStage::Compute; - const auto compiled_source = shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(buffer.str()), language, options); - if(!compiled_source.has_value()) { + const auto compiled_source = + shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(buffer.str()), language, options); + if (!compiled_source.has_value()) { prism::log("Error when compiling {}!", source_path.string()); return -1; } - - switch(language) { + + switch (language) { // right now, WGSL is outputted as SPIR-V with some WGSL compatibility stuff included - case ShaderLanguage::SPIRV: - { + case ShaderLanguage::SPIRV: { const auto spirv = compiled_source->as_bytecode(); - + std::ofstream out(destination_path, std::ios::binary); // remove .glsl out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t)); - } - break; - case ShaderLanguage::MSL: - { + } break; + case ShaderLanguage::MSL: { std::ofstream out(destination_path); // remove .glsl out << compiled_source->as_string(); - } - break; - case ShaderLanguage::HLSL: - { + } break; + case ShaderLanguage::HLSL: { std::ofstream out(destination_path); // remove .glsl out << compiled_source->as_string(); - } - break; + } break; default: break; } } // TODO: output disabled for now, will have to expose in a better arg system - //prism::log::info(System::Core, "Successfully written shader from {} to {}.", source_path, destination_path); + // prism::log::info(System::Core, "Successfully written shader from {} to {}.", source_path, destination_path); return 0; }