Reformat editor code
This commit is contained in:
parent
c0928ea80c
commit
68d4512763
27 changed files with 1364 additions and 1323 deletions
|
@ -1,14 +1,14 @@
|
||||||
set(CMAKE_FOLDER "Tools")
|
set(CMAKE_FOLDER "Tools")
|
||||||
|
|
||||||
if(NOT NEEDS_HOSTED_SHADER_COMPILER)
|
if (NOT NEEDS_HOSTED_SHADER_COMPILER)
|
||||||
add_subdirectory(shadercompiler)
|
add_subdirectory(shadercompiler)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(BUILD_TOOLS)
|
if (BUILD_TOOLS)
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
add_subdirectory(assetpipeline)
|
add_subdirectory(assetpipeline)
|
||||||
add_subdirectory(fontcompiler)
|
add_subdirectory(fontcompiler)
|
||||||
add_subdirectory(editor)
|
add_subdirectory(editor)
|
||||||
add_subdirectory(modelcompiler)
|
add_subdirectory(modelcompiler)
|
||||||
add_subdirectory(cutsceneeditor)
|
add_subdirectory(cutsceneeditor)
|
||||||
endif()
|
endif ()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
@ -11,8 +11,8 @@ int main(int argc, char* argv[]) {
|
||||||
std::string gameDirectory = argv[2];
|
std::string gameDirectory = argv[2];
|
||||||
fmt::print("Game directory to output compiled assets in: {}\n", gameDirectory);
|
fmt::print("Game directory to output compiled assets in: {}\n", gameDirectory);
|
||||||
|
|
||||||
for(auto const& dir_entry : std::filesystem::recursive_directory_iterator{dataDirectory}) {
|
for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{dataDirectory}) {
|
||||||
if(dir_entry.path().extension() == ".fbx") {
|
if (dir_entry.path().extension() == ".fbx") {
|
||||||
|
|
||||||
fmt::print("Found fbx: {}\n", dir_entry.path().c_str());
|
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());
|
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");
|
fmt::print("Compiled version does not exist!\n");
|
||||||
|
|
||||||
std::vector<std::string> model_compiler_args;
|
std::vector<std::string> model_compiler_args;
|
||||||
|
@ -34,7 +34,7 @@ int main(int argc, char* argv[]) {
|
||||||
model_compiler_args.emplace_back(new_game_path.c_str());
|
model_compiler_args.emplace_back(new_game_path.c_str());
|
||||||
|
|
||||||
std::string compiled_command;
|
std::string compiled_command;
|
||||||
for(const auto& arg : model_compiler_args) {
|
for (const auto& arg : model_compiler_args) {
|
||||||
compiled_command += arg + " ";
|
compiled_command += arg + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
set(SRC
|
set(SRC
|
||||||
include/commoneditor.hpp
|
include/commoneditor.hpp
|
||||||
include/debugpass.hpp
|
include/debugpass.hpp
|
||||||
include/undostack.hpp
|
include/undostack.hpp
|
||||||
|
|
||||||
src/commoneditor.cpp
|
src/commoneditor.cpp
|
||||||
src/debugpass.cpp
|
src/debugpass.cpp
|
||||||
src/undostack.cpp)
|
src/undostack.cpp)
|
||||||
|
|
||||||
add_library(EditorCommon ${SRC})
|
add_library(EditorCommon ${SRC})
|
||||||
target_include_directories(EditorCommon PUBLIC include)
|
target_include_directories(EditorCommon PUBLIC include)
|
||||||
target_link_libraries(EditorCommon PUBLIC
|
target_link_libraries(EditorCommon PUBLIC
|
||||||
Renderer
|
Renderer
|
||||||
imgui
|
imgui
|
||||||
Core)
|
Core)
|
||||||
set_engine_properties(EditorCommon)
|
set_engine_properties(EditorCommon)
|
||||||
|
|
|
@ -4,39 +4,39 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "app.hpp"
|
#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 "utility.hpp"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "math.hpp"
|
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
#include "platform.hpp"
|
#include <imgui_stdlib.h>
|
||||||
#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"
|
|
||||||
|
|
||||||
class TransformCommand : public Command {
|
class TransformCommand : public Command {
|
||||||
public:
|
public:
|
||||||
prism::Object transformed;
|
prism::Object transformed;
|
||||||
|
|
||||||
Transform old_transform, new_transform;
|
Transform old_transform, new_transform;
|
||||||
|
|
||||||
std::string fetch_name() override {
|
std::string fetch_name() override {
|
||||||
return "Transform " + engine->get_scene()->get(transformed).name;
|
return "Transform " + engine->get_scene()->get(transformed).name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo() override {
|
void undo() override {
|
||||||
engine->get_scene()->get<Transform>(transformed) = old_transform;
|
engine->get_scene()->get<Transform>(transformed) = old_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute() override {
|
void execute() override {
|
||||||
engine->get_scene()->get<Transform>(transformed) = new_transform;
|
engine->get_scene()->get<Transform>(transformed) = new_transform;
|
||||||
}
|
}
|
||||||
|
@ -45,17 +45,17 @@ public:
|
||||||
class RenameCommand : public Command {
|
class RenameCommand : public Command {
|
||||||
public:
|
public:
|
||||||
prism::Object object;
|
prism::Object object;
|
||||||
|
|
||||||
std::string old_name, new_name;
|
std::string old_name, new_name;
|
||||||
|
|
||||||
std::string fetch_name() override {
|
std::string fetch_name() override {
|
||||||
return "Rename " + old_name + " to " + new_name;
|
return "Rename " + old_name + " to " + new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo() override {
|
void undo() override {
|
||||||
engine->get_scene()->get(object).name = old_name;
|
engine->get_scene()->get(object).name = old_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute() override {
|
void execute() override {
|
||||||
engine->get_scene()->get(object).name = new_name;
|
engine->get_scene()->get(object).name = new_name;
|
||||||
}
|
}
|
||||||
|
@ -64,18 +64,19 @@ public:
|
||||||
class ChangeParentCommand : public Command {
|
class ChangeParentCommand : public Command {
|
||||||
public:
|
public:
|
||||||
prism::Object object;
|
prism::Object object;
|
||||||
|
|
||||||
prism::Object old_parent;
|
prism::Object old_parent;
|
||||||
prism::Object new_parent;
|
prism::Object new_parent;
|
||||||
|
|
||||||
std::string fetch_name() override {
|
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 {
|
void undo() override {
|
||||||
engine->get_scene()->get(object).parent = old_parent;
|
engine->get_scene()->get(object).parent = old_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute() override {
|
void execute() override {
|
||||||
engine->get_scene()->get(object).parent = new_parent;
|
engine->get_scene()->get(object).parent = new_parent;
|
||||||
}
|
}
|
||||||
|
@ -89,18 +90,17 @@ enum class AssetType {
|
||||||
Scene
|
Scene
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> AssetType get_asset_type() {
|
||||||
AssetType get_asset_type() {
|
if constexpr (std::is_same<T, Mesh>::value) {
|
||||||
if constexpr(std::is_same<T, Mesh>::value) {
|
|
||||||
return AssetType::Mesh;
|
return AssetType::Mesh;
|
||||||
} else if constexpr(std::is_same<T, Material>::value) {
|
} else if constexpr (std::is_same<T, Material>::value) {
|
||||||
return AssetType::Material;
|
return AssetType::Material;
|
||||||
} else if constexpr(std::is_same<T, Texture>::value) {
|
} else if constexpr (std::is_same<T, Texture>::value) {
|
||||||
return AssetType::Texture;
|
return AssetType::Texture;
|
||||||
} else if constexpr(std::is_same<T, Scene>::value) {
|
} else if constexpr (std::is_same<T, Scene>::value) {
|
||||||
return AssetType::Scene;
|
return AssetType::Scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AssetType::Unknown;
|
return AssetType::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,19 +108,19 @@ constexpr int thumbnail_resolution = 256;
|
||||||
|
|
||||||
class CommonEditor : public prism::app {
|
class CommonEditor : public prism::app {
|
||||||
public:
|
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;
|
bool should_quit() override;
|
||||||
|
|
||||||
virtual void drawUI() {}
|
virtual void drawUI() {}
|
||||||
|
|
||||||
void begin_frame() override;
|
void begin_frame() override;
|
||||||
|
|
||||||
void update(float deltaTime) override;
|
void update(float deltaTime) override;
|
||||||
|
|
||||||
virtual void renderEditor([[maybe_unused]] GFXCommandBuffer* command_buffer) {}
|
virtual void renderEditor([[maybe_unused]] GFXCommandBuffer* command_buffer) {}
|
||||||
|
|
||||||
void render(GFXCommandBuffer* command_buffer) override {
|
void render(GFXCommandBuffer* command_buffer) override {
|
||||||
|
@ -130,150 +130,170 @@ public:
|
||||||
virtual void updateEditor([[maybe_unused]] float deltaTime) {}
|
virtual void updateEditor([[maybe_unused]] float deltaTime) {}
|
||||||
|
|
||||||
virtual void object_selected([[maybe_unused]] prism::Object object) {}
|
virtual void object_selected([[maybe_unused]] prism::Object object) {}
|
||||||
|
|
||||||
virtual void asset_selected([[maybe_unused]] const std::filesystem::path& path, [[maybe_unused]] AssetType type) {}
|
virtual void asset_selected([[maybe_unused]] const std::filesystem::path& path, [[maybe_unused]] AssetType type) {}
|
||||||
|
|
||||||
bool wants_no_scene_rendering() override { return true; }
|
bool wants_no_scene_rendering() override {
|
||||||
bool is_multimodal() override { return true; }
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_multimodal() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void createDockArea();
|
void createDockArea();
|
||||||
void drawViewport(Scene* scene);
|
void drawViewport(Scene* scene);
|
||||||
void drawAssets();
|
void drawAssets();
|
||||||
|
|
||||||
// options
|
// options
|
||||||
int getDefaultX() const;
|
int getDefaultX() const;
|
||||||
int getDefaultY() const;
|
int getDefaultY() const;
|
||||||
int getDefaultWidth() const;
|
int getDefaultWidth() const;
|
||||||
int getDefaultHeight() const;
|
int getDefaultHeight() const;
|
||||||
|
|
||||||
void addOpenedFile(std::string_view path);
|
void addOpenedFile(std::string_view path);
|
||||||
void clearOpenedFiles();
|
void clearOpenedFiles();
|
||||||
std::vector<std::string> getOpenedFiles() const;
|
std::vector<std::string> getOpenedFiles() const;
|
||||||
|
|
||||||
void drawOutline();
|
void drawOutline();
|
||||||
void drawPropertyEditor();
|
void drawPropertyEditor();
|
||||||
void drawConsole();
|
void drawConsole();
|
||||||
|
|
||||||
void set_undo_stack(UndoStack* stack);
|
void set_undo_stack(UndoStack* stack);
|
||||||
|
|
||||||
prism::Object selected_object = prism::NullObject;
|
prism::Object selected_object = prism::NullObject;
|
||||||
|
|
||||||
GFXTexture* get_material_preview(Material& material);
|
GFXTexture* get_material_preview(Material& material);
|
||||||
GFXTexture* get_mesh_preview(Mesh& mesh);
|
GFXTexture* get_mesh_preview(Mesh& mesh);
|
||||||
GFXTexture* get_texture_preview(Texture& texture);
|
GFXTexture* get_texture_preview(Texture& texture);
|
||||||
GFXTexture* generate_common_preview(Scene& scene, prism::float3 camera_position);
|
GFXTexture* generate_common_preview(Scene& scene, prism::float3 camera_position);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> GFXTexture* get_asset_thumbnail(AssetPtr<T>& asset) {
|
||||||
GFXTexture* get_asset_thumbnail(AssetPtr<T>& asset) {
|
|
||||||
Expects(asset.handle != nullptr);
|
Expects(asset.handle != nullptr);
|
||||||
|
|
||||||
if(asset_thumbnails.count(asset->path)) {
|
if (asset_thumbnails.count(asset->path)) {
|
||||||
return asset_thumbnails[asset->path];
|
return asset_thumbnails[asset->path];
|
||||||
} else {
|
} else {
|
||||||
if constexpr(std::is_same_v<T, Material>) {
|
if constexpr (std::is_same_v<T, Material>) {
|
||||||
auto texture = get_material_preview(*asset.handle);
|
auto texture = get_material_preview(*asset.handle);
|
||||||
|
|
||||||
asset_thumbnails[asset->path] = texture;
|
asset_thumbnails[asset->path] = texture;
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
} else if constexpr(std::is_same_v<T, Mesh>) {
|
} else if constexpr (std::is_same_v<T, Mesh>) {
|
||||||
auto texture = get_mesh_preview(*asset.handle);
|
auto texture = get_mesh_preview(*asset.handle);
|
||||||
|
|
||||||
asset_thumbnails[asset->path] = texture;
|
asset_thumbnails[asset->path] = texture;
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
} else if constexpr(std::is_same_v<T, Texture>) {
|
} else if constexpr (std::is_same_v<T, Texture>) {
|
||||||
auto texture = get_texture_preview(*asset.handle);
|
auto texture = get_texture_preview(*asset.handle);
|
||||||
|
|
||||||
asset_thumbnails[asset->path] = texture;
|
asset_thumbnails[asset->path] = texture;
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
} else {
|
} else {
|
||||||
return engine->get_renderer()->dummy_texture;
|
return engine->get_renderer()->dummy_texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXTexture* get_asset_thumbnail(const prism::path& path) {
|
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()];
|
return asset_thumbnails[path.string()];
|
||||||
} else {
|
} else {
|
||||||
auto [asset, block] = assetm->load_asset_generic(path);
|
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)
|
// 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;
|
asset_thumbnails[path.string()] = engine->get_renderer()->dummy_texture;
|
||||||
|
|
||||||
return engine->get_renderer()->dummy_texture;
|
return engine->get_renderer()->dummy_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(can_load_asset<Material>(path)) {
|
if (can_load_asset<Material>(path)) {
|
||||||
auto ptr = AssetPtr<Material>(static_cast<Material*>(asset), block);
|
auto ptr = AssetPtr<Material>(static_cast<Material*>(asset), block);
|
||||||
|
|
||||||
return get_asset_thumbnail(ptr);
|
return get_asset_thumbnail(ptr);
|
||||||
} else if(can_load_asset<Mesh>(path)) {
|
} else if (can_load_asset<Mesh>(path)) {
|
||||||
auto ptr = AssetPtr<Mesh>(static_cast<Mesh*>(asset), block);
|
auto ptr = AssetPtr<Mesh>(static_cast<Mesh*>(asset), block);
|
||||||
|
|
||||||
return get_asset_thumbnail(ptr);
|
return get_asset_thumbnail(ptr);
|
||||||
} else if(can_load_asset<Texture>(path)) {
|
} else if (can_load_asset<Texture>(path)) {
|
||||||
auto ptr = AssetPtr<Texture>(static_cast<Texture*>(asset), block);
|
auto ptr = AssetPtr<Texture>(static_cast<Texture*>(asset), block);
|
||||||
|
|
||||||
return get_asset_thumbnail(ptr);
|
return get_asset_thumbnail(ptr);
|
||||||
} else {
|
} else {
|
||||||
return engine->get_renderer()->dummy_texture;
|
return engine->get_renderer()->dummy_texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_asset_edit_changed = false;
|
bool has_asset_edit_changed = false;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> bool edit_asset(const char* name, AssetPtr<T>& asset) {
|
||||||
bool edit_asset(const char* name, AssetPtr<T>& asset) {
|
|
||||||
ImGui::PushID(&asset);
|
ImGui::PushID(&asset);
|
||||||
|
|
||||||
auto draw_list = ImGui::GetWindowDrawList();
|
auto draw_list = ImGui::GetWindowDrawList();
|
||||||
const auto window_pos = ImGui::GetCursorScreenPos();
|
const auto window_pos = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
const float thumbnail_size = 35.0f;
|
const float thumbnail_size = 35.0f;
|
||||||
const auto line_height = ImGui::GetTextLineHeight();
|
const auto line_height = ImGui::GetTextLineHeight();
|
||||||
|
|
||||||
const float item_width = ImGui::CalcItemWidth();
|
const float item_width = ImGui::CalcItemWidth();
|
||||||
const float inner_spacing = ImGui::GetStyle().ItemInnerSpacing.x;
|
const float inner_spacing = ImGui::GetStyle().ItemInnerSpacing.x;
|
||||||
|
|
||||||
const auto frame_color = ImGui::GetStyle().Colors[ImGuiCol_FrameBg];
|
const auto frame_color = ImGui::GetStyle().Colors[ImGuiCol_FrameBg];
|
||||||
const auto text_color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
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));
|
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);
|
if (asset)
|
||||||
|
draw_list->AddImageRounded(
|
||||||
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));
|
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);
|
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);
|
draw_list->AddRectFilled(clear_rect.Min, clear_rect.Max, ImColor(255, 0, 0, 255), 3.0f);
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
if(asset)
|
if (asset)
|
||||||
path = asset->path;
|
path = asset->path;
|
||||||
else
|
else
|
||||||
path = "None";
|
path = "None";
|
||||||
|
|
||||||
ImGui::PushClipRect(path_rect.Min, path_rect.Max, false);
|
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::Dummy(ImVec2(thumbnail_size, thumbnail_size + 10.0f));
|
||||||
|
|
||||||
ImGui::ItemAdd(path_rect, ImGui::GetID("path"));
|
ImGui::ItemAdd(path_rect, ImGui::GetID("path"));
|
||||||
|
|
||||||
ImGui::PopClipRect();
|
ImGui::PopClipRect();
|
||||||
|
|
||||||
if(ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
current_asset_type = get_asset_type<T>();
|
current_asset_type = get_asset_type<T>();
|
||||||
open_asset_popup = true;
|
open_asset_popup = true;
|
||||||
on_asset_select = [&asset, this](auto p) {
|
on_asset_select = [&asset, this](auto p) {
|
||||||
|
@ -281,20 +301,20 @@ public:
|
||||||
has_asset_edit_changed = true;
|
has_asset_edit_changed = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::ItemAdd(edit_rect, ImGui::GetID("edit"));
|
ImGui::ItemAdd(edit_rect, ImGui::GetID("edit"));
|
||||||
|
|
||||||
if(ImGui::IsItemClicked())
|
if (ImGui::IsItemClicked())
|
||||||
asset_selected(asset->path, get_asset_type<T>());
|
asset_selected(asset->path, get_asset_type<T>());
|
||||||
|
|
||||||
ImGui::ItemAdd(clear_rect, ImGui::GetID("clear"));
|
ImGui::ItemAdd(clear_rect, ImGui::GetID("clear"));
|
||||||
|
|
||||||
if(ImGui::IsItemClicked())
|
if (ImGui::IsItemClicked())
|
||||||
asset.clear();
|
asset.clear();
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
|
||||||
if(has_asset_edit_changed) {
|
if (has_asset_edit_changed) {
|
||||||
has_asset_edit_changed = false;
|
has_asset_edit_changed = false;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -302,63 +322,66 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T> void open_asset(const AssetType type, const std::function<void(prism::path)>& func_ptr) {
|
||||||
void open_asset(const AssetType type, const std::function<void(prism::path)>& func_ptr) {
|
|
||||||
current_asset_type = type;
|
current_asset_type = type;
|
||||||
open_asset_popup = true;
|
open_asset_popup = true;
|
||||||
on_asset_select = func_ptr;
|
on_asset_select = func_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugPass* debugPass = nullptr;
|
DebugPass* debugPass = nullptr;
|
||||||
|
|
||||||
int viewport_width = 1, viewport_height = 1;
|
int viewport_width = 1, viewport_height = 1;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct ViewportRenderTarget {
|
struct ViewportRenderTarget {
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
RenderTarget* target = nullptr;
|
RenderTarget* target = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<ImGuiID, ViewportRenderTarget> viewport_render_targets;
|
std::unordered_map<ImGuiID, ViewportRenderTarget> viewport_render_targets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load_options();
|
void load_options();
|
||||||
void save_options();
|
void save_options();
|
||||||
|
|
||||||
void load_thumbnail_cache();
|
void load_thumbnail_cache();
|
||||||
void save_thumbnail_cache();
|
void save_thumbnail_cache();
|
||||||
|
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string iniFileName;
|
std::string iniFileName;
|
||||||
|
|
||||||
std::unordered_map<std::string, GFXTexture*> asset_thumbnails;
|
std::unordered_map<std::string, GFXTexture*> asset_thumbnails;
|
||||||
|
|
||||||
bool accepting_viewport_input = false, doing_viewport_input = false;
|
bool accepting_viewport_input = false, doing_viewport_input = false;
|
||||||
int viewport_x = 1, viewport_y = 1;
|
int viewport_x = 1, viewport_y = 1;
|
||||||
|
|
||||||
bool transforming_axis = false;
|
bool transforming_axis = false;
|
||||||
SelectableObject::Axis axis;
|
SelectableObject::Axis axis;
|
||||||
prism::float3 last_object_position;
|
prism::float3 last_object_position;
|
||||||
|
|
||||||
bool open_asset_popup = false;
|
bool open_asset_popup = false;
|
||||||
AssetType current_asset_type;
|
AssetType current_asset_type;
|
||||||
std::function<void(std::filesystem::path)> on_asset_select;
|
std::function<void(std::filesystem::path)> on_asset_select;
|
||||||
|
|
||||||
UndoStack* current_stack = nullptr;
|
UndoStack* current_stack = nullptr;
|
||||||
|
|
||||||
int defaultX, defaultY, defaultWidth, defaultHeight;
|
int defaultX, defaultY, defaultWidth, defaultHeight;
|
||||||
std::vector<std::string> lastOpenedFiles;
|
std::vector<std::string> lastOpenedFiles;
|
||||||
|
|
||||||
void walkObject(prism::Object object, prism::Object parentObject = prism::NullObject);
|
void walkObject(prism::Object object, prism::Object parentObject = prism::NullObject);
|
||||||
|
|
||||||
void editTransform(prism::Object object, Transform transform);
|
void editTransform(prism::Object object, Transform transform);
|
||||||
void editRenderable(Renderable& mesh);
|
void editRenderable(Renderable& mesh);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void editPath(const char* label, std::string& path, bool editable = true, const std::function<void()> on_selected = nullptr) {
|
inline void editPath(
|
||||||
|
const char* label,
|
||||||
|
std::string& path,
|
||||||
|
bool editable = true,
|
||||||
|
const std::function<void()> on_selected = nullptr) {
|
||||||
ImGui::PushID(label);
|
ImGui::PushID(label);
|
||||||
|
|
||||||
if(!editable) {
|
if (!editable) {
|
||||||
ImGui::Text("%s: %s", label, path.c_str());
|
ImGui::Text("%s: %s", label, path.c_str());
|
||||||
} else {
|
} else {
|
||||||
ImGui::InputText(label, &path);
|
ImGui::InputText(label, &path);
|
||||||
|
@ -366,11 +389,11 @@ inline void editPath(const char* label, std::string& path, bool editable = true,
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::Button("...")) {
|
if (ImGui::Button("...")) {
|
||||||
engine->get_imgui().open_dialog(false, [&path, &on_selected](std::string p) {
|
engine->get_imgui().open_dialog(false, [&path, &on_selected](std::string p) {
|
||||||
path = prism::get_relative_path(prism::domain::game, p).string();
|
path = prism::get_relative_path(prism::domain::game, p).string();
|
||||||
|
|
||||||
if(on_selected != nullptr)
|
if (on_selected != nullptr)
|
||||||
on_selected();
|
on_selected();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -381,18 +404,18 @@ inline void editPath(const char* label, std::string& path, bool editable = true,
|
||||||
class SelectionCommand : public Command {
|
class SelectionCommand : public Command {
|
||||||
public:
|
public:
|
||||||
CommonEditor* editor = nullptr;
|
CommonEditor* editor = nullptr;
|
||||||
|
|
||||||
prism::Object new_selection;
|
prism::Object new_selection;
|
||||||
prism::Object old_selection;
|
prism::Object old_selection;
|
||||||
|
|
||||||
std::string fetch_name() override {
|
std::string fetch_name() override {
|
||||||
return "Change selection to " + engine->get_scene()->get(new_selection).name;
|
return "Change selection to " + engine->get_scene()->get(new_selection).name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo() override {
|
void undo() override {
|
||||||
editor->selected_object = old_selection;
|
editor->selected_object = old_selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute() override {
|
void execute() override {
|
||||||
editor->selected_object = new_selection;
|
editor->selected_object = new_selection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "pass.hpp"
|
#include "assetptr.hpp"
|
||||||
#include "gfx_renderpass.hpp"
|
|
||||||
#include "gfx_pipeline.hpp"
|
|
||||||
#include "gfx_texture.hpp"
|
|
||||||
#include "gfx_buffer.hpp"
|
#include "gfx_buffer.hpp"
|
||||||
#include "gfx_framebuffer.hpp"
|
#include "gfx_framebuffer.hpp"
|
||||||
|
#include "gfx_pipeline.hpp"
|
||||||
|
#include "gfx_renderpass.hpp"
|
||||||
|
#include "gfx_texture.hpp"
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "assetptr.hpp"
|
#include "pass.hpp"
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
|
@ -22,22 +22,22 @@ struct SelectableObject {
|
||||||
Object,
|
Object,
|
||||||
Handle
|
Handle
|
||||||
} type = Type::Object;
|
} type = Type::Object;
|
||||||
|
|
||||||
Matrix4x4 axis_model;
|
Matrix4x4 axis_model;
|
||||||
|
|
||||||
enum class Axis {
|
enum class Axis {
|
||||||
X,
|
X,
|
||||||
Y,
|
Y,
|
||||||
Z
|
Z
|
||||||
} axis = Axis::X;
|
} axis = Axis::X;
|
||||||
|
|
||||||
enum class RenderType {
|
enum class RenderType {
|
||||||
Mesh,
|
Mesh,
|
||||||
Sphere
|
Sphere
|
||||||
} render_type = RenderType::Mesh;
|
} render_type = RenderType::Mesh;
|
||||||
|
|
||||||
float sphere_size = 1.0f;
|
float sphere_size = 1.0f;
|
||||||
|
|
||||||
prism::Object object = prism::NullObject;
|
prism::Object object = prism::NullObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,31 +47,31 @@ public:
|
||||||
|
|
||||||
void create_render_target_resources(RenderTarget& target) override;
|
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<void(SelectableObject)>& callback);
|
void get_selected_object(int x, int y, const std::function<void(SelectableObject)>& callback);
|
||||||
void draw_arrow(GFXCommandBuffer* commandBuffer, prism::float3 color, Matrix4x4 model);
|
void draw_arrow(GFXCommandBuffer* commandBuffer, prism::float3 color, Matrix4x4 model);
|
||||||
|
|
||||||
GFXTexture* get_requested_texture(PassTextureType type) override {
|
GFXTexture* get_requested_texture(PassTextureType type) override {
|
||||||
if(type == PassTextureType::SelectionSobel)
|
if (type == PassTextureType::SelectionSobel)
|
||||||
return sobelTexture;
|
return sobelTexture;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXTexture* selectTexture = nullptr;
|
GFXTexture* selectTexture = nullptr;
|
||||||
GFXTexture* selectDepthTexture = nullptr;
|
GFXTexture* selectDepthTexture = nullptr;
|
||||||
GFXTexture* sobelTexture = nullptr;
|
GFXTexture* sobelTexture = nullptr;
|
||||||
|
|
||||||
prism::Object selected_object = prism::NullObject;
|
prism::Object selected_object = prism::NullObject;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createOffscreenResources();
|
void createOffscreenResources();
|
||||||
|
|
||||||
prism::Extent extent;
|
prism::Extent extent;
|
||||||
|
|
||||||
std::vector<SelectableObject> selectable_objects;
|
std::vector<SelectableObject> selectable_objects;
|
||||||
|
|
||||||
AssetPtr<Texture> pointTexture, spotTexture, sunTexture, probeTexture;
|
AssetPtr<Texture> pointTexture, spotTexture, sunTexture, probeTexture;
|
||||||
AssetPtr<Mesh> cubeMesh, arrowMesh, sphereMesh;
|
AssetPtr<Mesh> cubeMesh, arrowMesh, sphereMesh;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ private:
|
||||||
GFXRenderPass* selectRenderPass = nullptr;
|
GFXRenderPass* selectRenderPass = nullptr;
|
||||||
GFXFramebuffer* selectFramebuffer = nullptr;
|
GFXFramebuffer* selectFramebuffer = nullptr;
|
||||||
GFXBuffer* selectBuffer = nullptr;
|
GFXBuffer* selectBuffer = nullptr;
|
||||||
|
|
||||||
GFXPipeline* sobelPipeline = nullptr;
|
GFXPipeline* sobelPipeline = nullptr;
|
||||||
GFXFramebuffer* sobelFramebuffer = nullptr;
|
GFXFramebuffer* sobelFramebuffer = nullptr;
|
||||||
GFXRenderPass* sobelRenderPass = nullptr;
|
GFXRenderPass* sobelRenderPass = nullptr;
|
||||||
|
|
|
@ -1,53 +1,52 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class Command {
|
class Command {
|
||||||
public:
|
public:
|
||||||
std::string stored_name;
|
std::string stored_name;
|
||||||
|
|
||||||
std::string get_name() {
|
std::string get_name() {
|
||||||
if(stored_name.empty())
|
if (stored_name.empty())
|
||||||
stored_name = fetch_name();
|
stored_name = fetch_name();
|
||||||
|
|
||||||
return stored_name;
|
return stored_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string fetch_name() = 0;
|
virtual std::string fetch_name() = 0;
|
||||||
|
|
||||||
virtual void undo() = 0;
|
virtual void undo() = 0;
|
||||||
virtual void execute() = 0;
|
virtual void execute() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UndoStack {
|
class UndoStack {
|
||||||
public:
|
public:
|
||||||
template<class T>
|
template<class T> T& new_command() {
|
||||||
T& new_command() {
|
|
||||||
// if we are in the middle of the stack currently, wipe out everything and start fresh
|
// 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
|
// 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();
|
command_stack.clear();
|
||||||
stack_position = -1;
|
stack_position = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_position++;
|
stack_position++;
|
||||||
|
|
||||||
return static_cast<T&>(*command_stack.emplace_back(std::make_unique<T>()));
|
return static_cast<T&>(*command_stack.emplace_back(std::make_unique<T>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//void push_command(Command* command);
|
// void push_command(Command* command);
|
||||||
|
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
|
|
||||||
// useful for undo
|
// useful for undo
|
||||||
Command* get_last_command();
|
Command* get_last_command();
|
||||||
|
|
||||||
// useful for redo
|
// useful for redo
|
||||||
Command* get_next_command();
|
Command* get_next_command();
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Command>> command_stack;
|
std::vector<std::unique_ptr<Command>> command_stack;
|
||||||
int stack_position = -1;
|
int stack_position = -1;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,13 @@
|
||||||
#include "debugpass.hpp"
|
#include "debugpass.hpp"
|
||||||
|
|
||||||
#include "gfx_commandbuffer.hpp"
|
#include "asset.hpp"
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "scene.hpp"
|
|
||||||
#include "transform.hpp"
|
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "asset.hpp"
|
#include "gfx_commandbuffer.hpp"
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
|
#include "scene.hpp"
|
||||||
|
#include "transform.hpp"
|
||||||
|
|
||||||
struct BillPushConstant {
|
struct BillPushConstant {
|
||||||
Matrix4x4 mvp;
|
Matrix4x4 mvp;
|
||||||
|
@ -32,13 +32,9 @@ void DebugPass::initialize() {
|
||||||
|
|
||||||
createInfo.vertex_input.attributes.push_back(positionAttribute);
|
createInfo.vertex_input.attributes.push_back(positionAttribute);
|
||||||
|
|
||||||
createInfo.shader_input.push_constants = {
|
createInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}};
|
||||||
{sizeof(Matrix4x4) + sizeof(prism::float4), 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
createInfo.shader_input.bindings = {
|
createInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}};
|
||||||
{1, GFXBindingType::PushConstant}
|
|
||||||
};
|
|
||||||
|
|
||||||
createInfo.render_pass = engine->get_renderer()->offscreen_render_pass;
|
createInfo.render_pass = engine->get_renderer()->offscreen_render_pass;
|
||||||
createInfo.rasterization.polygon_type = GFXPolygonType::Line;
|
createInfo.rasterization.polygon_type = GFXPolygonType::Line;
|
||||||
|
@ -51,7 +47,7 @@ void DebugPass::initialize() {
|
||||||
createInfo.rasterization.polygon_type = GFXPolygonType::Fill;
|
createInfo.rasterization.polygon_type = GFXPolygonType::Fill;
|
||||||
|
|
||||||
arrow_pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
|
arrow_pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
|
||||||
|
|
||||||
arrowMesh = assetm->get<Mesh>(prism::base_domain / "models/arrow.model");
|
arrowMesh = assetm->get<Mesh>(prism::base_domain / "models/arrow.model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,20 +76,16 @@ void DebugPass::initialize() {
|
||||||
|
|
||||||
pipelineInfo.vertex_input.attributes.push_back(attribute);
|
pipelineInfo.vertex_input.attributes.push_back(attribute);
|
||||||
|
|
||||||
pipelineInfo.shader_input.bindings = {
|
pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}};
|
||||||
{1, GFXBindingType::PushConstant}
|
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.shader_input.push_constants = {
|
pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}};
|
||||||
{sizeof(Matrix4x4) + sizeof(prism::float4), 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.render_pass = selectRenderPass;
|
pipelineInfo.render_pass = selectRenderPass;
|
||||||
pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
|
pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
|
||||||
|
|
||||||
selectPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
selectPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sobel
|
// sobel
|
||||||
{
|
{
|
||||||
// render pass
|
// render pass
|
||||||
|
@ -101,7 +93,7 @@ void DebugPass::initialize() {
|
||||||
renderPassInfo.label = "Sobel";
|
renderPassInfo.label = "Sobel";
|
||||||
renderPassInfo.attachments.push_back(GFXPixelFormat::R8_UNORM);
|
renderPassInfo.attachments.push_back(GFXPixelFormat::R8_UNORM);
|
||||||
renderPassInfo.will_use_in_shader = true;
|
renderPassInfo.will_use_in_shader = true;
|
||||||
|
|
||||||
sobelRenderPass = engine->get_gfx()->create_render_pass(renderPassInfo);
|
sobelRenderPass = engine->get_gfx()->create_render_pass(renderPassInfo);
|
||||||
|
|
||||||
// pipeline
|
// pipeline
|
||||||
|
@ -121,46 +113,37 @@ void DebugPass::initialize() {
|
||||||
|
|
||||||
pipelineInfo.vertex_input.attributes.push_back(attribute);
|
pipelineInfo.vertex_input.attributes.push_back(attribute);
|
||||||
|
|
||||||
pipelineInfo.shader_input.bindings = {
|
pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}};
|
||||||
{1, GFXBindingType::PushConstant}
|
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.shader_input.push_constants = {
|
pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4) + sizeof(prism::float4), 0}};
|
||||||
{sizeof(Matrix4x4) + sizeof(prism::float4), 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.render_pass = sobelRenderPass;
|
pipelineInfo.render_pass = sobelRenderPass;
|
||||||
|
|
||||||
sobelPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
sobelPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// billboard
|
// billboard
|
||||||
{
|
{
|
||||||
// pipeline
|
// pipeline
|
||||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||||
pipelineInfo.label = "Billboard";
|
pipelineInfo.label = "Billboard";
|
||||||
|
|
||||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("billboard.vert"));
|
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("billboard.vert"));
|
||||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("billboard.frag"));
|
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("billboard.frag"));
|
||||||
|
|
||||||
pipelineInfo.shader_input.bindings = {
|
pipelineInfo.shader_input.bindings = {
|
||||||
{1, GFXBindingType::PushConstant},
|
{1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}, {3, GFXBindingType::StorageBuffer}};
|
||||||
{2, GFXBindingType::Texture},
|
|
||||||
{3, GFXBindingType::StorageBuffer}
|
pipelineInfo.shader_input.push_constants = {{sizeof(BillPushConstant), 0}};
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.shader_input.push_constants = {
|
|
||||||
{sizeof(BillPushConstant), 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
|
pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
|
||||||
|
|
||||||
pipelineInfo.blending.enable_blending = true;
|
pipelineInfo.blending.enable_blending = true;
|
||||||
|
|
||||||
pipelineInfo.render_pass = engine->get_renderer()->offscreen_render_pass;
|
pipelineInfo.render_pass = engine->get_renderer()->offscreen_render_pass;
|
||||||
|
|
||||||
billboard_pipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
billboard_pipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
||||||
|
|
||||||
pointTexture = assetm->get<Texture>(prism::base_domain / "textures/point.png");
|
pointTexture = assetm->get<Texture>(prism::base_domain / "textures/point.png");
|
||||||
spotTexture = assetm->get<Texture>(prism::base_domain / "textures/spot.png");
|
spotTexture = assetm->get<Texture>(prism::base_domain / "textures/spot.png");
|
||||||
sunTexture = assetm->get<Texture>(prism::base_domain / "textures/sun.png");
|
sunTexture = assetm->get<Texture>(prism::base_domain / "textures/sun.png");
|
||||||
|
@ -170,7 +153,7 @@ void DebugPass::initialize() {
|
||||||
|
|
||||||
void DebugPass::create_render_target_resources(RenderTarget& target) {
|
void DebugPass::create_render_target_resources(RenderTarget& target) {
|
||||||
this->extent = target.extent;
|
this->extent = target.extent;
|
||||||
|
|
||||||
createOffscreenResources();
|
createOffscreenResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,23 +167,24 @@ void DebugPass::createOffscreenResources() {
|
||||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment;
|
textureInfo.usage = GFXTextureUsage::Attachment;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
selectTexture = engine->get_gfx()->create_texture(textureInfo);
|
selectTexture = engine->get_gfx()->create_texture(textureInfo);
|
||||||
|
|
||||||
textureInfo.label = "Select Depth";
|
textureInfo.label = "Select Depth";
|
||||||
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||||
|
|
||||||
selectDepthTexture = engine->get_gfx()->create_texture(textureInfo);
|
selectDepthTexture = engine->get_gfx()->create_texture(textureInfo);
|
||||||
|
|
||||||
GFXFramebufferCreateInfo info;
|
GFXFramebufferCreateInfo info;
|
||||||
info.attachments = {selectTexture, selectDepthTexture};
|
info.attachments = {selectTexture, selectDepthTexture};
|
||||||
info.render_pass = selectRenderPass;
|
info.render_pass = selectRenderPass;
|
||||||
|
|
||||||
selectFramebuffer = engine->get_gfx()->create_framebuffer(info);
|
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
|
// sobel
|
||||||
{
|
{
|
||||||
GFXTextureCreateInfo textureInfo = {};
|
GFXTextureCreateInfo textureInfo = {};
|
||||||
|
@ -210,7 +194,7 @@ void DebugPass::createOffscreenResources() {
|
||||||
textureInfo.format = GFXPixelFormat::R8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment;
|
textureInfo.usage = GFXTextureUsage::Attachment;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
sobelTexture = engine->get_gfx()->create_texture(textureInfo);
|
sobelTexture = engine->get_gfx()->create_texture(textureInfo);
|
||||||
|
|
||||||
GFXFramebufferCreateInfo info;
|
GFXFramebufferCreateInfo info;
|
||||||
|
@ -226,28 +210,29 @@ void DebugPass::draw_arrow(GFXCommandBuffer* commandBuffer, prism::float3 color,
|
||||||
Matrix4x4 mvp;
|
Matrix4x4 mvp;
|
||||||
prism::float4 color;
|
prism::float4 color;
|
||||||
} pc;
|
} pc;
|
||||||
|
|
||||||
pc.mvp = model;
|
pc.mvp = model;
|
||||||
pc.color = color;
|
pc.color = color;
|
||||||
|
|
||||||
commandBuffer->set_push_constant(&pc, sizeof(PushConstant));
|
commandBuffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||||
|
|
||||||
commandBuffer->set_vertex_buffer(arrowMesh->position_buffer, 0, 0);
|
commandBuffer->set_vertex_buffer(arrowMesh->position_buffer, 0, 0);
|
||||||
commandBuffer->set_index_buffer(arrowMesh->index_buffer, IndexType::UINT32);
|
commandBuffer->set_index_buffer(arrowMesh->index_buffer, IndexType::UINT32);
|
||||||
|
|
||||||
commandBuffer->draw_indexed(arrowMesh->num_indices, 0, 0, 0);
|
commandBuffer->draw_indexed(arrowMesh->num_indices, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
||||||
auto [camObj, camera] = scene.get_all<Camera>()[0];
|
auto [camObj, camera] = scene.get_all<Camera>()[0];
|
||||||
|
|
||||||
struct PushConstant {
|
struct PushConstant {
|
||||||
Matrix4x4 mvp;
|
Matrix4x4 mvp;
|
||||||
prism::float4 color;
|
prism::float4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
Matrix4x4 vp = camera.perspective * camera.view;
|
Matrix4x4 vp = camera.perspective * camera.view;
|
||||||
|
|
||||||
commandBuffer->set_graphics_pipeline(primitive_pipeline);
|
commandBuffer->set_graphics_pipeline(primitive_pipeline);
|
||||||
|
|
||||||
struct DebugPrimitive {
|
struct DebugPrimitive {
|
||||||
prism::float3 position, size;
|
prism::float3 position, size;
|
||||||
|
@ -256,22 +241,22 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<DebugPrimitive> primitives;
|
std::vector<DebugPrimitive> primitives;
|
||||||
|
|
||||||
struct DebugBillboard {
|
struct DebugBillboard {
|
||||||
prism::float3 position;
|
prism::float3 position;
|
||||||
GFXTexture* texture = nullptr;
|
GFXTexture* texture = nullptr;
|
||||||
prism::float4 color;
|
prism::float4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<DebugBillboard> billboards;
|
std::vector<DebugBillboard> billboards;
|
||||||
|
|
||||||
for(auto& obj : scene.get_objects()) {
|
for (auto& obj : scene.get_objects()) {
|
||||||
if(scene.get(obj).editor_object)
|
if (scene.get(obj).editor_object)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto& transform = scene.get<Transform>(obj);
|
auto& transform = scene.get<Transform>(obj);
|
||||||
|
|
||||||
if(scene.has<Collision>(obj)) {
|
if (scene.has<Collision>(obj)) {
|
||||||
auto& collision = scene.get<Collision>(obj);
|
auto& collision = scene.get<Collision>(obj);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -284,13 +269,13 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
||||||
primitives.push_back(prim);
|
primitives.push_back(prim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scene.has<Light>(obj)) {
|
if (scene.has<Light>(obj)) {
|
||||||
DebugBillboard bill;
|
DebugBillboard bill;
|
||||||
bill.position = transform.get_world_position();
|
bill.position = transform.get_world_position();
|
||||||
bill.color = prism::float4(scene.get<Light>(obj).color, 1.0f);
|
bill.color = prism::float4(scene.get<Light>(obj).color, 1.0f);
|
||||||
|
|
||||||
switch(scene.get<Light>(obj).type) {
|
switch (scene.get<Light>(obj).type) {
|
||||||
case Light::Type::Point:
|
case Light::Type::Point:
|
||||||
bill.texture = pointTexture->handle;
|
bill.texture = pointTexture->handle;
|
||||||
break;
|
break;
|
||||||
|
@ -301,34 +286,34 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
||||||
bill.texture = sunTexture->handle;
|
bill.texture = sunTexture->handle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
billboards.push_back(bill);
|
billboards.push_back(bill);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scene.has<EnvironmentProbe>(obj)) {
|
if (scene.has<EnvironmentProbe>(obj)) {
|
||||||
if(selected_object == obj) {
|
if (selected_object == obj) {
|
||||||
auto& probe = scene.get<EnvironmentProbe>(obj);
|
auto& probe = scene.get<EnvironmentProbe>(obj);
|
||||||
|
|
||||||
DebugPrimitive prim;
|
DebugPrimitive prim;
|
||||||
prim.position = transform.get_world_position();
|
prim.position = transform.get_world_position();
|
||||||
prim.rotation = transform.rotation;
|
prim.rotation = transform.rotation;
|
||||||
prim.size = probe.size / 2.0f;
|
prim.size = probe.size / 2.0f;
|
||||||
prim.color = prism::float4(0, 1, 1, 1);
|
prim.color = prism::float4(0, 1, 1, 1);
|
||||||
|
|
||||||
primitives.push_back(prim);
|
primitives.push_back(prim);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugBillboard bill;
|
DebugBillboard bill;
|
||||||
bill.position = transform.get_world_position();
|
bill.position = transform.get_world_position();
|
||||||
bill.color = prism::float4(1.0f);
|
bill.color = prism::float4(1.0f);
|
||||||
bill.texture = probeTexture->handle;
|
bill.texture = probeTexture->handle;
|
||||||
|
|
||||||
billboards.push_back(bill);
|
billboards.push_back(bill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw primitives
|
// draw primitives
|
||||||
for(auto& prim : primitives) {
|
for (auto& prim : primitives) {
|
||||||
PushConstant pc;
|
PushConstant pc;
|
||||||
|
|
||||||
Matrix4x4 m = prism::translate(Matrix4x4(), prim.position);
|
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->draw_indexed(cubeMesh->num_indices, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
commandBuffer->set_graphics_pipeline(billboard_pipeline);
|
commandBuffer->set_graphics_pipeline(billboard_pipeline);
|
||||||
|
|
||||||
engine->get_gfx()->copy_buffer(scene_info_buffer, &camera.view, 0, sizeof(Matrix4x4));
|
engine->get_gfx()->copy_buffer(scene_info_buffer, &camera.view, 0, sizeof(Matrix4x4));
|
||||||
|
|
||||||
// draw primitives
|
// draw primitives
|
||||||
for(auto& bill : billboards) {
|
for (auto& bill : billboards) {
|
||||||
Matrix4x4 m = prism::translate(Matrix4x4(), bill.position);
|
Matrix4x4 m = prism::translate(Matrix4x4(), bill.position);
|
||||||
|
|
||||||
BillPushConstant pc;
|
BillPushConstant pc;
|
||||||
pc.mvp = vp * m;
|
pc.mvp = vp * m;
|
||||||
pc.color = bill.color;
|
pc.color = bill.color;
|
||||||
|
|
||||||
commandBuffer->bind_texture(bill.texture, 2);
|
commandBuffer->bind_texture(bill.texture, 2);
|
||||||
commandBuffer->bind_shader_buffer(scene_info_buffer, 0, 3, sizeof(Matrix4x4));
|
commandBuffer->bind_shader_buffer(scene_info_buffer, 0, 3, sizeof(Matrix4x4));
|
||||||
|
|
||||||
commandBuffer->set_push_constant(&pc, sizeof(BillPushConstant));
|
commandBuffer->set_push_constant(&pc, sizeof(BillPushConstant));
|
||||||
commandBuffer->draw_indexed(4, 0, 0, 0);
|
commandBuffer->draw_indexed(4, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
commandBuffer->set_graphics_pipeline(arrow_pipeline);
|
commandBuffer->set_graphics_pipeline(arrow_pipeline);
|
||||||
|
|
||||||
// draw handles for selected object;
|
// draw handles for selected object;
|
||||||
if(selected_object != prism::NullObject && engine->get_scene()->has<Transform>(selected_object)) {
|
if (selected_object != prism::NullObject && engine->get_scene()->has<Transform>(selected_object)) {
|
||||||
const auto position = engine->get_scene()->get<Transform>(selected_object).get_world_position();
|
const auto position = engine->get_scene()->get<Transform>(selected_object).get_world_position();
|
||||||
|
|
||||||
const float base_scale = 0.05f;
|
const float base_scale = 0.05f;
|
||||||
const float scale_factor = length(position - scene.get<Transform>(camObj).get_world_position());
|
const float scale_factor = length(position - scene.get<Transform>(camObj).get_world_position());
|
||||||
|
|
||||||
Matrix4x4 base_model = prism::translate(Matrix4x4(), position);
|
Matrix4x4 base_model = prism::translate(Matrix4x4(), position);
|
||||||
base_model = prism::scale(base_model, base_scale * scale_factor);
|
base_model = prism::scale(base_model, base_scale * scale_factor);
|
||||||
|
|
||||||
// draw y axis
|
// draw y axis
|
||||||
draw_arrow(commandBuffer, prism::float3(0, 1, 0), vp * base_model);
|
draw_arrow(commandBuffer, prism::float3(0, 1, 0), vp * base_model);
|
||||||
|
|
||||||
// draw x axis
|
// 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 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
|
// draw sobel
|
||||||
GFXRenderPassBeginInfo info = {};
|
GFXRenderPassBeginInfo info = {};
|
||||||
info.framebuffer = sobelFramebuffer;
|
info.framebuffer = sobelFramebuffer;
|
||||||
|
@ -394,29 +385,29 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) {
|
||||||
info.render_area.extent = extent;
|
info.render_area.extent = extent;
|
||||||
|
|
||||||
commandBuffer->set_render_pass(info);
|
commandBuffer->set_render_pass(info);
|
||||||
|
|
||||||
if(selected_object != prism::NullObject && engine->get_scene()->has<Renderable>(selected_object)) {
|
if (selected_object != prism::NullObject && engine->get_scene()->has<Renderable>(selected_object)) {
|
||||||
commandBuffer->set_graphics_pipeline(sobelPipeline);
|
commandBuffer->set_graphics_pipeline(sobelPipeline);
|
||||||
|
|
||||||
auto renderable = engine->get_scene()->get<Renderable>(selected_object);
|
auto renderable = engine->get_scene()->get<Renderable>(selected_object);
|
||||||
|
|
||||||
if(!renderable.mesh)
|
if (!renderable.mesh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct PC {
|
struct PC {
|
||||||
Matrix4x4 mvp;
|
Matrix4x4 mvp;
|
||||||
prism::float4 color;
|
prism::float4 color;
|
||||||
} pc;
|
} pc;
|
||||||
|
|
||||||
pc.mvp = vp * engine->get_scene()->get<Transform>(selected_object).model;
|
pc.mvp = vp * engine->get_scene()->get<Transform>(selected_object).model;
|
||||||
pc.color = prism::float4(1);
|
pc.color = prism::float4(1);
|
||||||
|
|
||||||
commandBuffer->set_push_constant(&pc, sizeof(PC));
|
commandBuffer->set_push_constant(&pc, sizeof(PC));
|
||||||
|
|
||||||
commandBuffer->set_vertex_buffer(renderable.mesh->position_buffer, 0, 0);
|
commandBuffer->set_vertex_buffer(renderable.mesh->position_buffer, 0, 0);
|
||||||
commandBuffer->set_index_buffer(renderable.mesh->index_buffer, IndexType::UINT32);
|
commandBuffer->set_index_buffer(renderable.mesh->index_buffer, IndexType::UINT32);
|
||||||
|
|
||||||
if(renderable.mesh) {
|
if (renderable.mesh) {
|
||||||
for (auto& part : renderable.mesh->parts)
|
for (auto& part : renderable.mesh->parts)
|
||||||
commandBuffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, 0);
|
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<void(SelectableObject)>& callback) {
|
void DebugPass::get_selected_object(int x, int y, const std::function<void(SelectableObject)>& callback) {
|
||||||
if(engine->get_scene() == nullptr)
|
if (engine->get_scene() == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto cameras = engine->get_scene()->get_all<Camera>();
|
auto cameras = engine->get_scene()->get_all<Camera>();
|
||||||
|
|
||||||
auto& [camObj, camera] = cameras[0];
|
auto& [camObj, camera] = cameras[0];
|
||||||
|
|
||||||
// calculate selectable objects
|
// calculate selectable objects
|
||||||
selectable_objects.clear();
|
selectable_objects.clear();
|
||||||
|
|
||||||
for(auto& [obj, mesh] : engine->get_scene()->get_all<Renderable>()) {
|
for (auto& [obj, mesh] : engine->get_scene()->get_all<Renderable>()) {
|
||||||
SelectableObject so;
|
SelectableObject so;
|
||||||
so.type = SelectableObject::Type::Object;
|
so.type = SelectableObject::Type::Object;
|
||||||
so.object = obj;
|
so.object = obj;
|
||||||
so.render_type = SelectableObject::RenderType::Mesh;
|
so.render_type = SelectableObject::RenderType::Mesh;
|
||||||
|
|
||||||
selectable_objects.push_back(so);
|
selectable_objects.push_back(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [obj, mesh] : engine->get_scene()->get_all<Light>()) {
|
for (auto& [obj, mesh] : engine->get_scene()->get_all<Light>()) {
|
||||||
SelectableObject so;
|
SelectableObject so;
|
||||||
so.type = SelectableObject::Type::Object;
|
so.type = SelectableObject::Type::Object;
|
||||||
so.object = obj;
|
so.object = obj;
|
||||||
so.render_type = SelectableObject::RenderType::Sphere;
|
so.render_type = SelectableObject::RenderType::Sphere;
|
||||||
so.sphere_size = 0.5f;
|
so.sphere_size = 0.5f;
|
||||||
|
|
||||||
selectable_objects.push_back(so);
|
selectable_objects.push_back(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [obj, mesh] : engine->get_scene()->get_all<EnvironmentProbe>()) {
|
for (auto& [obj, mesh] : engine->get_scene()->get_all<EnvironmentProbe>()) {
|
||||||
SelectableObject so;
|
SelectableObject so;
|
||||||
so.type = SelectableObject::Type::Object;
|
so.type = SelectableObject::Type::Object;
|
||||||
so.object = obj;
|
so.object = obj;
|
||||||
so.render_type = SelectableObject::RenderType::Sphere;
|
so.render_type = SelectableObject::RenderType::Sphere;
|
||||||
so.sphere_size = 0.5f;
|
so.sphere_size = 0.5f;
|
||||||
|
|
||||||
selectable_objects.push_back(so);
|
selectable_objects.push_back(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add selections for currently selected object handles
|
// add selections for currently selected object handles
|
||||||
const auto add_arrow = [this](SelectableObject::Axis axis, Matrix4x4 model) {
|
const auto add_arrow = [this](SelectableObject::Axis axis, Matrix4x4 model) {
|
||||||
SelectableObject so;
|
SelectableObject so;
|
||||||
|
@ -470,26 +461,30 @@ void DebugPass::get_selected_object(int x, int y, const std::function<void(Selec
|
||||||
so.axis = axis;
|
so.axis = axis;
|
||||||
so.axis_model = model;
|
so.axis_model = model;
|
||||||
so.object = selected_object;
|
so.object = selected_object;
|
||||||
|
|
||||||
selectable_objects.push_back(so);
|
selectable_objects.push_back(so);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(selected_object != prism::NullObject) {
|
if (selected_object != prism::NullObject) {
|
||||||
const auto position = engine->get_scene()->get<Transform>(selected_object).get_world_position();
|
const auto position = engine->get_scene()->get<Transform>(selected_object).get_world_position();
|
||||||
|
|
||||||
const float base_scale = 0.05f;
|
const float base_scale = 0.05f;
|
||||||
const float scale_factor = length(position - engine->get_scene()->get<Transform>(camObj).position);
|
const float scale_factor = length(position - engine->get_scene()->get<Transform>(camObj).position);
|
||||||
|
|
||||||
const Matrix4x4 translate_model = prism::translate(Matrix4x4(), position);
|
const Matrix4x4 translate_model = prism::translate(Matrix4x4(), position);
|
||||||
const Matrix4x4 scale_model = prism::scale(Matrix4x4(), base_scale * scale_factor);
|
const Matrix4x4 scale_model = prism::scale(Matrix4x4(), base_scale * scale_factor);
|
||||||
|
|
||||||
add_arrow(SelectableObject::Axis::Y, translate_model * scale_model);
|
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::X,
|
||||||
add_arrow(SelectableObject::Axis::Z, translate_model * matrix_from_quat(angle_axis(radians(90.0f), prism::float3(1, 0, 0))) * scale_model);
|
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);
|
GFXCommandBuffer* commandBuffer = engine->get_gfx()->acquire_command_buffer(false);
|
||||||
|
|
||||||
GFXRenderPassBeginInfo info = {};
|
GFXRenderPassBeginInfo info = {};
|
||||||
|
@ -499,30 +494,30 @@ void DebugPass::get_selected_object(int x, int y, const std::function<void(Selec
|
||||||
info.render_area.extent = extent;
|
info.render_area.extent = extent;
|
||||||
|
|
||||||
commandBuffer->set_render_pass(info);
|
commandBuffer->set_render_pass(info);
|
||||||
|
|
||||||
Viewport viewport = {};
|
Viewport viewport = {};
|
||||||
viewport.width = extent.width;
|
viewport.width = extent.width;
|
||||||
viewport.height = extent.height;
|
viewport.height = extent.height;
|
||||||
|
|
||||||
commandBuffer->set_viewport(viewport);
|
commandBuffer->set_viewport(viewport);
|
||||||
|
|
||||||
commandBuffer->set_graphics_pipeline(selectPipeline);
|
commandBuffer->set_graphics_pipeline(selectPipeline);
|
||||||
|
|
||||||
for(auto [i, object] : utility::enumerate(selectable_objects)) {
|
for (auto [i, object] : utility::enumerate(selectable_objects)) {
|
||||||
AssetPtr<Mesh> mesh;
|
AssetPtr<Mesh> mesh;
|
||||||
Matrix4x4 model;
|
Matrix4x4 model;
|
||||||
if(object.type == SelectableObject::Type::Object) {
|
if (object.type == SelectableObject::Type::Object) {
|
||||||
if(object.render_type == SelectableObject::RenderType::Mesh) {
|
if (object.render_type == SelectableObject::RenderType::Mesh) {
|
||||||
auto& renderable = engine->get_scene()->get<Renderable>(object.object);
|
auto& renderable = engine->get_scene()->get<Renderable>(object.object);
|
||||||
|
|
||||||
if(!renderable.mesh)
|
if (!renderable.mesh)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mesh = renderable.mesh;
|
mesh = renderable.mesh;
|
||||||
} else {
|
} else {
|
||||||
mesh = sphereMesh;
|
mesh = sphereMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
model = engine->get_scene()->get<Transform>(object.object).model;
|
model = engine->get_scene()->get<Transform>(object.object).model;
|
||||||
} else {
|
} else {
|
||||||
mesh = arrowMesh;
|
mesh = arrowMesh;
|
||||||
|
@ -538,8 +533,8 @@ void DebugPass::get_selected_object(int x, int y, const std::function<void(Selec
|
||||||
} pc;
|
} pc;
|
||||||
|
|
||||||
pc.mvp = camera.perspective * camera.view * model;
|
pc.mvp = camera.perspective * camera.view * model;
|
||||||
|
|
||||||
if(object.render_type == SelectableObject::RenderType::Sphere)
|
if (object.render_type == SelectableObject::RenderType::Sphere)
|
||||||
pc.mvp = prism::scale(pc.mvp, prism::float3(object.sphere_size));
|
pc.mvp = prism::scale(pc.mvp, prism::float3(object.sphere_size));
|
||||||
|
|
||||||
pc.color = {
|
pc.color = {
|
||||||
|
@ -556,22 +551,21 @@ void DebugPass::get_selected_object(int x, int y, const std::function<void(Selec
|
||||||
}
|
}
|
||||||
|
|
||||||
engine->get_gfx()->submit(commandBuffer, nullptr);
|
engine->get_gfx()->submit(commandBuffer, nullptr);
|
||||||
|
|
||||||
engine->get_gfx()->copy_texture(selectTexture, selectBuffer);
|
engine->get_gfx()->copy_texture(selectTexture, selectBuffer);
|
||||||
|
|
||||||
auto mapped_texture = reinterpret_cast<uint8_t*>(engine->get_gfx()->get_buffer_contents(selectBuffer));
|
auto mapped_texture = reinterpret_cast<uint8_t*>(engine->get_gfx()->get_buffer_contents(selectBuffer));
|
||||||
|
|
||||||
const int buffer_position = 4 * (y * extent.width + x);
|
const int buffer_position = 4 * (y * extent.width + x);
|
||||||
|
|
||||||
uint8_t a = mapped_texture[buffer_position + 3];
|
uint8_t a = mapped_texture[buffer_position + 3];
|
||||||
|
|
||||||
const int id = mapped_texture[buffer_position] +
|
const int id = mapped_texture[buffer_position] + mapped_texture[buffer_position + 1] * 256 +
|
||||||
mapped_texture[buffer_position + 1] * 256 +
|
mapped_texture[buffer_position + 2] * 256 * 256;
|
||||||
mapped_texture[buffer_position + 2] * 256 * 256;
|
|
||||||
|
|
||||||
engine->get_gfx()->release_buffer_contents(selectBuffer, mapped_texture);
|
engine->get_gfx()->release_buffer_contents(selectBuffer, mapped_texture);
|
||||||
|
|
||||||
if(a != 0) {
|
if (a != 0) {
|
||||||
callback(selectable_objects[id]);
|
callback(selectable_objects[id]);
|
||||||
} else {
|
} else {
|
||||||
SelectableObject o;
|
SelectableObject o;
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
#include "undostack.hpp"
|
#include "undostack.hpp"
|
||||||
|
|
||||||
void UndoStack::undo() {
|
void UndoStack::undo() {
|
||||||
if(stack_position >= 0) {
|
if (stack_position >= 0) {
|
||||||
command_stack[stack_position]->undo();
|
command_stack[stack_position]->undo();
|
||||||
stack_position--;
|
stack_position--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UndoStack::redo() {
|
void UndoStack::redo() {
|
||||||
if((stack_position + 1) < command_stack.size()) {
|
if ((stack_position + 1) < command_stack.size()) {
|
||||||
stack_position++;
|
stack_position++;
|
||||||
command_stack[stack_position]->execute();
|
command_stack[stack_position]->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* UndoStack::get_last_command() {
|
Command* UndoStack::get_last_command() {
|
||||||
if(command_stack.empty())
|
if (command_stack.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if(stack_position >= 0)
|
if (stack_position >= 0)
|
||||||
return command_stack[stack_position].get();
|
return command_stack[stack_position].get();
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* UndoStack::get_next_command() {
|
Command* UndoStack::get_next_command() {
|
||||||
if(command_stack.empty())
|
if (command_stack.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if((stack_position + 1) < command_stack.size())
|
if ((stack_position + 1) < command_stack.size())
|
||||||
return command_stack[stack_position + 1].get();
|
return command_stack[stack_position + 1].get();
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
add_platform_executable(
|
add_platform_executable(
|
||||||
TARGET CutsceneEditor
|
TARGET CutsceneEditor
|
||||||
APP_CLASS CutsceneEditor
|
APP_CLASS CutsceneEditor
|
||||||
APP_INCLUDE cutsceneeditor.hpp
|
APP_INCLUDE cutsceneeditor.hpp
|
||||||
SKIP_DATA ON
|
SKIP_DATA ON
|
||||||
SRC
|
SRC
|
||||||
src/cutsceneeditor.cpp
|
src/cutsceneeditor.cpp
|
||||||
include/cutsceneeditor.hpp)
|
include/cutsceneeditor.hpp)
|
||||||
target_link_libraries(CutsceneEditor PUBLIC
|
target_link_libraries(CutsceneEditor PUBLIC
|
||||||
Core
|
Core
|
||||||
EditorCommon)
|
EditorCommon)
|
||||||
target_include_directories(CutsceneEditor PUBLIC
|
target_include_directories(CutsceneEditor PUBLIC
|
||||||
include)
|
include)
|
||||||
set_engine_properties(CutsceneEditor)
|
set_engine_properties(CutsceneEditor)
|
|
@ -3,11 +3,11 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
|
#include "cutscene.hpp"
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "json_conversions.hpp"
|
#include "json_conversions.hpp"
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "cutscene.hpp"
|
|
||||||
|
|
||||||
Shot* currentShot = nullptr;
|
Shot* currentShot = nullptr;
|
||||||
AnimationChannel* currentChannel = nullptr;
|
AnimationChannel* currentChannel = nullptr;
|
||||||
|
@ -16,13 +16,15 @@ PositionKeyFrame* currentFrame = nullptr;
|
||||||
std::string currentPath;
|
std::string currentPath;
|
||||||
|
|
||||||
void app_main(prism::engine* engine) {
|
void app_main(prism::engine* engine) {
|
||||||
auto editor = (CommonEditor*)engine->get_app();
|
auto editor = (CommonEditor*)engine->get_app();
|
||||||
|
|
||||||
platform::open_window("Cutscene Editor",
|
platform::open_window(
|
||||||
{editor->getDefaultX(),
|
"Cutscene Editor",
|
||||||
editor->getDefaultY(),
|
{editor->getDefaultX(),
|
||||||
static_cast<uint32_t>(editor->getDefaultWidth()),
|
editor->getDefaultY(),
|
||||||
static_cast<uint32_t>(editor->getDefaultHeight())}, WindowFlags::Resizable);
|
static_cast<uint32_t>(editor->getDefaultWidth()),
|
||||||
|
static_cast<uint32_t>(editor->getDefaultHeight())},
|
||||||
|
WindowFlags::Resizable);
|
||||||
}
|
}
|
||||||
|
|
||||||
CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {}
|
CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {}
|
||||||
|
@ -30,7 +32,7 @@ CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {}
|
||||||
static bool has_been_docked = false;
|
static bool has_been_docked = false;
|
||||||
|
|
||||||
void CutsceneEditor::renderEditor(GFXCommandBuffer* command_buffer) {
|
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);
|
engine->get_renderer()->render(command_buffer, render_target.scene, *render_target.target, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,30 +44,30 @@ void CutsceneEditor::drawUI() {
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(!has_been_docked) {
|
if (!has_been_docked) {
|
||||||
const auto size = ImGui::GetMainViewport()->Size;
|
const auto size = ImGui::GetMainViewport()->Size;
|
||||||
|
|
||||||
ImGui::DockBuilderRemoveNode(editor_dockspace);
|
ImGui::DockBuilderRemoveNode(editor_dockspace);
|
||||||
ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace);
|
ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace);
|
||||||
ImGui::DockBuilderSetNodeSize(editor_dockspace, size);
|
ImGui::DockBuilderSetNodeSize(editor_dockspace, size);
|
||||||
|
|
||||||
ImGuiID outline_parent, view;
|
ImGuiID outline_parent, view;
|
||||||
ImGui::DockBuilderSplitNode(editor_dockspace, ImGuiDir_Left, 0.2f, &outline_parent, &view);
|
ImGui::DockBuilderSplitNode(editor_dockspace, ImGuiDir_Left, 0.2f, &outline_parent, &view);
|
||||||
|
|
||||||
ImGuiID outline, playback;
|
ImGuiID outline, playback;
|
||||||
ImGui::DockBuilderSplitNode(outline_parent, ImGuiDir_Down, 0.8f, &outline, &playback);
|
ImGui::DockBuilderSplitNode(outline_parent, ImGuiDir_Down, 0.8f, &outline, &playback);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow("Outliner", outline);
|
ImGui::DockBuilderDockWindow("Outliner", outline);
|
||||||
ImGui::DockBuilderDockWindow("Playback Settings", playback);
|
ImGui::DockBuilderDockWindow("Playback Settings", playback);
|
||||||
|
|
||||||
ImGuiID viewport_parent, properties;
|
ImGuiID viewport_parent, properties;
|
||||||
ImGui::DockBuilderSplitNode(view, ImGuiDir_Left, 0.7f, &viewport_parent, &properties);
|
ImGui::DockBuilderSplitNode(view, ImGuiDir_Left, 0.7f, &viewport_parent, &properties);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow("Properties", properties);
|
ImGui::DockBuilderDockWindow("Properties", properties);
|
||||||
|
|
||||||
ImGuiID lowerbar, viewport;
|
ImGuiID lowerbar, viewport;
|
||||||
ImGui::DockBuilderSplitNode(viewport_parent, ImGuiDir_Down, 0.3f, &lowerbar, &viewport);
|
ImGui::DockBuilderSplitNode(viewport_parent, ImGuiDir_Down, 0.3f, &lowerbar, &viewport);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow("Viewport", viewport);
|
ImGui::DockBuilderDockWindow("Viewport", viewport);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow("Timeline", lowerbar);
|
ImGui::DockBuilderDockWindow("Timeline", lowerbar);
|
||||||
|
@ -73,370 +75,378 @@ void CutsceneEditor::drawUI() {
|
||||||
|
|
||||||
ImGui::DockBuilderFinish(editor_dockspace);
|
ImGui::DockBuilderFinish(editor_dockspace);
|
||||||
|
|
||||||
has_been_docked =true;
|
has_been_docked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar())
|
if (ImGui::BeginMainMenuBar()) {
|
||||||
{
|
if (ImGui::BeginMenu("File")) {
|
||||||
if (ImGui::BeginMenu("File"))
|
if (ImGui::MenuItem("New", "CTRL+N")) {
|
||||||
{
|
|
||||||
if(ImGui::MenuItem("New", "CTRL+N")) {
|
|
||||||
engine->cutscene = std::make_unique<Cutscene>();
|
engine->cutscene = std::make_unique<Cutscene>();
|
||||||
|
|
||||||
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")) {
|
if (ImGui::MenuItem("Open", "CTRL+O")) {
|
||||||
engine->get_imgui().open_dialog(true, [this](std::string path){
|
engine->get_imgui().open_dialog(true, [this](std::string path) {
|
||||||
currentPath = path;
|
currentPath = path;
|
||||||
|
|
||||||
engine->load_cutscene(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();
|
const auto& recents = getOpenedFiles();
|
||||||
if (ImGui::BeginMenu("Open Recent...", !recents.empty())) {
|
if (ImGui::BeginMenu("Open Recent...", !recents.empty())) {
|
||||||
for (auto& file : recents) {
|
for (auto& file : recents) {
|
||||||
if (ImGui::MenuItem(file.c_str())) {
|
if (ImGui::MenuItem(file.c_str())) {
|
||||||
currentPath = file;
|
currentPath = file;
|
||||||
|
|
||||||
engine->load_cutscene(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")) {
|
if (ImGui::MenuItem("Clear")) {
|
||||||
clearOpenedFiles();
|
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);
|
engine->save_cutscene(path);
|
||||||
|
|
||||||
platform::set_window_title(0, ("Cutscene Editor - " + path).c_str());
|
platform::set_window_title(0, ("Cutscene Editor - " + path).c_str());
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
engine->save_cutscene(currentPath);
|
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) {
|
engine->get_imgui().save_dialog([](std::string path) {
|
||||||
currentPath = path;
|
currentPath = path;
|
||||||
|
|
||||||
engine->save_cutscene(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();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::MenuItem("Quit", "CTRL+Q"))
|
if (ImGui::MenuItem("Quit", "CTRL+Q"))
|
||||||
engine->quit();
|
engine->quit();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("Edit"))
|
if (ImGui::BeginMenu("Edit")) {
|
||||||
{
|
if (ImGui::MenuItem("Undo", "CTRL+Z")) {
|
||||||
if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
|
}
|
||||||
if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
|
if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {
|
||||||
|
} // Disabled item
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("Cut", "CTRL+X")) {}
|
if (ImGui::MenuItem("Cut", "CTRL+X")) {
|
||||||
if (ImGui::MenuItem("Copy", "CTRL+C")) {}
|
}
|
||||||
if (ImGui::MenuItem("Paste", "CTRL+V")) {}
|
if (ImGui::MenuItem("Copy", "CTRL+C")) {
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Paste", "CTRL+V")) {
|
||||||
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::BeginMenu("Add...")) {
|
if (ImGui::BeginMenu("Add...")) {
|
||||||
if (ImGui::MenuItem("Empty")) {
|
if (ImGui::MenuItem("Empty")) {
|
||||||
auto new_obj = engine->get_scene()->add_object();
|
auto new_obj = engine->get_scene()->add_object();
|
||||||
engine->get_scene()->get(new_obj).name = "new 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->get_imgui().open_dialog(false, [](std::string path) {
|
||||||
engine->add_prefab(*engine->get_scene(), path);
|
engine->add_prefab(*engine->get_scene(), path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Help")) {
|
if (ImGui::BeginMenu("Help")) {
|
||||||
if (ImGui::MenuItem("About")) {
|
if (ImGui::MenuItem("About")) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::Begin("Outliner")) {
|
if (ImGui::Begin("Outliner")) {
|
||||||
drawOutline();
|
drawOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Properties")) {
|
if (ImGui::Begin("Properties")) {
|
||||||
drawPropertyEditor();
|
drawPropertyEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Timeline")) {
|
if (ImGui::Begin("Timeline")) {
|
||||||
if(engine->cutscene != nullptr) {
|
if (engine->cutscene != nullptr) {
|
||||||
if(ImGui::Button("Add Shot")) {
|
if (ImGui::Button("Add Shot")) {
|
||||||
engine->cutscene->shots.emplace_back();
|
engine->cutscene->shots.emplace_back();
|
||||||
currentShot = &engine->cutscene->shots.back();
|
currentShot = &engine->cutscene->shots.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentShot != nullptr) {
|
if (currentShot != nullptr) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::Button("Change scene")) {
|
if (ImGui::Button("Change scene")) {
|
||||||
open_asset<Scene>(AssetType::Scene, [](prism::path path) {
|
open_asset<Scene>(AssetType::Scene, [](prism::path path) {
|
||||||
currentShot->scene = engine->load_scene(prism::game_domain / path);
|
currentShot->scene = engine->load_scene(prism::game_domain / path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(25.0f);
|
ImGui::SetNextItemWidth(25.0f);
|
||||||
|
|
||||||
ImGui::DragInt("Begin", ¤tShot->begin, 1.0f, 0, 1000);
|
ImGui::DragInt("Begin", ¤tShot->begin, 1.0f, 0, 1000);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(25.0f);
|
ImGui::SetNextItemWidth(25.0f);
|
||||||
|
|
||||||
ImGui::DragInt("Length", ¤tShot->length, 1.0f, 0, 1000);
|
ImGui::DragInt("Length", ¤tShot->length, 1.0f, 0, 1000);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::Button("Remove")) {
|
if (ImGui::Button("Remove")) {
|
||||||
utility::erase(engine->cutscene->shots, *currentShot);
|
utility::erase(engine->cutscene->shots, *currentShot);
|
||||||
currentShot = nullptr;
|
currentShot = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
const auto& draw_list = ImGui::GetWindowDrawList();
|
const auto& draw_list = ImGui::GetWindowDrawList();
|
||||||
const ImVec2 p = ImGui::GetCursorScreenPos();
|
const ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
int i = 0;
|
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 a = ImVec2(p.x + (5 * shot.begin), p.y);
|
||||||
auto b = ImVec2(p.x + (5 * (shot.begin + shot.length)), p.y + 50);
|
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->AddRectFilled(a, b, IM_COL32(0, 0, 100, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_list->AddRect(a, b, IM_COL32_WHITE);
|
draw_list->AddRect(a, b, IM_COL32_WHITE);
|
||||||
|
|
||||||
std::string name = "Shot " + std::to_string(i);
|
std::string name = "Shot " + std::to_string(i);
|
||||||
draw_list->AddText(ImVec2(a.x + 2, a.y + 2), IM_COL32_WHITE, name.c_str());
|
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();
|
auto c = ImGui::GetMousePos();
|
||||||
if(c.x > a.x && c.x < b.x && c.y > a.y && c.y < b.y) {
|
if (c.x > a.x && c.x < b.x && c.y > a.y && c.y < b.y) {
|
||||||
if(currentShot == &shot) {
|
if (currentShot == &shot) {
|
||||||
currentShot = nullptr;
|
currentShot = nullptr;
|
||||||
} else {
|
} else {
|
||||||
currentShot = &shot;
|
currentShot = &shot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
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 {
|
} else {
|
||||||
ImGui::Text("No cutscene loaded.");
|
ImGui::Text("No cutscene loaded.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Animation Editor")) {
|
if (ImGui::Begin("Animation Editor")) {
|
||||||
if(currentShot != nullptr && currentShot->scene != nullptr) {
|
if (currentShot != nullptr && currentShot->scene != nullptr) {
|
||||||
ImGui::BeginChild("animations", ImVec2(150, -1), true);
|
ImGui::BeginChild("animations", ImVec2(150, -1), true);
|
||||||
|
|
||||||
if(ImGui::Button("Add Channel")) {
|
if (ImGui::Button("Add Channel")) {
|
||||||
currentShot->channels.emplace_back();
|
currentShot->channels.emplace_back();
|
||||||
currentChannel = ¤tShot->channels.back();
|
currentChannel = ¤tShot->channels.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(auto& channel : currentShot->channels) {
|
for (auto& channel : currentShot->channels) {
|
||||||
std::string name = "Channel " + std::to_string(i);
|
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;
|
currentChannel = &channel;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentShot->channels.empty())
|
if (currentShot->channels.empty())
|
||||||
ImGui::TextDisabled("No channels in this shot.");
|
ImGui::TextDisabled("No channels in this shot.");
|
||||||
|
|
||||||
ImGui::EndChildFrame();
|
ImGui::EndChildFrame();
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::BeginChild("editanim", ImVec2(-1, -1), false);
|
ImGui::BeginChild("editanim", ImVec2(-1, -1), false);
|
||||||
|
|
||||||
if(currentChannel != nullptr) {
|
if (currentChannel != nullptr) {
|
||||||
if(ImGui::Button("Add Position Frame")) {
|
if (ImGui::Button("Add Position Frame")) {
|
||||||
currentChannel->positions.emplace_back();
|
currentChannel->positions.emplace_back();
|
||||||
currentFrame = ¤tChannel->positions.back();
|
currentFrame = ¤tChannel->positions.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(50.0f);
|
ImGui::SetNextItemWidth(50.0f);
|
||||||
|
|
||||||
const char* preview_value = "None";
|
const char* preview_value = "None";
|
||||||
if(currentChannel->target != prism::NullObject && currentShot->scene->has<Data>(currentChannel->target))
|
if (currentChannel->target != prism::NullObject &&
|
||||||
|
currentShot->scene->has<Data>(currentChannel->target))
|
||||||
preview_value = currentShot->scene->get(currentChannel->target).name.c_str();
|
preview_value = currentShot->scene->get(currentChannel->target).name.c_str();
|
||||||
|
|
||||||
if(ImGui::BeginCombo("Target", preview_value)) {
|
if (ImGui::BeginCombo("Target", preview_value)) {
|
||||||
for(auto& object : currentShot->scene->get_objects()) {
|
for (auto& object : currentShot->scene->get_objects()) {
|
||||||
if(ImGui::Selectable(currentShot->scene->get(object).name.c_str())) {
|
if (ImGui::Selectable(currentShot->scene->get(object).name.c_str())) {
|
||||||
currentChannel->target = object;
|
currentChannel->target = object;
|
||||||
currentChannel->bone = nullptr;
|
currentChannel->bone = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentShot->scene->has<Renderable>(object) && !currentShot->scene->get<Renderable>(object).mesh->bones.empty()) {
|
if (currentShot->scene->has<Renderable>(object) &&
|
||||||
|
!currentShot->scene->get<Renderable>(object).mesh->bones.empty()) {
|
||||||
ImGui::Indent();
|
ImGui::Indent();
|
||||||
|
|
||||||
for(auto& bone : currentShot->scene->get<Renderable>(object).mesh->bones) {
|
for (auto& bone : currentShot->scene->get<Renderable>(object).mesh->bones) {
|
||||||
if(ImGui::Selectable(bone.name.c_str())) {
|
if (ImGui::Selectable(bone.name.c_str())) {
|
||||||
currentChannel->bone = &bone;
|
currentChannel->bone = &bone;
|
||||||
currentChannel->target = prism::NullObject;
|
currentChannel->target = prism::NullObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::Button("Remove Channel")) {
|
if (ImGui::Button("Remove Channel")) {
|
||||||
utility::erase(currentShot->channels, *currentChannel);
|
utility::erase(currentShot->channels, *currentChannel);
|
||||||
currentChannel = nullptr;
|
currentChannel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentFrame != nullptr) {
|
if (currentFrame != nullptr) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(10.0f);
|
ImGui::SetNextItemWidth(10.0f);
|
||||||
|
|
||||||
ImGui::DragFloat("FT", ¤tFrame->time, 1.0f, 0.0f, 10000.0f);
|
ImGui::DragFloat("FT", ¤tFrame->time, 1.0f, 0.0f, 10000.0f);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(50.0f);
|
ImGui::SetNextItemWidth(50.0f);
|
||||||
|
|
||||||
ImGui::DragFloat3("FV", currentFrame->value.ptr());
|
ImGui::DragFloat3("FV", currentFrame->value.ptr());
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::Button("Remove Keyframe")) {
|
if (ImGui::Button("Remove Keyframe")) {
|
||||||
utility::erase(currentChannel->positions, *currentFrame);
|
utility::erase(currentChannel->positions, *currentFrame);
|
||||||
currentFrame = nullptr;
|
currentFrame = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentChannel != nullptr) {
|
if (currentChannel != nullptr) {
|
||||||
const auto& draw_list = ImGui::GetWindowDrawList();
|
const auto& draw_list = ImGui::GetWindowDrawList();
|
||||||
const ImVec2 p = ImGui::GetCursorScreenPos();
|
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);
|
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->AddCircleFilled(c, 5.0f, IM_COL32(0, 0, 100, 255));
|
||||||
|
|
||||||
draw_list->AddCircle(c, 5.0f, IM_COL32_WHITE);
|
draw_list->AddCircle(c, 5.0f, IM_COL32_WHITE);
|
||||||
|
|
||||||
if(ImGui::IsMouseClicked(0)) {
|
if (ImGui::IsMouseClicked(0)) {
|
||||||
ImVec2 a = ImVec2(p.x + (keyframe.time * 5) - 5, p.y - 5);
|
ImVec2 a = ImVec2(p.x + (keyframe.time * 5) - 5, p.y - 5);
|
||||||
ImVec2 b = 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();
|
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 (mouse_pos.x > a.x && mouse_pos.x < b.x && mouse_pos.y > a.y && mouse_pos.y < b.y) {
|
||||||
if(currentFrame == &keyframe) {
|
if (currentFrame == &keyframe) {
|
||||||
currentFrame = nullptr;
|
currentFrame = nullptr;
|
||||||
} else {
|
} else {
|
||||||
currentFrame = &keyframe;
|
currentFrame = &keyframe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 shot_start = ImVec2(p.x + (currentShot->begin * 5), p.y + 10.0f);
|
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);
|
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_start, 2.5f, IM_COL32(255, 0, 0, 255));
|
||||||
draw_list->AddCircleFilled(shot_end, 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 {
|
} else {
|
||||||
ImGui::TextDisabled("No animation selected.");
|
ImGui::TextDisabled("No animation selected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextDisabled("No shot selected.");
|
ImGui::TextDisabled("No shot selected.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Playback Settings")) {
|
if (ImGui::Begin("Playback Settings")) {
|
||||||
if(ImGui::Button(engine->play_cutscene ? "Stop" : "Play")) {
|
if (ImGui::Button(engine->play_cutscene ? "Stop" : "Play")) {
|
||||||
engine->play_cutscene = !engine->play_cutscene;
|
engine->play_cutscene = !engine->play_cutscene;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::DragFloat("Time", &engine->current_cutscene_time, 1.0f, 0.0f, 1000.0f);
|
ImGui::DragFloat("Time", &engine->current_cutscene_time, 1.0f, 0.0f, 1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Viewport")) {
|
if (ImGui::Begin("Viewport")) {
|
||||||
if(currentShot != nullptr && currentShot->scene != nullptr)
|
if (currentShot != nullptr && currentShot->scene != nullptr)
|
||||||
drawViewport(currentShot->scene);
|
drawViewport(currentShot->scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
|
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
|
||||||
engine->current_cutscene_time -= 1.0f;
|
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;
|
engine->current_cutscene_time += 1.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
set(SRC
|
set(SRC
|
||||||
include/prismeditor.hpp
|
include/prismeditor.hpp
|
||||||
include/materialeditor.hpp
|
include/materialeditor.hpp
|
||||||
include/sceneeditor.hpp
|
include/sceneeditor.hpp
|
||||||
include/prefabeditor.hpp
|
include/prefabeditor.hpp
|
||||||
|
|
||||||
src/prismeditor.cpp
|
src/prismeditor.cpp
|
||||||
src/materialeditor.cpp
|
src/materialeditor.cpp
|
||||||
src/sceneeditor.cpp
|
src/sceneeditor.cpp
|
||||||
src/prefabeditor.cpp)
|
src/prefabeditor.cpp)
|
||||||
|
|
||||||
add_platform_executable(
|
add_platform_executable(
|
||||||
TARGET PrismEditor
|
TARGET PrismEditor
|
||||||
APP_CLASS PrismEditor
|
APP_CLASS PrismEditor
|
||||||
APP_INCLUDE prismeditor.hpp
|
APP_INCLUDE prismeditor.hpp
|
||||||
SKIP_DATA ON
|
SKIP_DATA ON
|
||||||
SRC ${SRC})
|
SRC ${SRC})
|
||||||
target_link_libraries(PrismEditor PUBLIC
|
target_link_libraries(PrismEditor PUBLIC
|
||||||
Core
|
Core
|
||||||
EditorCommon)
|
EditorCommon)
|
||||||
target_include_directories(PrismEditor PUBLIC
|
target_include_directories(PrismEditor PUBLIC
|
||||||
include)
|
include)
|
||||||
set_engine_properties(PrismEditor)
|
set_engine_properties(PrismEditor)
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "prismeditor.hpp"
|
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
|
#include "prismeditor.hpp"
|
||||||
#include "scene.hpp"
|
#include "scene.hpp"
|
||||||
|
|
||||||
class MaterialEditor : public Editor {
|
class MaterialEditor : public Editor {
|
||||||
|
@ -17,10 +17,10 @@ public:
|
||||||
std::string get_title() const override;
|
std::string get_title() const override;
|
||||||
|
|
||||||
Scene* get_scene() const override;
|
Scene* get_scene() const override;
|
||||||
|
|
||||||
void setup_windows(ImGuiID dockspace) override;
|
void setup_windows(ImGuiID dockspace) override;
|
||||||
|
|
||||||
void setup_material();
|
void setup_material();
|
||||||
|
|
||||||
void draw(CommonEditor* editor) override;
|
void draw(CommonEditor* editor) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
std::string get_title() const override;
|
std::string get_title() const override;
|
||||||
|
|
||||||
Scene* get_scene() const override;
|
Scene* get_scene() const override;
|
||||||
|
|
||||||
void setup_windows(ImGuiID dockspace) override;
|
void setup_windows(ImGuiID dockspace) override;
|
||||||
|
|
||||||
void draw(CommonEditor* editor) override;
|
void draw(CommonEditor* editor) override;
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Scene;
|
||||||
class Editor {
|
class Editor {
|
||||||
public:
|
public:
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
bool has_been_docked = false;
|
bool has_been_docked = false;
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
bool wants_to_close = false;
|
bool wants_to_close = false;
|
||||||
|
@ -19,15 +19,21 @@ public:
|
||||||
auto window_class = get_window_class();
|
auto window_class = get_window_class();
|
||||||
return get_title() + "###" + std::to_string(window_class.ClassId);
|
return get_title() + "###" + std::to_string(window_class.ClassId);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Scene* get_scene() const {
|
virtual Scene* get_scene() const {
|
||||||
return nullptr;
|
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 draw([[maybe_unused]] CommonEditor* editor) {}
|
||||||
|
|
||||||
virtual void setup_windows([[maybe_unused]] ImGuiID dockspace) {}
|
virtual void setup_windows([[maybe_unused]] ImGuiID dockspace) {}
|
||||||
|
|
||||||
ImGuiWindowClass get_window_class() const {
|
ImGuiWindowClass get_window_class() const {
|
||||||
|
@ -37,7 +43,7 @@ public:
|
||||||
|
|
||||||
return window_class;
|
return window_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_window_name(std::string title) {
|
std::string get_window_name(std::string title) {
|
||||||
return title + "##" + std::to_string((uint64_t)this);
|
return title + "##" + std::to_string((uint64_t)this);
|
||||||
}
|
}
|
||||||
|
@ -45,21 +51,21 @@ public:
|
||||||
bool begin(std::string title, bool* p_open = nullptr) {
|
bool begin(std::string title, bool* p_open = nullptr) {
|
||||||
return ImGui::Begin(get_window_name(title).c_str(), p_open);
|
return ImGui::Begin(get_window_name(title).c_str(), p_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
UndoStack undo_stack;
|
UndoStack undo_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrismEditor : public CommonEditor {
|
class PrismEditor : public CommonEditor {
|
||||||
public:
|
public:
|
||||||
PrismEditor();
|
PrismEditor();
|
||||||
|
|
||||||
void renderEditor(GFXCommandBuffer* command_buffer) override;
|
void renderEditor(GFXCommandBuffer* command_buffer) override;
|
||||||
void drawUI() override;
|
void drawUI() override;
|
||||||
void updateEditor(float deltaTime) override;
|
void updateEditor(float deltaTime) override;
|
||||||
|
|
||||||
void object_selected(prism::Object object) override;
|
void object_selected(prism::Object object) override;
|
||||||
void asset_selected(const std::filesystem::path& path, AssetType type) override;
|
void asset_selected(const std::filesystem::path& path, AssetType type) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void open_asset(prism::path path);
|
void open_asset(prism::path path);
|
||||||
void setup_editor(Editor* editor);
|
void setup_editor(Editor* editor);
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "prismeditor.hpp"
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
#include "prismeditor.hpp"
|
||||||
|
|
||||||
class AddObjectCommand : public Command {
|
class AddObjectCommand : public Command {
|
||||||
public:
|
public:
|
||||||
prism::Object id;
|
prism::Object id;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
std::string fetch_name() override {
|
std::string fetch_name() override {
|
||||||
return "Add object " + name;
|
return "Add object " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo() override {
|
void undo() override {
|
||||||
engine->get_scene()->remove_object(id);
|
engine->get_scene()->remove_object(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute() override {
|
void execute() override {
|
||||||
engine->get_scene()->add_object_by_id(id);
|
engine->get_scene()->add_object_by_id(id);
|
||||||
engine->get_scene()->get(id).name = name;
|
engine->get_scene()->get(id).name = name;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "materialeditor.hpp"
|
#include "materialeditor.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ void MaterialEditor::setup_windows(ImGuiID dockspace) {
|
||||||
|
|
||||||
ImGuiID dock_id_left, dock_id_right;
|
ImGuiID dock_id_left, dock_id_right;
|
||||||
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.40f, &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("Viewport").c_str(), dock_id_left);
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Node Editor").c_str(), dock_id_right);
|
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) {
|
void MaterialEditor::draw(CommonEditor* editor) {
|
||||||
if(!material)
|
if (!material)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File")) {
|
||||||
if(ImGui::MenuItem("Save", "CTRL+S")) {
|
if (ImGui::MenuItem("Save", "CTRL+S")) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
engine->get_imgui().save_dialog([this](std::string path) {
|
engine->get_imgui().save_dialog([this](std::string path) {
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
|
||||||
save_material(*material, path);
|
save_material(*material, path);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
save_material(*material, prism::get_file_path(path));
|
save_material(*material, prism::get_file_path(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("Save as...", "CTRL+S")) {
|
if (ImGui::MenuItem("Save as...", "CTRL+S")) {
|
||||||
engine->get_imgui().save_dialog([this](std::string path) {
|
engine->get_imgui().save_dialog([this](std::string path) {
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
|
||||||
save_material(*material, path);
|
save_material(*material, path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::MenuItem("Close"))
|
if (ImGui::MenuItem("Close"))
|
||||||
wants_to_close = true;
|
wants_to_close = true;
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::MenuItem("Compile"))
|
if (ImGui::MenuItem("Compile"))
|
||||||
recompile(*material);
|
recompile(*material);
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto viewport_scene = engine->get_scene();
|
auto viewport_scene = engine->get_scene();
|
||||||
|
|
||||||
if(viewport_scene != nullptr) {
|
if (viewport_scene != nullptr) {
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
if(begin("Viewport"))
|
if (begin("Viewport"))
|
||||||
editor->drawViewport(viewport_scene);
|
editor->drawViewport(viewport_scene);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(begin("Node Editor")) {
|
if (begin("Node Editor")) {
|
||||||
const auto draw_list = ImGui::GetWindowDrawList();
|
const auto draw_list = ImGui::GetWindowDrawList();
|
||||||
const auto window_pos = ImGui::GetCursorScreenPos();
|
const auto window_pos = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
|
@ -97,42 +97,40 @@ void MaterialEditor::draw(CommonEditor* editor) {
|
||||||
|
|
||||||
auto& property = material->colorProperty;
|
auto& property = material->colorProperty;
|
||||||
|
|
||||||
ImGui::PushID(property.name.c_str());
|
ImGui::PushID(property.name.c_str());
|
||||||
|
|
||||||
if(ImGui::BeginCombo("Type", "test")) {
|
if (ImGui::BeginCombo("Type", "test")) {
|
||||||
if(ImGui::Selectable("Vector3"))
|
if (ImGui::Selectable("Vector3"))
|
||||||
property.type = DataType::Vector3;
|
property.type = DataType::Vector3;
|
||||||
|
|
||||||
if(ImGui::Selectable("Texture"))
|
if (ImGui::Selectable("Texture"))
|
||||||
property.type = DataType::AssetTexture;
|
property.type = DataType::AssetTexture;
|
||||||
|
|
||||||
if(ImGui::Selectable("Float"))
|
if (ImGui::Selectable("Float"))
|
||||||
property.type = DataType::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) {
|
switch (property.type) {
|
||||||
case DataType::Vector3:
|
case DataType::Vector3:
|
||||||
changed |= ImGui::ColorEdit3("", property.value.ptr());
|
changed |= ImGui::ColorEdit3("", property.value.ptr());
|
||||||
break;
|
break;
|
||||||
case DataType::Float:
|
case DataType::Float:
|
||||||
changed |= ImGui::DragFloat("", &property.float_value);
|
changed |= ImGui::DragFloat("", &property.float_value);
|
||||||
break;
|
break;
|
||||||
case DataType::AssetTexture:
|
case DataType::AssetTexture:
|
||||||
changed |= editor->edit_asset("", property.value_tex);
|
changed |= editor->edit_asset("", property.value_tex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
|
||||||
if(changed)
|
if (changed)
|
||||||
recompile(*material);
|
recompile(*material);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "prefabeditor.hpp"
|
#include "prefabeditor.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ void PrefabEditor::setup_windows(ImGuiID dockspace) {
|
||||||
void PrefabEditor::draw(CommonEditor* editor) {
|
void PrefabEditor::draw(CommonEditor* editor) {
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File")) {
|
||||||
if(ImGui::MenuItem("Save", "CTRL+S")) {
|
if (ImGui::MenuItem("Save", "CTRL+S")) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
engine->get_imgui().save_dialog([this](std::string path) {
|
engine->get_imgui().save_dialog([this](std::string path) {
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
@ -53,12 +53,12 @@ void PrefabEditor::draw(CommonEditor* editor) {
|
||||||
engine->save_prefab(root_object, path);
|
engine->save_prefab(root_object, path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::MenuItem("Close"))
|
if (ImGui::MenuItem("Close"))
|
||||||
wants_to_close = true;
|
wants_to_close = true;
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,13 +67,13 @@ void PrefabEditor::draw(CommonEditor* editor) {
|
||||||
|
|
||||||
auto viewport_scene = engine->get_scene();
|
auto viewport_scene = engine->get_scene();
|
||||||
|
|
||||||
if(viewport_scene != nullptr) {
|
if (viewport_scene != nullptr) {
|
||||||
auto window_class = get_window_class();
|
auto window_class = get_window_class();
|
||||||
|
|
||||||
if(showOutliner) {
|
if (showOutliner) {
|
||||||
ImGui::SetNextWindowClass(&window_class);
|
ImGui::SetNextWindowClass(&window_class);
|
||||||
|
|
||||||
if(begin("Outliner", &showOutliner))
|
if (begin("Outliner", &showOutliner))
|
||||||
editor->drawOutline();
|
editor->drawOutline();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -91,7 +91,7 @@ void PrefabEditor::draw(CommonEditor* editor) {
|
||||||
ImGui::SetNextWindowClass(&window_class);
|
ImGui::SetNextWindowClass(&window_class);
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
if(begin("Viewport"))
|
if (begin("Viewport"))
|
||||||
editor->drawViewport(viewport_scene);
|
editor->drawViewport(viewport_scene);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
#include "prismeditor.hpp"
|
#include "prismeditor.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "json_conversions.hpp"
|
#include "json_conversions.hpp"
|
||||||
#include "platform.hpp"
|
|
||||||
#include "string_utils.hpp"
|
|
||||||
#include "sceneeditor.hpp"
|
|
||||||
#include "materialeditor.hpp"
|
#include "materialeditor.hpp"
|
||||||
|
#include "platform.hpp"
|
||||||
#include "prefabeditor.hpp"
|
#include "prefabeditor.hpp"
|
||||||
|
#include "sceneeditor.hpp"
|
||||||
|
#include "string_utils.hpp"
|
||||||
|
|
||||||
std::string get_filename(const std::string path) {
|
std::string get_filename(const std::string path) {
|
||||||
return path.substr(path.find_last_of("/") + 1, path.length());
|
return path.substr(path.find_last_of("/") + 1, path.length());
|
||||||
|
@ -20,21 +20,20 @@ std::string get_filename(const std::string path) {
|
||||||
std::vector<Editor*> editors;
|
std::vector<Editor*> editors;
|
||||||
|
|
||||||
void app_main(prism::engine* engine) {
|
void app_main(prism::engine* engine) {
|
||||||
CommonEditor* editor = (CommonEditor*)engine->get_app();
|
CommonEditor* editor = (CommonEditor*)engine->get_app();
|
||||||
|
|
||||||
platform::open_window("Prism Editor",
|
platform::open_window(
|
||||||
{editor->getDefaultX(),
|
"Prism Editor",
|
||||||
editor->getDefaultY(),
|
{editor->getDefaultX(),
|
||||||
static_cast<uint32_t>(editor->getDefaultWidth()),
|
editor->getDefaultY(),
|
||||||
static_cast<uint32_t>(editor->getDefaultHeight())},
|
static_cast<uint32_t>(editor->getDefaultWidth()),
|
||||||
WindowFlags::Resizable);
|
static_cast<uint32_t>(editor->getDefaultHeight())},
|
||||||
|
WindowFlags::Resizable);
|
||||||
|
|
||||||
engine->update_physics = false;
|
engine->update_physics = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrismEditor::PrismEditor() : CommonEditor("PrismEditor") {
|
PrismEditor::PrismEditor() : CommonEditor("PrismEditor") {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void prepScene() {
|
void prepScene() {
|
||||||
auto scene = engine->get_scene();
|
auto scene = engine->get_scene();
|
||||||
|
@ -44,13 +43,13 @@ void prepScene() {
|
||||||
scene->get(camera).editor_object = true;
|
scene->get(camera).editor_object = true;
|
||||||
|
|
||||||
scene->add<Camera>(camera);
|
scene->add<Camera>(camera);
|
||||||
|
|
||||||
camera_look_at(*scene, camera, prism::float3(0, 2, 3), prism::float3(0));
|
camera_look_at(*scene, camera, prism::float3(0, 2, 3), prism::float3(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepThreePointLighting() {
|
void prepThreePointLighting() {
|
||||||
auto scene = engine->get_scene();
|
auto scene = engine->get_scene();
|
||||||
|
|
||||||
auto probe = scene->add_object();
|
auto probe = scene->add_object();
|
||||||
scene->add<EnvironmentProbe>(probe).is_sized = false;
|
scene->add<EnvironmentProbe>(probe).is_sized = false;
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ void prepPrefabScene() {
|
||||||
|
|
||||||
Renderable* prepMaterialScene() {
|
Renderable* prepMaterialScene() {
|
||||||
auto scene = engine->get_scene();
|
auto scene = engine->get_scene();
|
||||||
|
|
||||||
auto plane = scene->add_object();
|
auto plane = scene->add_object();
|
||||||
scene->get(plane).name = "plane";
|
scene->get(plane).name = "plane";
|
||||||
scene->get(plane).editor_object = true;
|
scene->get(plane).editor_object = true;
|
||||||
|
@ -93,24 +92,25 @@ Renderable* prepMaterialScene() {
|
||||||
scene->get<Transform>(plane).scale = prism::float3(50);
|
scene->get<Transform>(plane).scale = prism::float3(50);
|
||||||
|
|
||||||
scene->add<Renderable>(plane).mesh = assetm->get<Mesh>(prism::base_domain / "models/plane.model");
|
scene->add<Renderable>(plane).mesh = assetm->get<Mesh>(prism::base_domain / "models/plane.model");
|
||||||
scene->get<Renderable>(plane).materials.push_back(assetm->get<Material>(prism::base_domain / "materials/Material.material"));
|
scene->get<Renderable>(plane).materials.push_back(
|
||||||
|
assetm->get<Material>(prism::base_domain / "materials/Material.material"));
|
||||||
|
|
||||||
auto sphere = scene->add_object();
|
auto sphere = scene->add_object();
|
||||||
scene->get(sphere).name = "sphere";
|
scene->get(sphere).name = "sphere";
|
||||||
scene->get(sphere).editor_object = true;
|
scene->get(sphere).editor_object = true;
|
||||||
|
|
||||||
scene->get<Transform>(sphere).rotation = euler_to_quat(prism::float3(radians(90.0f), 0, 0));
|
scene->get<Transform>(sphere).rotation = euler_to_quat(prism::float3(radians(90.0f), 0, 0));
|
||||||
|
|
||||||
scene->add<Renderable>(sphere).mesh = assetm->get<Mesh>(prism::base_domain / "models/sphere.model");
|
scene->add<Renderable>(sphere).mesh = assetm->get<Mesh>(prism::base_domain / "models/sphere.model");
|
||||||
|
|
||||||
prepThreePointLighting();
|
prepThreePointLighting();
|
||||||
|
|
||||||
return &scene->get<Renderable>(sphere);
|
return &scene->get<Renderable>(sphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OpenAssetRequest {
|
struct OpenAssetRequest {
|
||||||
OpenAssetRequest(std::string p, bool is_r) : path(p), is_relative(is_r) {}
|
OpenAssetRequest(std::string p, bool is_r) : path(p), is_relative(is_r) {}
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
bool is_relative;
|
bool is_relative;
|
||||||
};
|
};
|
||||||
|
@ -120,7 +120,7 @@ std::vector<OpenAssetRequest> open_requests;
|
||||||
void PrismEditor::setup_editor(Editor*) {}
|
void PrismEditor::setup_editor(Editor*) {}
|
||||||
|
|
||||||
void PrismEditor::open_asset(const prism::path path) {
|
void PrismEditor::open_asset(const prism::path path) {
|
||||||
if(path.extension() == ".prefab") {
|
if (path.extension() == ".prefab") {
|
||||||
PrefabEditor* editor = new PrefabEditor();
|
PrefabEditor* editor = new PrefabEditor();
|
||||||
editor->path = path.string();
|
editor->path = path.string();
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
@ -133,26 +133,26 @@ void PrismEditor::open_asset(const prism::path path) {
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
} else if(path.extension() == ".scene") {
|
} else if (path.extension() == ".scene") {
|
||||||
SceneEditor* editor = new SceneEditor();
|
SceneEditor* editor = new SceneEditor();
|
||||||
editor->path = path.string();
|
editor->path = path.string();
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
|
||||||
editor->scene = engine->load_scene(path);
|
editor->scene = engine->load_scene(path);
|
||||||
prepScene();
|
prepScene();
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
} else if(path.extension() == ".material") {
|
} else if (path.extension() == ".material") {
|
||||||
MaterialEditor* editor = new MaterialEditor();
|
MaterialEditor* editor = new MaterialEditor();
|
||||||
editor->path = path.string();
|
editor->path = path.string();
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
|
||||||
engine->create_empty_scene();
|
engine->create_empty_scene();
|
||||||
prepScene();
|
prepScene();
|
||||||
editor->renderable = prepMaterialScene();
|
editor->renderable = prepMaterialScene();
|
||||||
|
|
||||||
editor->material = assetm->get<Material>(path);
|
editor->material = assetm->get<Material>(path);
|
||||||
|
|
||||||
editor->setup_material();
|
editor->setup_material();
|
||||||
|
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
|
@ -162,7 +162,7 @@ void PrismEditor::open_asset(const prism::path path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrismEditor::renderEditor(GFXCommandBuffer* command_buffer) {
|
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);
|
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::BeginMainMenuBar()) {
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File")) {
|
||||||
if(ImGui::BeginMenu("New")) {
|
if (ImGui::BeginMenu("New")) {
|
||||||
if(ImGui::MenuItem("Scene")) {
|
if (ImGui::MenuItem("Scene")) {
|
||||||
SceneEditor* editor = new SceneEditor();
|
SceneEditor* editor = new SceneEditor();
|
||||||
editor->modified = true;
|
editor->modified = true;
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
|
||||||
engine->create_empty_scene();
|
engine->create_empty_scene();
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
prepScene();
|
prepScene();
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::MenuItem("Prefab")) {
|
if (ImGui::MenuItem("Prefab")) {
|
||||||
PrefabEditor* editor = new PrefabEditor();
|
PrefabEditor* editor = new PrefabEditor();
|
||||||
editor->modified = true;
|
editor->modified = true;
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
|
||||||
engine->create_empty_scene();
|
engine->create_empty_scene();
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
prepScene();
|
prepScene();
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::MenuItem("Material")) {
|
if (ImGui::MenuItem("Material")) {
|
||||||
MaterialEditor* editor = new MaterialEditor();
|
MaterialEditor* editor = new MaterialEditor();
|
||||||
editor->modified = true;
|
editor->modified = true;
|
||||||
setup_editor(editor);
|
setup_editor(editor);
|
||||||
|
|
||||||
engine->create_empty_scene();
|
engine->create_empty_scene();
|
||||||
prepScene();
|
prepScene();
|
||||||
editor->material = assetm->add<Material>();
|
editor->material = assetm->add<Material>();
|
||||||
editor->renderable = prepMaterialScene();
|
editor->renderable = prepMaterialScene();
|
||||||
editor->scene = engine->get_scene();
|
editor->scene = engine->get_scene();
|
||||||
|
|
||||||
editor->setup_material();
|
editor->setup_material();
|
||||||
|
|
||||||
editors.push_back(editor);
|
editors.push_back(editor);
|
||||||
|
@ -220,32 +220,32 @@ void PrismEditor::drawUI() {
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::MenuItem("Open", "CTRL+O")) {
|
if (ImGui::MenuItem("Open", "CTRL+O")) {
|
||||||
engine->get_imgui().open_dialog(true, [this](std::string path) {
|
engine->get_imgui().open_dialog(true, [this](std::string path) {
|
||||||
open_requests.emplace_back(path, false);
|
open_requests.emplace_back(path, false);
|
||||||
|
|
||||||
addOpenedFile(path);
|
addOpenedFile(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& recents = getOpenedFiles();
|
const auto& recents = getOpenedFiles();
|
||||||
if (ImGui::BeginMenu("Open Recent...", !recents.empty())) {
|
if (ImGui::BeginMenu("Open Recent...", !recents.empty())) {
|
||||||
for (auto& file : recents) {
|
for (auto& file : recents) {
|
||||||
if (ImGui::MenuItem(file.c_str()))
|
if (ImGui::MenuItem(file.c_str()))
|
||||||
open_requests.emplace_back(file, false);
|
open_requests.emplace_back(file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if (ImGui::MenuItem("Clear"))
|
if (ImGui::MenuItem("Clear"))
|
||||||
clearOpenedFiles();
|
clearOpenedFiles();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::MenuItem("Quit", "CTRL+Q"))
|
if (ImGui::MenuItem("Quit", "CTRL+Q"))
|
||||||
engine->quit();
|
engine->quit();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -254,48 +254,48 @@ void PrismEditor::drawUI() {
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& editor : editors) {
|
for (auto& editor : editors) {
|
||||||
if(!editor->has_been_docked) {
|
if (!editor->has_been_docked) {
|
||||||
ImGui::DockBuilderDockWindow(editor->get_window_title().c_str(), dock_id);
|
ImGui::DockBuilderDockWindow(editor->get_window_title().c_str(), dock_id);
|
||||||
ImGui::DockBuilderFinish(dock_id);
|
ImGui::DockBuilderFinish(dock_id);
|
||||||
|
|
||||||
editor->has_been_docked = true;
|
editor->has_been_docked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImGuiID editor_dockspace = ImGui::GetID(editor);
|
const ImGuiID editor_dockspace = ImGui::GetID(editor);
|
||||||
|
|
||||||
if(ImGui::DockBuilderGetNode(editor_dockspace) == nullptr) {
|
|
||||||
const auto size = ImGui::GetMainViewport()->Size;
|
|
||||||
|
|
||||||
ImGui::DockBuilderRemoveNode(editor_dockspace);
|
if (ImGui::DockBuilderGetNode(editor_dockspace) == nullptr) {
|
||||||
ImGui::DockBuilderAddNode(editor_dockspace, ImGuiDockNodeFlags_DockSpace);
|
const auto size = ImGui::GetMainViewport()->Size;
|
||||||
ImGui::DockBuilderSetNodeSize(editor_dockspace, 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));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
|
|
||||||
int window_flags = 0;
|
int window_flags = 0;
|
||||||
if(editor->has_menubar())
|
if (editor->has_menubar())
|
||||||
window_flags |= ImGuiWindowFlags_MenuBar;
|
window_flags |= ImGuiWindowFlags_MenuBar;
|
||||||
|
|
||||||
if(editor->modified)
|
if (editor->modified)
|
||||||
window_flags |= ImGuiWindowFlags_UnsavedDocument;
|
window_flags |= ImGuiWindowFlags_UnsavedDocument;
|
||||||
|
|
||||||
bool should_draw = ImGui::Begin(editor->get_window_title().c_str(), nullptr, window_flags);
|
bool should_draw = ImGui::Begin(editor->get_window_title().c_str(), nullptr, window_flags);
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
ImGui::DockSpace(editor_dockspace, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
|
ImGui::DockSpace(editor_dockspace, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
|
||||||
|
|
||||||
if(should_draw) {
|
if (should_draw) {
|
||||||
/*debugPass = editor->debug_pass;
|
/*debugPass = editor->debug_pass;
|
||||||
if(debugPass != nullptr)
|
if(debugPass != nullptr)
|
||||||
debugPass->selected_object = selected_object;*/
|
debugPass->selected_object = selected_object;*/
|
||||||
|
|
||||||
engine->set_current_scene(editor->get_scene());
|
engine->set_current_scene(editor->get_scene());
|
||||||
set_undo_stack(&editor->undo_stack);
|
set_undo_stack(&editor->undo_stack);
|
||||||
editor->draw(this);
|
editor->draw(this);
|
||||||
|
@ -303,7 +303,7 @@ void PrismEditor::drawUI() {
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
utility::erase_if(editors, [](Editor* editor) {
|
utility::erase_if(editors, [](Editor* editor) {
|
||||||
return editor->wants_to_close;
|
return editor->wants_to_close;
|
||||||
});
|
});
|
||||||
|
@ -318,8 +318,8 @@ void PrismEditor::asset_selected(const std::filesystem::path& path, AssetType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrismEditor::updateEditor(float) {
|
void PrismEditor::updateEditor(float) {
|
||||||
for(auto [path, is_relative] : open_requests)
|
for (auto [path, is_relative] : open_requests)
|
||||||
open_asset(path);
|
open_asset(path);
|
||||||
|
|
||||||
open_requests.clear();
|
open_requests.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "sceneeditor.hpp"
|
#include "sceneeditor.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ Scene* SceneEditor::get_scene() const {
|
||||||
|
|
||||||
void SceneEditor::setup_windows(ImGuiID dockspace) {
|
void SceneEditor::setup_windows(ImGuiID dockspace) {
|
||||||
ImGuiID dock_main_id = dockspace;
|
ImGuiID dock_main_id = dockspace;
|
||||||
|
|
||||||
ImGuiID dock_id_top, dock_id_bottom;
|
ImGuiID dock_id_top, dock_id_bottom;
|
||||||
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, 0.70f, &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);
|
ImGui::DockBuilderDockWindow(get_window_name("Assets").c_str(), dock_id_bottom);
|
||||||
|
|
||||||
ImGuiID dock_id_left, dock_id_right;
|
ImGuiID dock_id_left, dock_id_right;
|
||||||
ImGui::DockBuilderSplitNode(dock_id_top, ImGuiDir_Left, 0.70f, &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::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("Outliner").c_str(), dock_id_left);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Viewport").c_str(), dock_id_right);
|
ImGui::DockBuilderDockWindow(get_window_name("Viewport").c_str(), dock_id_right);
|
||||||
ImGui::DockBuilderDockWindow(get_window_name("Console").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) {
|
void SceneEditor::draw(CommonEditor* editor) {
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File")) {
|
||||||
if(ImGui::MenuItem("Save", "CTRL+S")) {
|
if (ImGui::MenuItem("Save", "CTRL+S")) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
engine->get_imgui().save_dialog([this](std::string path) {
|
engine->get_imgui().save_dialog([this](std::string path) {
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
@ -50,68 +50,68 @@ void SceneEditor::draw(CommonEditor* editor) {
|
||||||
engine->save_scene(path);
|
engine->save_scene(path);
|
||||||
});
|
});
|
||||||
} else {
|
} 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) {
|
engine->get_imgui().save_dialog([this](std::string path) {
|
||||||
this->path = path;
|
this->path = path;
|
||||||
|
|
||||||
engine->save_scene(path);
|
engine->save_scene(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::MenuItem("Close"))
|
if (ImGui::MenuItem("Close"))
|
||||||
wants_to_close = true;
|
wants_to_close = true;
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Edit")) {
|
if (ImGui::BeginMenu("Edit")) {
|
||||||
std::string previous_stack_name = "Undo";
|
std::string previous_stack_name = "Undo";
|
||||||
bool undo_available = false;
|
bool undo_available = false;
|
||||||
|
|
||||||
std::string next_stack_name = "Redo";
|
std::string next_stack_name = "Redo";
|
||||||
bool redo_available = false;
|
bool redo_available = false;
|
||||||
|
|
||||||
if (auto command = undo_stack.get_last_command()) {
|
if (auto command = undo_stack.get_last_command()) {
|
||||||
undo_available = true;
|
undo_available = true;
|
||||||
previous_stack_name += " " + command->get_name();
|
previous_stack_name += " " + command->get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto command = undo_stack.get_next_command()) {
|
if (auto command = undo_stack.get_next_command()) {
|
||||||
redo_available = true;
|
redo_available = true;
|
||||||
next_stack_name += " " + command->get_name();
|
next_stack_name += " " + command->get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem(previous_stack_name.c_str(), "CTRL+Z", false, undo_available))
|
if (ImGui::MenuItem(previous_stack_name.c_str(), "CTRL+Z", false, undo_available))
|
||||||
undo_stack.undo();
|
undo_stack.undo();
|
||||||
|
|
||||||
if (ImGui::MenuItem(next_stack_name.c_str(), "CTRL+Y", false, redo_available))
|
if (ImGui::MenuItem(next_stack_name.c_str(), "CTRL+Y", false, redo_available))
|
||||||
undo_stack.redo();
|
undo_stack.redo();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::BeginMenu("Add...")) {
|
if (ImGui::BeginMenu("Add...")) {
|
||||||
if (ImGui::MenuItem("Empty")) {
|
if (ImGui::MenuItem("Empty")) {
|
||||||
auto new_obj = engine->get_scene()->add_object();
|
auto new_obj = engine->get_scene()->add_object();
|
||||||
engine->get_scene()->get(new_obj).name = "new object";
|
engine->get_scene()->get(new_obj).name = "new object";
|
||||||
|
|
||||||
auto& command = undo_stack.new_command<AddObjectCommand>();
|
auto& command = undo_stack.new_command<AddObjectCommand>();
|
||||||
command.id = new_obj;
|
command.id = new_obj;
|
||||||
command.name = engine->get_scene()->get(new_obj).name;
|
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->get_imgui().open_dialog(false, [](std::string path) {
|
||||||
engine->add_prefab(*engine->get_scene(), path);
|
engine->add_prefab(*engine->get_scene(), path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,63 +130,62 @@ void SceneEditor::draw(CommonEditor* editor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto viewport_scene = engine->get_scene();
|
auto viewport_scene = engine->get_scene();
|
||||||
if(viewport_scene != nullptr) {
|
if (viewport_scene != nullptr) {
|
||||||
if(showSceneSettings) {
|
if (showSceneSettings) {
|
||||||
if(begin("Scene Settings", &showSceneSettings)) {
|
if (begin("Scene Settings", &showSceneSettings)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showOutliner) {
|
if (showOutliner) {
|
||||||
if(begin("Outliner", &showOutliner))
|
if (begin("Outliner", &showOutliner))
|
||||||
editor->drawOutline();
|
editor->drawOutline();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showProperties) {
|
if (showProperties) {
|
||||||
if(begin("Properties", &showProperties))
|
if (begin("Properties", &showProperties))
|
||||||
editor->drawPropertyEditor();
|
editor->drawPropertyEditor();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showViewport) {
|
if (showViewport) {
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
if(begin("Viewport", &showViewport))
|
if (begin("Viewport", &showViewport))
|
||||||
editor->drawViewport(viewport_scene);
|
editor->drawViewport(viewport_scene);
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showUndoStack) {
|
if (showUndoStack) {
|
||||||
if(begin("Undo Stack", &showUndoStack)) {
|
if (begin("Undo Stack", &showUndoStack)) {
|
||||||
for(auto [i, command] : utility::enumerate(undo_stack.command_stack)) {
|
for (auto [i, command] : utility::enumerate(undo_stack.command_stack)) {
|
||||||
std::string name = command->get_name();
|
std::string name = command->get_name();
|
||||||
if(i == undo_stack.stack_position)
|
if (i == undo_stack.stack_position)
|
||||||
name = "-> " + name;
|
name = "-> " + name;
|
||||||
|
|
||||||
ImGui::Selectable(name.c_str());
|
ImGui::Selectable(name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showAssets) {
|
if (showAssets) {
|
||||||
if(begin("Assets", &showAssets))
|
if (begin("Assets", &showAssets))
|
||||||
editor->drawAssets();
|
editor->drawAssets();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(begin("Console"))
|
if (begin("Console"))
|
||||||
editor->drawConsole();
|
editor->drawConsole();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <stb_truetype.h>
|
#include <stb_truetype.h>
|
||||||
|
|
||||||
constexpr std::array sizes_to_pack = {
|
constexpr std::array sizes_to_pack = {36.0f, 24.0f};
|
||||||
36.0f,
|
|
||||||
24.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr int num_glyphs = 95;
|
constexpr int num_glyphs = 95;
|
||||||
constexpr int texture_width = 2048, texture_height = 1150;
|
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[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if(argc != 3) {
|
if (argc != 3) {
|
||||||
std::cout << "Usage: FontCompiler [input ttf] [output fp]" << std::endl;
|
std::cout << "Usage: FontCompiler [input ttf] [output fp]" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -53,14 +50,14 @@ int main(int argc, char* argv[]) {
|
||||||
stbtt_PackSetOversampling(&pack_context, 2, 2);
|
stbtt_PackSetOversampling(&pack_context, 2, 2);
|
||||||
|
|
||||||
stbtt_pack_range ranges[sizes_to_pack.size()];
|
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};
|
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_PackFontRanges(&pack_context, font_data, 0, ranges, sizes_to_pack.size());
|
||||||
stbtt_PackEnd(&pack_context);
|
stbtt_PackEnd(&pack_context);
|
||||||
|
|
||||||
FILE* file = fopen(argv[2], "wb");
|
FILE* file = fopen(argv[2], "wb");
|
||||||
if(!file)
|
if (!file)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
fwrite(&texture_width, sizeof(int), 1, file);
|
fwrite(&texture_width, sizeof(int), 1, file);
|
||||||
|
@ -73,10 +70,10 @@ int main(int argc, char* argv[]) {
|
||||||
fwrite(&descent, sizeof(int), 1, file);
|
fwrite(&descent, sizeof(int), 1, file);
|
||||||
fwrite(&gap, 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);
|
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);
|
const float f = (ascent + descent) * stbtt_ScaleForPixelHeight(&font_info, range.font_size);
|
||||||
fwrite(&f, sizeof(float), 1, file);
|
fwrite(&f, sizeof(float), 1, file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
add_platform_executable(
|
add_platform_executable(
|
||||||
TARGET ModelCompiler
|
TARGET ModelCompiler
|
||||||
APP_CLASS ModelEditor
|
APP_CLASS ModelEditor
|
||||||
APP_INCLUDE modeleditor.hpp
|
APP_INCLUDE modeleditor.hpp
|
||||||
SRC
|
SRC
|
||||||
src/modeleditor.cpp
|
src/modeleditor.cpp
|
||||||
include/modeleditor.hpp
|
include/modeleditor.hpp
|
||||||
SKIP_DATA TRUE)
|
SKIP_DATA TRUE)
|
||||||
target_link_libraries(ModelCompiler PUBLIC
|
target_link_libraries(ModelCompiler PUBLIC
|
||||||
Core
|
Core
|
||||||
EditorCommon
|
EditorCommon
|
||||||
PRIVATE
|
PRIVATE
|
||||||
assimp)
|
assimp)
|
||||||
target_include_directories(ModelCompiler PUBLIC
|
target_include_directories(ModelCompiler PUBLIC
|
||||||
include)
|
include)
|
||||||
set_engine_properties(ModelCompiler)
|
set_engine_properties(ModelCompiler)
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
#include "commoneditor.hpp"
|
#include "commoneditor.hpp"
|
||||||
|
|
||||||
class ModelEditor : public CommonEditor {
|
class ModelEditor : public CommonEditor {
|
||||||
public:
|
public:
|
||||||
ModelEditor();
|
ModelEditor();
|
||||||
|
|
||||||
|
void drawUI() override;
|
||||||
|
|
||||||
void drawUI() override;
|
|
||||||
|
|
||||||
struct Flags {
|
struct Flags {
|
||||||
bool hide_ui = false;
|
bool hide_ui = false;
|
||||||
bool compile_static = false;
|
bool compile_static = false;
|
||||||
bool export_animations = true;
|
bool export_animations = true;
|
||||||
bool export_materials = true;
|
bool export_materials = true;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
std::string data_path, model_path;
|
std::string data_path, model_path;
|
||||||
|
|
||||||
void compile_model(std::string compiled_model_path);
|
void compile_model(std::string compiled_model_path);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
#include "modeleditor.hpp"
|
#include "modeleditor.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <imgui_stdlib.h>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <magic_enum.hpp>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <unordered_map>
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
|
@ -23,24 +23,23 @@ void app_main(prism::engine* engine) {
|
||||||
engine->debug_enabled = false;
|
engine->debug_enabled = false;
|
||||||
engine->console_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;
|
editor->flags.hide_ui = true;
|
||||||
|
|
||||||
if(!editor->flags.hide_ui) {
|
if (!editor->flags.hide_ui) {
|
||||||
platform::open_window("Model Compiler",
|
platform::open_window(
|
||||||
{editor->getDefaultX(), editor->getDefaultY(), 300, 300},
|
"Model Compiler", {editor->getDefaultX(), editor->getDefaultY(), 300, 300}, WindowFlags::None);
|
||||||
WindowFlags::None);
|
|
||||||
} else {
|
} else {
|
||||||
std::string compiled_model_path;
|
std::string compiled_model_path;
|
||||||
|
|
||||||
for(auto [i, argument] : utility::enumerate(engine->command_line_arguments)) {
|
for (auto [i, argument] : utility::enumerate(engine->command_line_arguments)) {
|
||||||
if(argument == "--model-path")
|
if (argument == "--model-path")
|
||||||
editor->model_path = engine->command_line_arguments[i + 1];
|
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];
|
compiled_model_path = engine->command_line_arguments[i + 1];
|
||||||
|
|
||||||
if(argument == "--compile-static")
|
if (argument == "--compile-static")
|
||||||
editor->flags.compile_static = true;
|
editor->flags.compile_static = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +55,9 @@ void app_main(prism::engine* engine) {
|
||||||
ModelEditor::ModelEditor() : CommonEditor("ModelEditor") {}
|
ModelEditor::ModelEditor() : CommonEditor("ModelEditor") {}
|
||||||
|
|
||||||
void traverseNode(const aiScene* scene, aiNode* node, const aiBone* bone, aiString& parent) {
|
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];
|
aiNode* child = node->mChildren[i];
|
||||||
if(child->mName == bone->mName) {
|
if (child->mName == bone->mName) {
|
||||||
parent = node->mName;
|
parent = node->mName;
|
||||||
} else {
|
} else {
|
||||||
traverseNode(scene, child, bone, parent);
|
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) {
|
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];
|
aiNode* child = node->mChildren[i];
|
||||||
if(child->mName == bone->mName) {
|
if (child->mName == bone->mName) {
|
||||||
aiVector3D scale, position;
|
aiVector3D scale, position;
|
||||||
aiQuaternion rotation;
|
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) {
|
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];
|
aiNode* child = node->mChildren[i];
|
||||||
if(child->mName == bone->mName) {
|
if (child->mName == bone->mName) {
|
||||||
aiVector3D scale, position;
|
aiVector3D scale, position;
|
||||||
aiQuaternion rotation;
|
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) {
|
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];
|
aiNode* child = node->mChildren[i];
|
||||||
if(child->mName == bone->mName) {
|
if (child->mName == bone->mName) {
|
||||||
aiVector3D scale, position;
|
aiVector3D scale, position;
|
||||||
aiQuaternion rotation;
|
aiQuaternion rotation;
|
||||||
|
|
||||||
|
@ -148,7 +147,7 @@ aiVector3D getBoneScale(const aiScene* scene, const aiBone* bone) {
|
||||||
|
|
||||||
void write_string(FILE* file, const aiString& str) {
|
void write_string(FILE* file, const aiString& str) {
|
||||||
fwrite(&str.length, sizeof(unsigned int), 1, file);
|
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);
|
fwrite(str.C_Str(), sizeof(char) * str.length, 1, file);
|
||||||
prism::log("writing string {}", str.C_Str());
|
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();
|
unsigned int len = str.length();
|
||||||
fwrite(&len, sizeof(unsigned int), 1, file);
|
fwrite(&len, sizeof(unsigned int), 1, file);
|
||||||
|
|
||||||
if(str.length() > 0) {
|
if (str.length() > 0) {
|
||||||
fwrite(str.c_str(), sizeof(char) * len, 1, file);
|
fwrite(str.c_str(), sizeof(char) * len, 1, file);
|
||||||
prism::log("writing string {}", str.c_str());
|
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;
|
unsigned int vertex_index = 0, bone_index = 0;
|
||||||
float weight = 0.0f;
|
float weight = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int max_weights_per_vertex = 4;
|
constexpr int max_weights_per_vertex = 4;
|
||||||
|
|
||||||
struct BoneVertexData {
|
struct BoneVertexData {
|
||||||
std::array<int, max_weights_per_vertex> ids;
|
std::array<int, max_weights_per_vertex> ids;
|
||||||
std::array<float, max_weights_per_vertex> weights;
|
std::array<float, max_weights_per_vertex> weights;
|
||||||
|
|
||||||
void add(int boneID, float boneWeight) {
|
void add(int boneID, float boneWeight) {
|
||||||
for (int i = 0; i < max_weights_per_vertex; i++) {
|
for (int i = 0; i < max_weights_per_vertex; i++) {
|
||||||
if (weights[i] == 0.0f) {
|
if (weights[i] == 0.0f) {
|
||||||
|
@ -186,31 +185,27 @@ void ModelEditor::compile_model(std::string compiled_model_path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
|
|
||||||
unsigned int importer_flags =
|
unsigned int importer_flags = aiProcess_Triangulate | aiProcess_ImproveCacheLocality |
|
||||||
aiProcess_Triangulate |
|
aiProcess_JoinIdenticalVertices | aiProcess_OptimizeMeshes |
|
||||||
aiProcess_ImproveCacheLocality |
|
aiProcess_CalcTangentSpace | aiProcess_GenNormals;
|
||||||
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.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 1.0);
|
||||||
|
|
||||||
importer_flags |= aiProcess_GlobalScale;
|
importer_flags |= aiProcess_GlobalScale;
|
||||||
importer_flags |= aiProcess_PreTransformVertices;
|
importer_flags |= aiProcess_PreTransformVertices;
|
||||||
|
|
||||||
aiMatrix4x4 matrix;
|
aiMatrix4x4 matrix;
|
||||||
|
|
||||||
importer.SetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, matrix);
|
importer.SetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, matrix);
|
||||||
importer.SetPropertyBool(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, true);
|
importer.SetPropertyBool(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiScene* sc = importer.ReadFile(model_path.c_str(), importer_flags);
|
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());
|
auto name = model_path.substr(model_path.find_last_of("/") + 1, model_path.length());
|
||||||
name = name.substr(0, name.find_last_of("."));
|
name = name.substr(0, name.find_last_of("."));
|
||||||
|
|
||||||
|
@ -220,183 +215,183 @@ void ModelEditor::compile_model(std::string compiled_model_path) {
|
||||||
|
|
||||||
int version = 7;
|
int version = 7;
|
||||||
fwrite(&version, sizeof(int), 1, file);
|
fwrite(&version, sizeof(int), 1, file);
|
||||||
|
|
||||||
std::vector<std::string> meshToMaterial;
|
std::vector<std::string> meshToMaterial;
|
||||||
meshToMaterial.resize(sc->mNumMeshes);
|
meshToMaterial.resize(sc->mNumMeshes);
|
||||||
|
|
||||||
std::map<std::string, int> matNameToIndex;
|
std::map<std::string, int> matNameToIndex;
|
||||||
int last_material = 0;
|
int last_material = 0;
|
||||||
|
|
||||||
std::vector<aiVector3D> positions;
|
std::vector<aiVector3D> positions;
|
||||||
|
|
||||||
enum MeshType : int {
|
enum MeshType : int {
|
||||||
Static,
|
Static,
|
||||||
Skinned
|
Skinned
|
||||||
} mesh_type = MeshType::Static;
|
} mesh_type = MeshType::Static;
|
||||||
|
|
||||||
std::vector<aiVector3D> normals;
|
std::vector<aiVector3D> normals;
|
||||||
std::vector<aiVector2D> texture_coords;
|
std::vector<aiVector2D> texture_coords;
|
||||||
std::vector<aiVector3D> tangents, bitangents;
|
std::vector<aiVector3D> tangents, bitangents;
|
||||||
|
|
||||||
std::vector<BoneVertexData> bone_vertex_data;
|
std::vector<BoneVertexData> 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];
|
aiMesh* mesh = sc->mMeshes[i];
|
||||||
|
|
||||||
if(mesh->HasBones())
|
if (mesh->HasBones())
|
||||||
mesh_type = MeshType::Skinned;
|
mesh_type = MeshType::Skinned;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> indices;
|
std::vector<uint32_t> indices;
|
||||||
|
|
||||||
std::vector<BoneWeight> bone_weights;
|
std::vector<BoneWeight> bone_weights;
|
||||||
|
|
||||||
aiMesh* armature_mesh = nullptr;
|
aiMesh* armature_mesh = nullptr;
|
||||||
|
|
||||||
int vertex_offset = 0;
|
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];
|
aiMesh* mesh = sc->mMeshes[i];
|
||||||
|
|
||||||
if(armature_mesh == nullptr && mesh->mNumBones != 0) {
|
if (armature_mesh == nullptr && mesh->mNumBones != 0) {
|
||||||
armature_mesh = mesh;
|
armature_mesh = mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int v = 0; v < mesh->mNumVertices; v++) {
|
for (unsigned int v = 0; v < mesh->mNumVertices; v++) {
|
||||||
positions.push_back(mesh->mVertices[v]);
|
positions.push_back(mesh->mVertices[v]);
|
||||||
normals.push_back(mesh->mNormals[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);
|
texture_coords.emplace_back(mesh->mTextureCoords[0][v].x, mesh->mTextureCoords[0][v].y);
|
||||||
} else {
|
} else {
|
||||||
texture_coords.emplace_back(0, 0);
|
texture_coords.emplace_back(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tangents.push_back(mesh->mTangents[v]);
|
tangents.push_back(mesh->mTangents[v]);
|
||||||
bitangents.push_back(mesh->mBitangents[v]);
|
bitangents.push_back(mesh->mBitangents[v]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int e = 0; e < mesh->mNumFaces; e++) {
|
for (unsigned int e = 0; e < mesh->mNumFaces; e++) {
|
||||||
const aiFace& face = mesh->mFaces[e];
|
const aiFace& face = mesh->mFaces[e];
|
||||||
|
|
||||||
indices.push_back(face.mIndices[0]);
|
indices.push_back(face.mIndices[0]);
|
||||||
indices.push_back(face.mIndices[1]);
|
indices.push_back(face.mIndices[1]);
|
||||||
indices.push_back(face.mIndices[2]);
|
indices.push_back(face.mIndices[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int b = 0; b < mesh->mNumBones; b++) {
|
for (unsigned int b = 0; b < mesh->mNumBones; b++) {
|
||||||
for(int y = 0; y < mesh->mBones[b]->mNumWeights; y++) {
|
for (int y = 0; y < mesh->mBones[b]->mNumWeights; y++) {
|
||||||
BoneWeight bw;
|
BoneWeight bw;
|
||||||
bw.bone_index = b;
|
bw.bone_index = b;
|
||||||
bw.vertex_index = vertex_offset + mesh->mBones[b]->mWeights[y].mVertexId;
|
bw.vertex_index = vertex_offset + mesh->mBones[b]->mWeights[y].mVertexId;
|
||||||
bw.weight = mesh->mBones[b]->mWeights[y].mWeight;
|
bw.weight = mesh->mBones[b]->mWeights[y].mWeight;
|
||||||
|
|
||||||
bone_weights.push_back(bw);
|
bone_weights.push_back(bw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string material = sc->mMaterials[mesh->mMaterialIndex]->GetName().C_Str();
|
std::string material = sc->mMaterials[mesh->mMaterialIndex]->GetName().C_Str();
|
||||||
meshToMaterial[i] = material;
|
meshToMaterial[i] = material;
|
||||||
|
|
||||||
if(!matNameToIndex.count(material))
|
if (!matNameToIndex.count(material))
|
||||||
matNameToIndex[material] = last_material++;
|
matNameToIndex[material] = last_material++;
|
||||||
|
|
||||||
vertex_offset += mesh->mNumVertices;
|
vertex_offset += mesh->mNumVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mesh_type == MeshType::Skinned) {
|
if (mesh_type == MeshType::Skinned) {
|
||||||
bone_vertex_data.resize(positions.size());
|
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);
|
bone_vertex_data[bw.vertex_index].add(bw.bone_index, bw.weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(&mesh_type, sizeof(int), 1, file);
|
fwrite(&mesh_type, sizeof(int), 1, file);
|
||||||
|
|
||||||
int vert_len = positions.size();
|
int vert_len = positions.size();
|
||||||
fwrite(&vert_len, sizeof(int), 1, file);
|
fwrite(&vert_len, sizeof(int), 1, file);
|
||||||
|
|
||||||
const auto write_buffer = [numVertices = positions.size(), file](auto vec, unsigned int size) {
|
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);
|
fwrite(&vec[i], size, 1, file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
write_buffer(positions, sizeof(prism::float3));
|
write_buffer(positions, sizeof(prism::float3));
|
||||||
write_buffer(normals, sizeof(prism::float3));
|
write_buffer(normals, sizeof(prism::float3));
|
||||||
write_buffer(texture_coords, sizeof(prism::float2));
|
write_buffer(texture_coords, sizeof(prism::float2));
|
||||||
write_buffer(tangents, sizeof(prism::float3));
|
write_buffer(tangents, sizeof(prism::float3));
|
||||||
write_buffer(bitangents, 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));
|
write_buffer(bone_vertex_data, sizeof(BoneVertexData));
|
||||||
|
|
||||||
int element_len = indices.size();
|
int element_len = indices.size();
|
||||||
fwrite(&element_len, sizeof(int), 1, file);
|
fwrite(&element_len, sizeof(int), 1, file);
|
||||||
|
|
||||||
fwrite(indices.data(), sizeof(uint32_t) * indices.size(), 1, file);
|
fwrite(indices.data(), sizeof(uint32_t) * indices.size(), 1, file);
|
||||||
|
|
||||||
int bone_len = 0;
|
int bone_len = 0;
|
||||||
if(armature_mesh != nullptr) {
|
if (armature_mesh != nullptr) {
|
||||||
bone_len = armature_mesh->mNumBones;
|
bone_len = armature_mesh->mNumBones;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(&bone_len, sizeof(int), 1, file);
|
fwrite(&bone_len, sizeof(int), 1, file);
|
||||||
|
|
||||||
if(bone_len > 0) {
|
if (bone_len > 0) {
|
||||||
auto transform = sc->mRootNode->mTransformation;
|
auto transform = sc->mRootNode->mTransformation;
|
||||||
transform.Inverse();
|
transform.Inverse();
|
||||||
transform.Transpose();
|
transform.Transpose();
|
||||||
|
|
||||||
fwrite(&transform, sizeof(aiMatrix4x4), 1, file);
|
fwrite(&transform, sizeof(aiMatrix4x4), 1, file);
|
||||||
|
|
||||||
for (unsigned int b = 0; b < armature_mesh->mNumBones; b++) {
|
for (unsigned int b = 0; b < armature_mesh->mNumBones; b++) {
|
||||||
const aiBone* aBone = armature_mesh->mBones[b];
|
const aiBone* aBone = armature_mesh->mBones[b];
|
||||||
|
|
||||||
write_string(file, aBone->mName);
|
write_string(file, aBone->mName);
|
||||||
write_string(file, findBoneParent(sc, aBone));
|
write_string(file, findBoneParent(sc, aBone));
|
||||||
|
|
||||||
auto pos = getBonePosition(sc, aBone);
|
auto pos = getBonePosition(sc, aBone);
|
||||||
|
|
||||||
fwrite(&pos, sizeof(float) * 3, 1, file);
|
fwrite(&pos, sizeof(float) * 3, 1, file);
|
||||||
|
|
||||||
auto rot = getBoneRotation(sc, aBone);
|
auto rot = getBoneRotation(sc, aBone);
|
||||||
|
|
||||||
fwrite(&rot, sizeof(float) * 4, 1, file);
|
fwrite(&rot, sizeof(float) * 4, 1, file);
|
||||||
|
|
||||||
auto scl = getBoneScale(sc, aBone);
|
auto scl = getBoneScale(sc, aBone);
|
||||||
|
|
||||||
fwrite(&scl, sizeof(float) * 3, 1, file);
|
fwrite(&scl, sizeof(float) * 3, 1, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(&sc->mNumMeshes, sizeof(int), 1, file);
|
fwrite(&sc->mNumMeshes, sizeof(int), 1, file);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sc->mNumMeshes; i++) {
|
for (unsigned int i = 0; i < sc->mNumMeshes; i++) {
|
||||||
const aiMesh* mesh = sc->mMeshes[i];
|
const aiMesh* mesh = sc->mMeshes[i];
|
||||||
|
|
||||||
write_string(file, mesh->mName);
|
write_string(file, mesh->mName);
|
||||||
|
|
||||||
float min_x = 0.0f, min_y = 0.0f, min_z = 0.0f;
|
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;
|
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];
|
auto vertex_pos = mesh->mVertices[i];
|
||||||
|
|
||||||
if(vertex_pos.x < min_x)
|
if (vertex_pos.x < min_x)
|
||||||
min_x = vertex_pos.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;
|
max_x = vertex_pos.x;
|
||||||
|
|
||||||
if(vertex_pos.y < min_y)
|
if (vertex_pos.y < min_y)
|
||||||
min_y = vertex_pos.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;
|
max_y = vertex_pos.y;
|
||||||
|
|
||||||
if(vertex_pos.z < min_z)
|
if (vertex_pos.z < min_z)
|
||||||
min_z = vertex_pos.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;
|
max_z = vertex_pos.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
prism::aabb aabb;
|
prism::aabb aabb;
|
||||||
aabb.min = prism::float3(min_x, min_y, min_z);
|
aabb.min = prism::float3(min_x, min_y, min_z);
|
||||||
aabb.max = prism::float3(max_x, max_y, max_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;
|
unsigned int numIndices = mesh->mNumFaces * 3;
|
||||||
fwrite(&numIndices, sizeof(int), 1, file);
|
fwrite(&numIndices, sizeof(int), 1, file);
|
||||||
|
|
||||||
int numOffsetMatrices = mesh->mNumBones;
|
int numOffsetMatrices = mesh->mNumBones;
|
||||||
fwrite(&numOffsetMatrices, sizeof(int), 1, file);
|
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;
|
auto offset = mesh->mBones[b]->mOffsetMatrix;
|
||||||
offset.Transpose();
|
offset.Transpose();
|
||||||
|
|
||||||
fwrite(&offset, sizeof(aiMatrix4x4), 1, file);
|
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");
|
fmt::print("Finished writing model!\n");
|
||||||
|
|
||||||
if(flags.export_materials) {
|
if (flags.export_materials) {
|
||||||
for(int i = 0; i < sc->mNumMaterials; i++) {
|
for (int i = 0; i < sc->mNumMaterials; i++) {
|
||||||
auto path = data_path + "/materials/" + sc->mMaterials[i]->GetName().C_Str() + ".material";
|
auto path = data_path + "/materials/" + sc->mMaterials[i]->GetName().C_Str() + ".material";
|
||||||
|
|
||||||
Material mat;
|
Material mat;
|
||||||
|
|
||||||
aiColor4D color;
|
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.type = DataType::Vector3;
|
||||||
mat.colorProperty.value = prism::float3(color.r, color.g, color.b);
|
mat.colorProperty.value = prism::float3(color.r, color.g, color.b);
|
||||||
|
|
||||||
aiString diffuse_path;
|
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.type = DataType::AssetTexture;
|
||||||
mat.colorProperty.value_tex.handle = new Texture();
|
mat.colorProperty.value_tex.handle = new Texture();
|
||||||
mat.colorProperty.value_tex->path = std::string("textures/") + diffuse_path.C_Str();
|
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;
|
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.type = DataType::AssetTexture;
|
||||||
mat.normalProperty.value_tex.handle = new Texture();
|
mat.normalProperty.value_tex.handle = new Texture();
|
||||||
mat.normalProperty.value_tex->path = std::string("textures/") + normal_path.C_Str();
|
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) {
|
if (flags.export_animations) {
|
||||||
for(auto i = 0; i < sc->mNumAnimations; i++) {
|
for (auto i = 0; i < sc->mNumAnimations; i++) {
|
||||||
const aiAnimation* animation = sc->mAnimations[i];
|
const aiAnimation* animation = sc->mAnimations[i];
|
||||||
std::string animName = animation->mName.C_Str();
|
std::string animName = animation->mName.C_Str();
|
||||||
|
|
||||||
if(animName.length() == 0)
|
if (animName.length() == 0)
|
||||||
animName = "default";
|
animName = "default";
|
||||||
|
|
||||||
std::string finalName = (name + animName + ".anim");
|
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);
|
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];
|
const aiNodeAnim* channel = animation->mChannels[j];
|
||||||
|
|
||||||
write_string(file, channel->mNodeName);
|
write_string(file, channel->mNodeName);
|
||||||
|
|
||||||
fwrite(&channel->mNumPositionKeys, sizeof(unsigned int), 1, file);
|
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;
|
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;
|
key.time = channel->mPositionKeys[k].mTime;
|
||||||
|
|
||||||
fwrite(&key, sizeof(PositionKeyFrame), 1, file);
|
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);
|
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;
|
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;
|
key.time = channel->mRotationKeys[k].mTime;
|
||||||
|
|
||||||
fwrite(&key, sizeof(RotationKeyFrame), 1, file);
|
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);
|
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;
|
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;
|
key.time = channel->mScalingKeys[k].mTime;
|
||||||
|
|
||||||
fwrite(&key, sizeof(ScaleKeyFrame), 1, file);
|
fwrite(&key, sizeof(ScaleKeyFrame), 1, file);
|
||||||
|
@ -523,31 +528,35 @@ void ModelEditor::drawUI() {
|
||||||
|
|
||||||
auto viewport = ImGui::GetMainViewport();
|
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::SetWindowPos(viewport->Pos, ImGuiCond_Always);
|
||||||
ImGui::SetWindowSize(viewport->Size, 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) {
|
engine->get_imgui().open_dialog(true, [this](std::string path) {
|
||||||
model_path = path;
|
model_path = path;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::Button("Open data path...")) {
|
if (ImGui::Button("Open data path...")) {
|
||||||
engine->get_imgui().open_dialog(true, [this](std::string path) {
|
engine->get_imgui().open_dialog(
|
||||||
data_path = path;
|
true,
|
||||||
}, true);
|
[this](std::string path) {
|
||||||
|
data_path = path;
|
||||||
|
},
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Checkbox("Compile as static (remove transforms)", &flags.compile_static);
|
ImGui::Checkbox("Compile as static (remove transforms)", &flags.compile_static);
|
||||||
ImGui::Checkbox("Export materials", &flags.export_materials);
|
ImGui::Checkbox("Export materials", &flags.export_materials);
|
||||||
ImGui::Checkbox("Export animations", &flags.export_animations);
|
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());
|
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());
|
auto name = model_path.substr(model_path.find_last_of("/") + 1, model_path.length());
|
||||||
name = name.substr(0, name.find_last_of("."));
|
name = name.substr(0, name.find_last_of("."));
|
||||||
compile_model(data_path + "/models/" + name + ".model");
|
compile_model(data_path + "/models/" + name + ".model");
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
add_executable(ShaderCompilerTool main.cpp)
|
add_executable(ShaderCompilerTool main.cpp)
|
||||||
target_link_libraries(ShaderCompilerTool
|
target_link_libraries(ShaderCompilerTool
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ShaderCompiler
|
ShaderCompiler
|
||||||
Log
|
Log
|
||||||
Utility)
|
Utility)
|
||||||
set_engine_properties(ShaderCompilerTool)
|
set_engine_properties(ShaderCompilerTool)
|
||||||
set_output_dir(ShaderCompilerTool)
|
set_output_dir(ShaderCompilerTool)
|
||||||
|
|
|
@ -36,10 +36,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
|
|
||||||
|
@ -48,19 +48,15 @@
|
||||||
// Can be overridden to customize.
|
// Can be overridden to customize.
|
||||||
class DirStackFileIncluder : public glslang::TShader::Includer {
|
class DirStackFileIncluder : public glslang::TShader::Includer {
|
||||||
public:
|
public:
|
||||||
DirStackFileIncluder() : externalLocalDirectoryCount(0) { }
|
DirStackFileIncluder() : externalLocalDirectoryCount(0) {}
|
||||||
|
|
||||||
virtual IncludeResult* includeLocal(const char* headerName,
|
virtual IncludeResult*
|
||||||
const char* includerName,
|
includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override {
|
||||||
size_t inclusionDepth) override
|
|
||||||
{
|
|
||||||
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual IncludeResult* includeSystem(const char* headerName,
|
virtual IncludeResult*
|
||||||
const char* /*includerName*/,
|
includeSystem(const char* headerName, const char* /*includerName*/, size_t /*inclusionDepth*/) override {
|
||||||
size_t /*inclusionDepth*/) override
|
|
||||||
{
|
|
||||||
return readSystemPath(headerName);
|
return readSystemPath(headerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,21 +66,19 @@ public:
|
||||||
// is checked.
|
// is checked.
|
||||||
// - This only applies to the "local" form of #include.
|
// - This only applies to the "local" form of #include.
|
||||||
// - Makes its own copy of the path.
|
// - 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);
|
directoryStack.push_back(dir);
|
||||||
externalLocalDirectoryCount = (int)directoryStack.size();
|
externalLocalDirectoryCount = (int)directoryStack.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void releaseInclude(IncludeResult* result) override
|
virtual void releaseInclude(IncludeResult* result) override {
|
||||||
{
|
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
delete [] static_cast<tUserDataElement*>(result->userData);
|
delete[] static_cast<tUserDataElement*>(result->userData);
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~DirStackFileIncluder() override { }
|
virtual ~DirStackFileIncluder() override {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef char tUserDataElement;
|
typedef char tUserDataElement;
|
||||||
|
@ -93,8 +87,7 @@ protected:
|
||||||
|
|
||||||
// Search for a valid "local" path based on combining the stack of include
|
// Search for a valid "local" path based on combining the stack of include
|
||||||
// directories and the nominal name of the header.
|
// 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
|
// Discard popped include directories, and
|
||||||
// initialize when at parse-time first level.
|
// initialize when at parse-time first level.
|
||||||
directoryStack.resize(depth + externalLocalDirectoryCount);
|
directoryStack.resize(depth + externalLocalDirectoryCount);
|
||||||
|
@ -117,15 +110,13 @@ protected:
|
||||||
|
|
||||||
// Search for a valid <system> path.
|
// Search for a valid <system> path.
|
||||||
// Not implemented yet; returning nullptr signals failure to find.
|
// 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do actual reading of the file, filling in a new include result.
|
// 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
|
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const {
|
||||||
{
|
char* content = new tUserDataElement[length];
|
||||||
char* content = new tUserDataElement [length];
|
|
||||||
file.seekg(0, file.beg);
|
file.seekg(0, file.beg);
|
||||||
file.read(content, length);
|
file.read(content, length);
|
||||||
return new IncludeResult(path, content, length, content);
|
return new IncludeResult(path, content, length, content);
|
||||||
|
@ -133,8 +124,7 @@ protected:
|
||||||
|
|
||||||
// If no path markers, return current working directory.
|
// If no path markers, return current working directory.
|
||||||
// Otherwise, strip file name and return path leading up to it.
|
// 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("/\\");
|
size_t last = path.find_last_of("/\\");
|
||||||
return last == std::string::npos ? "." : path.substr(0, last);
|
return last == std::string::npos ? "." : path.substr(0, last);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <sstream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "shadercompiler.hpp"
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
#include "shadercompiler.hpp"
|
||||||
#include "string_utils.hpp"
|
#include "string_utils.hpp"
|
||||||
|
|
||||||
bool has_extension(const std::filesystem::path& path, const std::string_view extension) {
|
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[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if(argc < 2) {
|
if (argc < 2) {
|
||||||
prism::log("Not enough arguments!");
|
prism::log("Not enough arguments!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_compiler.set_include_path(std::filesystem::current_path().string());
|
shader_compiler.set_include_path(std::filesystem::current_path().string());
|
||||||
|
|
||||||
std::filesystem::path source_path = argv[1];
|
std::filesystem::path source_path = argv[1];
|
||||||
|
@ -22,75 +22,70 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
ShaderLanguage language = ShaderLanguage::SPIRV;
|
ShaderLanguage language = ShaderLanguage::SPIRV;
|
||||||
std::string_view shader_language_string = argv[3];
|
std::string_view shader_language_string = argv[3];
|
||||||
if(shader_language_string == "spv") {
|
if (shader_language_string == "spv") {
|
||||||
language = ShaderLanguage::SPIRV;
|
language = ShaderLanguage::SPIRV;
|
||||||
} else if(shader_language_string == "msl") {
|
} else if (shader_language_string == "msl") {
|
||||||
language = ShaderLanguage::MSL;
|
language = ShaderLanguage::MSL;
|
||||||
} else if(shader_language_string == "glsl") {
|
} else if (shader_language_string == "glsl") {
|
||||||
language = ShaderLanguage::GLSL;
|
language = ShaderLanguage::GLSL;
|
||||||
} else if(shader_language_string == "hlsl") {
|
} else if (shader_language_string == "hlsl") {
|
||||||
language = ShaderLanguage::HLSL;
|
language = ShaderLanguage::HLSL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileOptions options;
|
CompileOptions options;
|
||||||
|
|
||||||
std::string_view extra_options = argc > 4 ? argv[4] : "";
|
std::string_view extra_options = argc > 4 ? argv[4] : "";
|
||||||
if(extra_options == "mobile")
|
if (extra_options == "mobile")
|
||||||
options.is_apple_mobile = true;
|
options.is_apple_mobile = true;
|
||||||
|
|
||||||
std::ifstream t(source_path);
|
std::ifstream t(source_path);
|
||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
buffer << t.rdbuf();
|
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
|
destination_path = remove_substring(destination_path.string(), ".nocompile"); // remove extension
|
||||||
|
|
||||||
std::ofstream out(destination_path);
|
std::ofstream out(destination_path);
|
||||||
out << buffer.rdbuf();
|
out << buffer.rdbuf();
|
||||||
} else {
|
} else {
|
||||||
ShaderStage stage = ShaderStage::Vertex;
|
ShaderStage stage = ShaderStage::Vertex;
|
||||||
if(has_extension(source_path, ".vert"))
|
if (has_extension(source_path, ".vert"))
|
||||||
stage = ShaderStage::Vertex;
|
stage = ShaderStage::Vertex;
|
||||||
else if(has_extension(source_path, ".frag"))
|
else if (has_extension(source_path, ".frag"))
|
||||||
stage = ShaderStage::Fragment;
|
stage = ShaderStage::Fragment;
|
||||||
else if(has_extension(source_path, ".comp"))
|
else if (has_extension(source_path, ".comp"))
|
||||||
stage = ShaderStage::Compute;
|
stage = ShaderStage::Compute;
|
||||||
|
|
||||||
const auto compiled_source = shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(buffer.str()), language, options);
|
const auto compiled_source =
|
||||||
if(!compiled_source.has_value()) {
|
shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(buffer.str()), language, options);
|
||||||
|
if (!compiled_source.has_value()) {
|
||||||
prism::log("Error when compiling {}!", source_path.string());
|
prism::log("Error when compiling {}!", source_path.string());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(language) {
|
switch (language) {
|
||||||
// right now, WGSL is outputted as SPIR-V with some WGSL compatibility stuff included
|
// 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();
|
const auto spirv = compiled_source->as_bytecode();
|
||||||
|
|
||||||
std::ofstream out(destination_path, std::ios::binary); // remove .glsl
|
std::ofstream out(destination_path, std::ios::binary); // remove .glsl
|
||||||
out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t));
|
out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t));
|
||||||
}
|
} break;
|
||||||
break;
|
case ShaderLanguage::MSL: {
|
||||||
case ShaderLanguage::MSL:
|
|
||||||
{
|
|
||||||
std::ofstream out(destination_path); // remove .glsl
|
std::ofstream out(destination_path); // remove .glsl
|
||||||
out << compiled_source->as_string();
|
out << compiled_source->as_string();
|
||||||
}
|
} break;
|
||||||
break;
|
case ShaderLanguage::HLSL: {
|
||||||
case ShaderLanguage::HLSL:
|
|
||||||
{
|
|
||||||
std::ofstream out(destination_path); // remove .glsl
|
std::ofstream out(destination_path); // remove .glsl
|
||||||
out << compiled_source->as_string();
|
out << compiled_source->as_string();
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: output disabled for now, will have to expose in a better arg system
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue