Reformat core module
This commit is contained in:
parent
924d60e99b
commit
100e1d7434
20 changed files with 702 additions and 662 deletions
|
@ -21,9 +21,9 @@ set(SRC
|
||||||
src/debug.cpp
|
src/debug.cpp
|
||||||
src/console.cpp)
|
src/console.cpp)
|
||||||
|
|
||||||
if(NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
if (NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
||||||
set(EXTRA_LIBRARIES Audio)
|
set(EXTRA_LIBRARIES Audio)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
add_library(Core STATIC ${SRC})
|
add_library(Core STATIC ${SRC})
|
||||||
target_include_directories(Core PUBLIC
|
target_include_directories(Core PUBLIC
|
||||||
|
|
|
@ -29,10 +29,15 @@ namespace prism {
|
||||||
|
|
||||||
virtual void render([[maybe_unused]] GFXCommandBuffer* command_buffer) {}
|
virtual void render([[maybe_unused]] GFXCommandBuffer* command_buffer) {}
|
||||||
|
|
||||||
virtual bool wants_no_scene_rendering() { return false; }
|
virtual bool wants_no_scene_rendering() {
|
||||||
virtual bool is_multimodal() { return false; }
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool is_multimodal() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace prism
|
||||||
|
|
||||||
/// This is an app's equivalent of main(). You can check command line arguments through Engine::command_line_arguments.
|
/// This is an app's equivalent of main(). You can check command line arguments through Engine::command_line_arguments.
|
||||||
void app_main(prism::engine* engine);
|
void app_main(prism::engine* engine);
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "assetptr.hpp"
|
#include "assetptr.hpp"
|
||||||
|
#include "matrix.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "quaternion.hpp"
|
#include "quaternion.hpp"
|
||||||
#include "matrix.hpp"
|
|
||||||
|
|
||||||
class btCollisionShape;
|
class btCollisionShape;
|
||||||
class btRigidBody;
|
class btRigidBody;
|
||||||
|
@ -63,11 +63,7 @@ struct Transform {
|
||||||
Matrix4x4 model;
|
Matrix4x4 model;
|
||||||
|
|
||||||
[[nodiscard]] prism::float3 get_world_position() const {
|
[[nodiscard]] prism::float3 get_world_position() const {
|
||||||
return {
|
return {model[3][0], model[3][1], model[3][2]};
|
||||||
model[3][0],
|
|
||||||
model[3][1],
|
|
||||||
model[3][2]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +75,7 @@ struct Renderable {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Light {
|
struct Light {
|
||||||
enum class Type : int{
|
enum class Type : int {
|
||||||
Point = 0,
|
Point = 0,
|
||||||
Spot = 1,
|
Spot = 1,
|
||||||
Sun = 2
|
Sun = 2
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
|
||||||
#include <variant>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "path.hpp"
|
#include "path.hpp"
|
||||||
|
|
||||||
|
@ -59,15 +59,14 @@ namespace prism::console {
|
||||||
|
|
||||||
void load_cfg(const prism::path& path);
|
void load_cfg(const prism::path& path);
|
||||||
|
|
||||||
void
|
void register_command(std::string_view name, argument_format expected_format, function_ptr function);
|
||||||
register_command(std::string_view name, argument_format expected_format, function_ptr function);
|
|
||||||
|
|
||||||
void invoke_command(std::string_view name, arguments arguments);
|
void invoke_command(std::string_view name, arguments arguments);
|
||||||
|
|
||||||
void parse_and_invoke_command(std::string_view command);
|
void parse_and_invoke_command(std::string_view command);
|
||||||
|
|
||||||
void register_variable(std::string_view name, bool &variable);
|
void register_variable(std::string_view name, bool& variable);
|
||||||
void register_variable(std::string_view name, float& variable);
|
void register_variable(std::string_view name, float& variable);
|
||||||
void register_variable(std::string_view name, int& variable);
|
void register_variable(std::string_view name, int& variable);
|
||||||
void register_variable(std::string_view name, double& variable);
|
void register_variable(std::string_view name, double& variable);
|
||||||
}
|
} // namespace prism::console
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "vector.hpp"
|
|
||||||
#include "quaternion.hpp"
|
|
||||||
#include "math.hpp"
|
#include "math.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
#include "quaternion.hpp"
|
||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
struct PositionKeyFrame {
|
struct PositionKeyFrame {
|
||||||
float time;
|
float time;
|
||||||
|
@ -70,10 +70,9 @@ public:
|
||||||
|
|
||||||
int get_real_end() {
|
int get_real_end() {
|
||||||
int end = -1;
|
int end = -1;
|
||||||
for(auto& shot : shots) {
|
for (auto& shot : shots) {
|
||||||
if((shot.begin + shot.length) >= end)
|
if ((shot.begin + shot.length) >= end)
|
||||||
end = shot.begin + shot.length;
|
end = shot.begin + shot.length;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
#include "object.hpp"
|
|
||||||
#include "cutscene.hpp"
|
|
||||||
#include "common.hpp"
|
|
||||||
#include "asset_types.hpp"
|
#include "asset_types.hpp"
|
||||||
#include "platform.hpp"
|
#include "common.hpp"
|
||||||
|
#include "cutscene.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
#include "path.hpp"
|
#include "path.hpp"
|
||||||
|
#include "platform.hpp"
|
||||||
|
|
||||||
class GFX;
|
class GFX;
|
||||||
class Scene;
|
class Scene;
|
||||||
|
@ -87,10 +87,12 @@ namespace prism {
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool is_paused() const;
|
[[nodiscard]] bool is_paused() const;
|
||||||
|
|
||||||
/// Request to begin quitting immediately. This is not forced, and can be canceled by the user, platform, or app.
|
/// Request to begin quitting immediately. This is not forced, and can be canceled by the user, platform, or
|
||||||
|
/// app.
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
/// Call right before the platform is about to quit the application, and requests the app or other systems to save work.
|
/// Call right before the platform is about to quit the application, and requests the app or other systems to
|
||||||
|
/// save work.
|
||||||
void prepare_quit();
|
void prepare_quit();
|
||||||
|
|
||||||
/// Query whether or not the engine is in the process of quitting.
|
/// Query whether or not the engine is in the process of quitting.
|
||||||
|
@ -203,21 +205,24 @@ namespace prism {
|
||||||
/** Called when a key has been pressed.
|
/** Called when a key has been pressed.
|
||||||
@param keyCode A platform-specific key code.
|
@param keyCode A platform-specific key code.
|
||||||
@note Use platform::get_keycode to get a InputButton equivalent if needed.
|
@note Use platform::get_keycode to get a InputButton equivalent if needed.
|
||||||
@note This function is only intended for debug purposes and all production code should be using the Input system instead.
|
@note This function is only intended for debug purposes and all production code should be using the Input
|
||||||
|
system instead.
|
||||||
*/
|
*/
|
||||||
void process_key_down(unsigned int keyCode);
|
void process_key_down(unsigned int keyCode);
|
||||||
|
|
||||||
/** Called when a key has been released.
|
/** Called when a key has been released.
|
||||||
@param keyCode A platform-specific key code.
|
@param keyCode A platform-specific key code.
|
||||||
@note Use platform::get_keycode to get a InputButton equivalent if needed.
|
@note Use platform::get_keycode to get a InputButton equivalent if needed.
|
||||||
@note This function is only intended for debug purposes and all production code should be using the Input system instead.
|
@note This function is only intended for debug purposes and all production code should be using the Input
|
||||||
|
system instead.
|
||||||
*/
|
*/
|
||||||
void process_key_up(unsigned int keyCode);
|
void process_key_up(unsigned int keyCode);
|
||||||
|
|
||||||
/** Called when a mouse button has been clicked..
|
/** Called when a mouse button has been clicked..
|
||||||
@param button The mouse button.
|
@param button The mouse button.
|
||||||
@param offset The mouse position relative to the window where the click occured.
|
@param offset The mouse position relative to the window where the click occured.
|
||||||
@note This function is only intended for debug purposes and all production code should be using the Input system instead.
|
@note This function is only intended for debug purposes and all production code should be using the Input
|
||||||
|
system instead.
|
||||||
*/
|
*/
|
||||||
void process_mouse_down(int button, prism::Offset offset);
|
void process_mouse_down(int button, prism::Offset offset);
|
||||||
|
|
||||||
|
@ -229,7 +234,8 @@ namespace prism {
|
||||||
|
|
||||||
/** Adds a timer to the list of timers.
|
/** Adds a timer to the list of timers.
|
||||||
@param timer The timer to add.
|
@param timer The timer to add.
|
||||||
@note The timer instance is passed by reference. Use this to keep track of your timers without having to query it's state back.
|
@note The timer instance is passed by reference. Use this to keep track of your timers without having to query
|
||||||
|
it's state back.
|
||||||
*/
|
*/
|
||||||
void add_timer(Timer& timer);
|
void add_timer(Timer& timer);
|
||||||
|
|
||||||
|
@ -250,7 +256,8 @@ namespace prism {
|
||||||
void set_current_scene(Scene* scene);
|
void set_current_scene(Scene* scene);
|
||||||
|
|
||||||
/** Get the current scene's path.
|
/** Get the current scene's path.
|
||||||
@return If a scene is loaded, the path to the scene. Can be an empty string if there is no scene loaded, or if it's an empty scene.
|
@return If a scene is loaded, the path to the scene. Can be an empty string if there is no scene loaded, or if
|
||||||
|
it's an empty scene.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::string_view get_scene_path() const;
|
[[nodiscard]] std::string_view get_scene_path() const;
|
||||||
|
|
||||||
|
@ -281,7 +288,8 @@ namespace prism {
|
||||||
|
|
||||||
/** Sets the animation speed of an object.
|
/** Sets the animation speed of an object.
|
||||||
@param target The object you want to change the animation speed of.
|
@param target The object you want to change the animation speed of.
|
||||||
@param modifier The speed to play the object's animations at. A modifier of 2.0 would be 2x the speed, and 0.5 would be 1/2x the speed.
|
@param modifier The speed to play the object's animations at. A modifier of 2.0 would be 2x the speed, and 0.5
|
||||||
|
would be 1/2x the speed.
|
||||||
*/
|
*/
|
||||||
void set_animation_speed_modifier(Object target, float modifier);
|
void set_animation_speed_modifier(Object target, float modifier);
|
||||||
|
|
||||||
|
@ -290,7 +298,8 @@ namespace prism {
|
||||||
*/
|
*/
|
||||||
void stop_animation(Object target);
|
void stop_animation(Object target);
|
||||||
|
|
||||||
/// If there is a render context available. If this is false, avoid doing any GFX or Renderer work as it could crash or cause undefined behavior.
|
/// If there is a render context available. If this is false, avoid doing any GFX or Renderer work as it could
|
||||||
|
/// crash or cause undefined behavior.
|
||||||
bool render_ready = false;
|
bool render_ready = false;
|
||||||
|
|
||||||
/// If physics should upate. This is a control indepentent of the pause state.
|
/// If physics should upate. This is a control indepentent of the pause state.
|
||||||
|
@ -328,8 +337,8 @@ namespace prism {
|
||||||
std::vector<Window*> windows;
|
std::vector<Window*> windows;
|
||||||
|
|
||||||
Window* get_window(const platform::window_ptr identifier) {
|
Window* get_window(const platform::window_ptr identifier) {
|
||||||
for(auto& window : windows) {
|
for (auto& window : windows) {
|
||||||
if(window->identifier == identifier)
|
if (window->identifier == identifier)
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +375,6 @@ namespace prism {
|
||||||
inline bool operator==(const AnimationTarget& a1, const AnimationTarget& a2) {
|
inline bool operator==(const AnimationTarget& a1, const AnimationTarget& a2) {
|
||||||
return a1.current_time == a2.current_time;
|
return a1.current_time == a2.current_time;
|
||||||
}
|
}
|
||||||
}
|
} // namespace prism
|
||||||
|
|
||||||
inline prism::engine* engine = nullptr;
|
inline prism::engine* engine = nullptr;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
|
|
||||||
|
@ -27,13 +27,15 @@ namespace prism {
|
||||||
|
|
||||||
/**Opens a file dialog to select a file. This will not block.
|
/**Opens a file dialog to select a file. This will not block.
|
||||||
@param existing Whether or not to limit to existing files.
|
@param existing Whether or not to limit to existing files.
|
||||||
@param returnFunction The callback function when a file is selected or the dialog is cancelled. An empy string is returned when cancelled.
|
@param returnFunction The callback function when a file is selected or the dialog is cancelled. An empy string
|
||||||
|
is returned when cancelled.
|
||||||
@param openDirectory Whether or not to allow selecting directories as well.
|
@param openDirectory Whether or not to allow selecting directories as well.
|
||||||
*/
|
*/
|
||||||
void open_dialog(bool existing, std::function<void(std::string)> returnFunction, bool openDirectory = false);
|
void open_dialog(bool existing, std::function<void(std::string)> returnFunction, bool openDirectory = false);
|
||||||
|
|
||||||
/**Opens a file dialog to select a save location for a file. This will not block.
|
/**Opens a file dialog to select a save location for a file. This will not block.
|
||||||
@param returnFunction The callback function when a file is selected or the dialog is cancelled. An empy string is returned when cancelled.
|
@param returnFunction The callback function when a file is selected or the dialog is cancelled. An empy string
|
||||||
|
is returned when cancelled.
|
||||||
*/
|
*/
|
||||||
void save_dialog(std::function<void(std::string)> returnFunction);
|
void save_dialog(std::function<void(std::string)> returnFunction);
|
||||||
|
|
||||||
|
@ -53,4 +55,4 @@ namespace prism {
|
||||||
dialog_data open_dialog_data;
|
dialog_data open_dialog_data;
|
||||||
dialog_data save_dialog_data;
|
dialog_data save_dialog_data;
|
||||||
};
|
};
|
||||||
}
|
} // namespace prism
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "utility.hpp"
|
|
||||||
#include "math.hpp"
|
#include "math.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace ImGui {
|
namespace ImGui {
|
||||||
template<typename T>
|
template<typename T> inline bool ComboEnum(const char* label, T* t) {
|
||||||
inline bool ComboEnum(const char* label, T* t) {
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
const auto preview_value = utility::enum_to_string(*t);
|
const auto preview_value = utility::enum_to_string(*t);
|
||||||
|
|
||||||
if (ImGui::BeginCombo(label, preview_value.c_str())) {
|
if (ImGui::BeginCombo(label, preview_value.c_str())) {
|
||||||
for(auto& name : magic_enum::enum_values<T>()) {
|
for (auto& name : magic_enum::enum_values<T>()) {
|
||||||
const auto n = utility::enum_to_string(name);
|
const auto n = utility::enum_to_string(name);
|
||||||
|
|
||||||
if (ImGui::Selectable(n.c_str(), *t == name)) {
|
if (ImGui::Selectable(n.c_str(), *t == name)) {
|
||||||
|
@ -28,8 +27,7 @@ namespace ImGui {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TMax>
|
template<typename T, typename TMax> void ProgressBar(const char* label, const T value, const TMax max) {
|
||||||
void ProgressBar(const char* label, const T value, const TMax max) {
|
|
||||||
const float progress_saturated = value / static_cast<float>(max);
|
const float progress_saturated = value / static_cast<float>(max);
|
||||||
|
|
||||||
char buf[32] = {};
|
char buf[32] = {};
|
||||||
|
@ -49,7 +47,7 @@ namespace ImGui {
|
||||||
euler.y = degrees(euler.y);
|
euler.y = degrees(euler.y);
|
||||||
euler.z = degrees(euler.z);
|
euler.z = degrees(euler.z);
|
||||||
|
|
||||||
if(ImGui::DragFloat3(label, euler.ptr(), 1.0f, 0.0f, 0.0f, "%.3f°")) {
|
if (ImGui::DragFloat3(label, euler.ptr(), 1.0f, 0.0f, 0.0f, "%.3f°")) {
|
||||||
euler.x = radians(euler.x);
|
euler.x = radians(euler.x);
|
||||||
euler.y = radians(euler.y);
|
euler.y = radians(euler.y);
|
||||||
euler.z = radians(euler.z);
|
euler.z = radians(euler.z);
|
||||||
|
@ -61,4 +59,4 @@ namespace ImGui {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace ImGui
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
|
|
||||||
|
@ -42,20 +42,20 @@ namespace prism {
|
||||||
/** Add a new binding.
|
/** Add a new binding.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
*/
|
*/
|
||||||
void add_binding(const std::string &name);
|
void add_binding(const std::string& name);
|
||||||
|
|
||||||
/** Ties a button-type input to the binding.
|
/** Ties a button-type input to the binding.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
@param button The button to associate with.
|
@param button The button to associate with.
|
||||||
@param value The resulting input value when the button is pressed. Default is 1.0.
|
@param value The resulting input value when the button is pressed. Default is 1.0.
|
||||||
*/
|
*/
|
||||||
void add_binding_button(const std::string &name, InputButton button, float value = 1.0f);
|
void add_binding_button(const std::string& name, InputButton button, float value = 1.0f);
|
||||||
|
|
||||||
/** Ties an axis-type input to the button.
|
/** Ties an axis-type input to the button.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
@param button The axis to associate with.
|
@param button The axis to associate with.
|
||||||
*/
|
*/
|
||||||
void add_binding_axis(const std::string &name, axis axis);
|
void add_binding_axis(const std::string& name, axis axis);
|
||||||
|
|
||||||
/** Gets the input value of a binding.
|
/** Gets the input value of a binding.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
|
@ -63,20 +63,23 @@ namespace prism {
|
||||||
@note If this binding is tied to a button-type input, assume that 0.0 means not pressed.
|
@note If this binding is tied to a button-type input, assume that 0.0 means not pressed.
|
||||||
@note If this binding is tied to an axis-type input, assume that 0.0 means the stick is centered.
|
@note If this binding is tied to an axis-type input, assume that 0.0 means the stick is centered.
|
||||||
*/
|
*/
|
||||||
float get_value(const std::string &name);
|
float get_value(const std::string& name);
|
||||||
|
|
||||||
/** Gets whether or not the binding is pressed.
|
/** Gets whether or not the binding is pressed.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
@param repeating If true, return a correct value regardless if it was identical for multiple frames. If false, any continued input past the first frame of being pressed is ignored and the input is considered released.
|
@param repeating If true, return a correct value regardless if it was identical for multiple frames. If false,
|
||||||
@return If the binding is found, return true if the binding value is 1.0. If no binding is found or if the binding has continued pressing and repeating is turned off, returns false.
|
any continued input past the first frame of being pressed is ignored and the input is considered released.
|
||||||
|
@return If the binding is found, return true if the binding value is 1.0. If no binding is found or if the
|
||||||
|
binding has continued pressing and repeating is turned off, returns false.
|
||||||
*/
|
*/
|
||||||
bool is_pressed(const std::string &name, bool repeating = false);
|
bool is_pressed(const std::string& name, bool repeating = false);
|
||||||
|
|
||||||
/** Queries if the binding is repeating it's input.
|
/** Queries if the binding is repeating it's input.
|
||||||
@param name The binding name.
|
@param name The binding name.
|
||||||
@return If the binding is found, returns true if the binding's values have been identical for multiple frames. Returns false if the binding is not found.
|
@return If the binding is found, returns true if the binding's values have been identical for multiple frames.
|
||||||
|
Returns false if the binding is not found.
|
||||||
*/
|
*/
|
||||||
bool is_repeating(const std::string &name);
|
bool is_repeating(const std::string& name);
|
||||||
|
|
||||||
/// Returns all of the bindings registered with this Input system.
|
/// Returns all of the bindings registered with this Input system.
|
||||||
[[nodiscard]] std::vector<input_binding> get_bindings() const;
|
[[nodiscard]] std::vector<input_binding> get_bindings() const;
|
||||||
|
@ -93,4 +96,4 @@ namespace prism {
|
||||||
|
|
||||||
bool _in_text_input = false;
|
bool _in_text_input = false;
|
||||||
};
|
};
|
||||||
}
|
} // namespace prism
|
|
@ -5,4 +5,4 @@
|
||||||
namespace prism {
|
namespace prism {
|
||||||
using Object = uint64_t;
|
using Object = uint64_t;
|
||||||
constexpr Object NullObject = 0;
|
constexpr Object NullObject = 0;
|
||||||
}
|
} // namespace prism
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "vector.hpp"
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
class btBroadphaseInterface;
|
class btBroadphaseInterface;
|
||||||
class btDefaultCollisionConfiguration;
|
class btDefaultCollisionConfiguration;
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "object.hpp"
|
|
||||||
#include "components.hpp"
|
#include "components.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
template<class Component>
|
template<class Component> using Pool = std::unordered_map<prism::Object, Component>;
|
||||||
using Pool = std::unordered_map<prism::Object, Component>;
|
|
||||||
|
|
||||||
template<class... Components>
|
template<class... Components> class ObjectComponents : Pool<Components>... {
|
||||||
class ObjectComponents : Pool<Components>... {
|
|
||||||
public:
|
public:
|
||||||
/** Adds a new object.
|
/** Adds a new object.
|
||||||
@param parent The object to parent the new object to. Default is null.
|
@param parent The object to parent the new object to. Default is null.
|
||||||
|
@ -46,8 +44,8 @@ public:
|
||||||
|
|
||||||
/// Find an object by name.
|
/// Find an object by name.
|
||||||
[[nodiscard]] prism::Object find_object(const std::string_view name) const {
|
[[nodiscard]] prism::Object find_object(const std::string_view name) const {
|
||||||
for(auto& obj : _objects) {
|
for (auto& obj : _objects) {
|
||||||
if(get<Data>(obj).name == name)
|
if (get<Data>(obj).name == name)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +80,11 @@ public:
|
||||||
[[nodiscard]] std::vector<prism::Object> children_of(const prism::Object obj, const bool recursive = false) const {
|
[[nodiscard]] std::vector<prism::Object> children_of(const prism::Object obj, const bool recursive = false) const {
|
||||||
std::vector<prism::Object> vec;
|
std::vector<prism::Object> vec;
|
||||||
|
|
||||||
if(recursive) {
|
if (recursive) {
|
||||||
recurse_children(vec, obj);
|
recurse_children(vec, obj);
|
||||||
} else {
|
} else {
|
||||||
for(auto& o : _objects) {
|
for (auto& o : _objects) {
|
||||||
if(get(o).parent == obj)
|
if (get(o).parent == obj)
|
||||||
vec.push_back(o);
|
vec.push_back(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,33 +93,28 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a component.
|
/// Adds a component.
|
||||||
template<class Component>
|
template<class Component> Component& add(const prism::Object object) {
|
||||||
Component& add(const prism::Object object) {
|
|
||||||
return Pool<Component>::emplace(object, Component()).first->second;
|
return Pool<Component>::emplace(object, Component()).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a component.
|
/// Returns a component.
|
||||||
template<class Component = Data>
|
template<class Component = Data> Component& get(const prism::Object object) {
|
||||||
Component& get(const prism::Object object) {
|
|
||||||
return Pool<Component>::at(object);
|
return Pool<Component>::at(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a component.
|
/// Returns a component.
|
||||||
template<class Component = Data>
|
template<class Component = Data> Component get(const prism::Object object) const {
|
||||||
Component get(const prism::Object object) const {
|
|
||||||
return Pool<Component>::at(object);
|
return Pool<Component>::at(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether or not an object has a certain component.
|
/// Checks whether or not an object has a certain component.
|
||||||
template<class Component>
|
template<class Component> [[nodiscard]] bool has(const prism::Object object) const {
|
||||||
[[nodiscard]] bool has(const prism::Object object) const {
|
|
||||||
return Pool<Component>::count(object);
|
return Pool<Component>::count(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a component from an object. Is a no-op if the component wasn't attached.
|
/// Removes a component from an object. Is a no-op if the component wasn't attached.
|
||||||
template<class Component>
|
template<class Component> bool remove(const prism::Object object) {
|
||||||
bool remove(const prism::Object object) {
|
if (has<Component>(object)) {
|
||||||
if(has<Component>(object)) {
|
|
||||||
Pool<Component>::erase(object);
|
Pool<Component>::erase(object);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -130,11 +123,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all instances of a component.
|
/// Returns all instances of a component.
|
||||||
template<class Component>
|
template<class Component> std::vector<std::tuple<prism::Object, Component&>> get_all() {
|
||||||
std::vector<std::tuple<prism::Object, Component&>> get_all() {
|
|
||||||
std::vector<std::tuple<prism::Object, Component&>> comps;
|
std::vector<std::tuple<prism::Object, Component&>> comps;
|
||||||
|
|
||||||
for(auto it = Pool<Component>::begin(); it != Pool<Component>::end(); it++)
|
for (auto it = Pool<Component>::begin(); it != Pool<Component>::end(); it++)
|
||||||
comps.emplace_back(it->first, it->second);
|
comps.emplace_back(it->first, it->second);
|
||||||
|
|
||||||
return comps;
|
return comps;
|
||||||
|
@ -154,7 +146,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void recurse_remove(prism::Object obj) {
|
void recurse_remove(prism::Object obj) {
|
||||||
for(auto& o : children_of(obj))
|
for (auto& o : children_of(obj))
|
||||||
recurse_remove(o);
|
recurse_remove(o);
|
||||||
|
|
||||||
utility::erase(_objects, obj);
|
utility::erase(_objects, obj);
|
||||||
|
@ -165,22 +157,21 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_prefab_parent(prism::Object obj, bool& p) const {
|
void check_prefab_parent(prism::Object obj, bool& p) const {
|
||||||
if(!get(obj).prefab_path.empty())
|
if (!get(obj).prefab_path.empty())
|
||||||
p = true;
|
p = true;
|
||||||
|
|
||||||
if(get(obj).parent != prism::NullObject)
|
if (get(obj).parent != prism::NullObject)
|
||||||
check_prefab_parent(get(obj).parent, p);
|
check_prefab_parent(get(obj).parent, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Component>
|
template<class Component> void add_duplicate_component(const prism::Object from, const prism::Object to) {
|
||||||
void add_duplicate_component(const prism::Object from, const prism::Object to) {
|
if (Pool<Component>::count(from))
|
||||||
if(Pool<Component>::count(from))
|
|
||||||
Pool<Component>::emplace(to, Pool<Component>::at(from));
|
Pool<Component>::emplace(to, Pool<Component>::at(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
void recurse_children(std::vector<prism::Object>& vec, prism::Object obj) const {
|
void recurse_children(std::vector<prism::Object>& vec, prism::Object obj) const {
|
||||||
for(const auto o : _objects) {
|
for (const auto o : _objects) {
|
||||||
if(get(o).parent == obj) {
|
if (get(o).parent == obj) {
|
||||||
vec.push_back(o);
|
vec.push_back(o);
|
||||||
|
|
||||||
recurse_children(vec, o);
|
recurse_children(vec, o);
|
||||||
|
@ -201,25 +192,27 @@ class GFXFramebuffer;
|
||||||
class GFXTexture;
|
class GFXTexture;
|
||||||
|
|
||||||
/// Represents a scene consisting of Objects with varying Components.
|
/// Represents a scene consisting of Objects with varying Components.
|
||||||
class Scene : public ObjectComponents<Data, Transform, Renderable, Light, Camera, Collision, Rigidbody, EnvironmentProbe> {
|
class Scene
|
||||||
|
: public ObjectComponents<Data, Transform, Renderable, Light, Camera, Collision, Rigidbody, EnvironmentProbe> {
|
||||||
public:
|
public:
|
||||||
/// If loaded from disk, the path to the scene file this originated from.
|
/// If loaded from disk, the path to the scene file this originated from.
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
/// Invalidates the current shadow data for all shadowed lights. This may cause stuttering while the data is regenerated.
|
/// Invalidates the current shadow data for all shadowed lights. This may cause stuttering while the data is
|
||||||
|
/// regenerated.
|
||||||
void reset_shadows() {
|
void reset_shadows() {
|
||||||
sun_light_dirty = true;
|
sun_light_dirty = true;
|
||||||
|
|
||||||
for(auto& point_dirty : point_light_dirty)
|
for (auto& point_dirty : point_light_dirty)
|
||||||
point_dirty = true;
|
point_dirty = true;
|
||||||
|
|
||||||
for(auto& spot_dirty : spot_light_dirty)
|
for (auto& spot_dirty : spot_light_dirty)
|
||||||
spot_dirty = true;
|
spot_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invalidates the current environment probe data. This may cause stuttering while the data is regenerated.
|
/// Invalidates the current environment probe data. This may cause stuttering while the data is regenerated.
|
||||||
void reset_environment() {
|
void reset_environment() {
|
||||||
for(auto& probe_dirty : environment_dirty)
|
for (auto& probe_dirty : environment_dirty)
|
||||||
probe_dirty = true;
|
probe_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +244,8 @@ public:
|
||||||
@param cam The camera object.
|
@param cam The camera object.
|
||||||
@param pos The position the camera will be viewing the target from.
|
@param pos The position the camera will be viewing the target from.
|
||||||
@param target The position to be centered in the camera's view.
|
@param target The position to be centered in the camera's view.
|
||||||
@note Although this is a look at function, it applies no special attribute to the camera and simply changes it's position and rotation.
|
@note Although this is a look at function, it applies no special attribute to the camera and simply changes it's
|
||||||
|
position and rotation.
|
||||||
*/
|
*/
|
||||||
void camera_look_at(Scene& scene, prism::Object cam, prism::float3 pos, prism::float3 target);
|
void camera_look_at(Scene& scene, prism::Object cam, prism::float3 pos, prism::float3 target);
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <string>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "file.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "string_utils.hpp"
|
#include "string_utils.hpp"
|
||||||
#include "file.hpp"
|
|
||||||
|
|
||||||
struct registered_command {
|
struct registered_command {
|
||||||
registered_command(const prism::console::argument_format format, const prism::console::function_ptr function) : expected_format(format), function(function) {}
|
registered_command(const prism::console::argument_format format, const prism::console::function_ptr function)
|
||||||
|
: expected_format(format), function(function) {}
|
||||||
|
|
||||||
prism::console::argument_format expected_format;
|
prism::console::argument_format expected_format;
|
||||||
std::function<void(prism::console::arguments)> function;
|
std::function<void(prism::console::arguments)> function;
|
||||||
|
@ -19,8 +20,11 @@ static std::unordered_map<std::string, registered_command> registered_commands;
|
||||||
|
|
||||||
struct RegisteredVariable {
|
struct RegisteredVariable {
|
||||||
RegisteredVariable(bool& data) : type(prism::console::argument_type::Boolean), data(&data) {}
|
RegisteredVariable(bool& data) : type(prism::console::argument_type::Boolean), data(&data) {}
|
||||||
|
|
||||||
RegisteredVariable(float& data) : type(prism::console::argument_type::Float), data(&data) {}
|
RegisteredVariable(float& data) : type(prism::console::argument_type::Float), data(&data) {}
|
||||||
|
|
||||||
RegisteredVariable(int& data) : type(prism::console::argument_type::Integer), data(&data) {}
|
RegisteredVariable(int& data) : type(prism::console::argument_type::Integer), data(&data) {}
|
||||||
|
|
||||||
RegisteredVariable(double& data) : type(prism::console::argument_type::Double), data(&data) {}
|
RegisteredVariable(double& data) : type(prism::console::argument_type::Double), data(&data) {}
|
||||||
|
|
||||||
prism::console::argument_type type;
|
prism::console::argument_type type;
|
||||||
|
@ -33,24 +37,27 @@ static std::unordered_map<std::string, RegisteredVariable> registered_variables;
|
||||||
void prism::console::load_cfg(const prism::path& path) {
|
void prism::console::load_cfg(const prism::path& path) {
|
||||||
auto file = prism::open_file(path);
|
auto file = prism::open_file(path);
|
||||||
auto stream = file->read_as_stream();
|
auto stream = file->read_as_stream();
|
||||||
for (std::string line; getline( stream, line );) {
|
for (std::string line; getline(stream, line);) {
|
||||||
prism::console::parse_and_invoke_command(line);
|
prism::console::parse_and_invoke_command(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prism::console::register_command(const std::string_view name, const prism::console::argument_format expected_format, const prism::console::function_ptr function) {
|
void prism::console::register_command(
|
||||||
|
const std::string_view name,
|
||||||
|
const prism::console::argument_format expected_format,
|
||||||
|
const prism::console::function_ptr function) {
|
||||||
registered_commands.try_emplace(name.data(), registered_command(expected_format, function));
|
registered_commands.try_emplace(name.data(), registered_command(expected_format, function));
|
||||||
}
|
}
|
||||||
|
|
||||||
void prism::console::invoke_command(const std::string_view name, const prism::console::arguments arguments) {
|
void prism::console::invoke_command(const std::string_view name, const prism::console::arguments arguments) {
|
||||||
for(auto& [command_name, command_data] : registered_commands) {
|
for (auto& [command_name, command_data] : registered_commands) {
|
||||||
if(command_name == name) {
|
if (command_name == name) {
|
||||||
bool invalid_format = false;
|
bool invalid_format = false;
|
||||||
|
|
||||||
if(arguments.size() != command_data.expected_format.num_arguments)
|
if (arguments.size() != command_data.expected_format.num_arguments)
|
||||||
invalid_format = true;
|
invalid_format = true;
|
||||||
|
|
||||||
if(invalid_format) {
|
if (invalid_format) {
|
||||||
prism::log("Invalid command format!");
|
prism::log("Invalid command format!");
|
||||||
} else {
|
} else {
|
||||||
command_data.function(console::arguments());
|
command_data.function(console::arguments());
|
||||||
|
@ -60,21 +67,21 @@ void prism::console::invoke_command(const std::string_view name, const prism::co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [variable_name, variable_data] : registered_variables) {
|
for (auto& [variable_name, variable_data] : registered_variables) {
|
||||||
if(variable_name == name) {
|
if (variable_name == name) {
|
||||||
bool invalid_format = false;
|
bool invalid_format = false;
|
||||||
|
|
||||||
if(arguments.empty())
|
if (arguments.empty())
|
||||||
invalid_format = true;
|
invalid_format = true;
|
||||||
|
|
||||||
if(arguments[0].query_type() != variable_data.type)
|
if (arguments[0].query_type() != variable_data.type)
|
||||||
invalid_format = true;
|
invalid_format = true;
|
||||||
|
|
||||||
if(invalid_format) {
|
if (invalid_format) {
|
||||||
prism::log("Wrong or empty variable type!");
|
prism::log("Wrong or empty variable type!");
|
||||||
} else {
|
} else {
|
||||||
auto argument = arguments[0];
|
auto argument = arguments[0];
|
||||||
switch(argument.query_type()) {
|
switch (argument.query_type()) {
|
||||||
case console::argument_type::Boolean:
|
case console::argument_type::Boolean:
|
||||||
*std::get<bool*>(variable_data.data) = std::get<bool>(argument.data);
|
*std::get<bool*>(variable_data.data) = std::get<bool>(argument.data);
|
||||||
break;
|
break;
|
||||||
|
@ -94,15 +101,15 @@ void prism::console::parse_and_invoke_command(const std::string_view command) {
|
||||||
prism::log("> {}", command);
|
prism::log("> {}", command);
|
||||||
|
|
||||||
const auto tokens = tokenize(command, " ");
|
const auto tokens = tokenize(command, " ");
|
||||||
if(tokens.empty())
|
if (tokens.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto try_parse_argument = [](std::string_view arg) -> std::optional<console_argument> {
|
const auto try_parse_argument = [](std::string_view arg) -> std::optional<console_argument> {
|
||||||
if(arg == "true") {
|
if (arg == "true") {
|
||||||
return console_argument(true);
|
return console_argument(true);
|
||||||
} else if(arg == "false") {
|
} else if (arg == "false") {
|
||||||
return console_argument(false);
|
return console_argument(false);
|
||||||
} else if(is_numeric(arg)) {
|
} else if (is_numeric(arg)) {
|
||||||
return console_argument(std::stoi(arg.data()));
|
return console_argument(std::stoi(arg.data()));
|
||||||
} else {
|
} else {
|
||||||
return console_argument(arg);
|
return console_argument(arg);
|
||||||
|
@ -111,8 +118,8 @@ void prism::console::parse_and_invoke_command(const std::string_view command) {
|
||||||
|
|
||||||
std::vector<console_argument> arguments;
|
std::vector<console_argument> arguments;
|
||||||
|
|
||||||
for(int i = 1; i < tokens.size(); i++) {
|
for (int i = 1; i < tokens.size(); i++) {
|
||||||
if(auto arg = try_parse_argument(tokens[i]); arg)
|
if (auto arg = try_parse_argument(tokens[i]); arg)
|
||||||
arguments.push_back(*arg);
|
arguments.push_back(*arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
|
||||||
#include "shadowpass.hpp"
|
|
||||||
#include "scenecapture.hpp"
|
|
||||||
#include "gfx.hpp"
|
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
#include "imgui_utility.hpp"
|
|
||||||
#include "scene.hpp"
|
|
||||||
#include "renderer.hpp"
|
|
||||||
#include "file.hpp"
|
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "gfx.hpp"
|
||||||
#include "imgui_backend.hpp"
|
#include "imgui_backend.hpp"
|
||||||
|
#include "imgui_utility.hpp"
|
||||||
|
#include "renderer.hpp"
|
||||||
|
#include "scene.hpp"
|
||||||
|
#include "scenecapture.hpp"
|
||||||
|
#include "shadowpass.hpp"
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
std::string shader_source_path;
|
std::string shader_source_path;
|
||||||
|
@ -33,14 +33,14 @@ void draw_asset() {
|
||||||
|
|
||||||
ImGui::BeginChild("asset_child", ImVec2(-1, -1), true);
|
ImGui::BeginChild("asset_child", ImVec2(-1, -1), true);
|
||||||
|
|
||||||
for(auto& [path, block] : assetm->reference_blocks) {
|
for (auto& [path, block] : assetm->reference_blocks) {
|
||||||
ImGui::PushID(&block);
|
ImGui::PushID(&block);
|
||||||
|
|
||||||
ImGui::Text("- %s has %lu reference(s)", path.string().c_str(), block->references);
|
ImGui::Text("- %s has %lu reference(s)", path.string().c_str(), block->references);
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(200, 0, 0));
|
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(200, 0, 0));
|
||||||
|
|
||||||
if(ImGui::SmallButton("Force unload"))
|
if (ImGui::SmallButton("Force unload"))
|
||||||
block->references = 0;
|
block->references = 0;
|
||||||
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
@ -52,11 +52,11 @@ void draw_asset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_lighting() {
|
void draw_lighting() {
|
||||||
if(engine->get_scene() != nullptr) {
|
if (engine->get_scene() != nullptr) {
|
||||||
const auto& lights = engine->get_scene()->get_all<Light>();
|
const auto& lights = engine->get_scene()->get_all<Light>();
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Lights")) {
|
if (ImGui::CollapsingHeader("Lights")) {
|
||||||
for (auto&[obj, light]: lights) {
|
for (auto& [obj, light] : lights) {
|
||||||
ImGui::PushID(obj);
|
ImGui::PushID(obj);
|
||||||
|
|
||||||
ImGui::TextDisabled("%s", engine->get_scene()->get(obj).name.c_str());
|
ImGui::TextDisabled("%s", engine->get_scene()->get(obj).name.c_str());
|
||||||
|
@ -72,8 +72,8 @@ void draw_lighting() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Environment")) {
|
if (ImGui::CollapsingHeader("Environment")) {
|
||||||
for(auto& [obj, probe] : engine->get_scene()->get_all<EnvironmentProbe>()) {
|
for (auto& [obj, probe] : engine->get_scene()->get_all<EnvironmentProbe>()) {
|
||||||
ImGui::PushID(obj);
|
ImGui::PushID(obj);
|
||||||
|
|
||||||
ImGui::TextDisabled("%s", engine->get_scene()->get(obj).name.c_str());
|
ImGui::TextDisabled("%s", engine->get_scene()->get(obj).name.c_str());
|
||||||
|
@ -88,8 +88,8 @@ void draw_lighting() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Materials")) {
|
if (ImGui::CollapsingHeader("Materials")) {
|
||||||
for (auto& material: assetm->get_all<Material>()) {
|
for (auto& material : assetm->get_all<Material>()) {
|
||||||
ImGui::PushID(material);
|
ImGui::PushID(material);
|
||||||
|
|
||||||
ImGui::TextDisabled("%s", material->path.c_str());
|
ImGui::TextDisabled("%s", material->path.c_str());
|
||||||
|
@ -103,10 +103,10 @@ void draw_lighting() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::Button("Reload shadows"))
|
if (ImGui::Button("Reload shadows"))
|
||||||
engine->get_scene()->reset_shadows();
|
engine->get_scene()->reset_shadows();
|
||||||
|
|
||||||
if(ImGui::Button("Reload probes"))
|
if (ImGui::Button("Reload probes"))
|
||||||
engine->get_scene()->reset_environment();
|
engine->get_scene()->reset_environment();
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextDisabled("No scene loaded.");
|
ImGui::TextDisabled("No scene loaded.");
|
||||||
|
@ -114,7 +114,7 @@ void draw_lighting() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_renderer() {
|
void draw_renderer() {
|
||||||
if(engine->get_scene() != nullptr) {
|
if (engine->get_scene() != nullptr) {
|
||||||
ImGui::Text("Budgets");
|
ImGui::Text("Budgets");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
@ -126,9 +126,9 @@ void draw_renderer() {
|
||||||
ImGui::ProgressBar("Probe Budget", probes.size(), max_environment_probes);
|
ImGui::ProgressBar("Probe Budget", probes.size(), max_environment_probes);
|
||||||
|
|
||||||
int material_count = 0;
|
int material_count = 0;
|
||||||
for(const auto& [obj, renderable] : renderables) {
|
for (const auto& [obj, renderable] : renderables) {
|
||||||
for(auto& material : renderable.materials) {
|
for (auto& material : renderable.materials) {
|
||||||
if(material)
|
if (material)
|
||||||
material_count++;
|
material_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ void draw_renderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto targets = engine->get_renderer()->get_all_render_targets();
|
auto targets = engine->get_renderer()->get_all_render_targets();
|
||||||
for(auto target : targets) {
|
for (auto target : targets) {
|
||||||
ImGui::Text("Frame %i", target->current_frame);
|
ImGui::Text("Frame %i", target->current_frame);
|
||||||
ImGui::Text("%i %i", target->extent.width, target->extent.height);
|
ImGui::Text("%i %i", target->extent.width, target->extent.height);
|
||||||
ImGui::Image(target->offscreenColorTexture, ImVec2(100, 100));
|
ImGui::Image(target->offscreenColorTexture, ImVec2(100, 100));
|
||||||
|
@ -157,31 +157,30 @@ void draw_renderer() {
|
||||||
ImGui::ComboEnum("Display Color Space", &render_options.display_color_space);
|
ImGui::ComboEnum("Display Color Space", &render_options.display_color_space);
|
||||||
ImGui::ComboEnum("Tonemapping", &render_options.tonemapping);
|
ImGui::ComboEnum("Tonemapping", &render_options.tonemapping);
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Tonemapping")) {
|
if (ImGui::CollapsingHeader("Tonemapping")) {
|
||||||
ImGui::DragFloat("Exposure", &render_options.exposure, 0.1f);
|
ImGui::DragFloat("Exposure", &render_options.exposure, 0.1f);
|
||||||
ImGui::DragFloat("Min Luminance", &render_options.min_luminance);
|
ImGui::DragFloat("Min Luminance", &render_options.min_luminance);
|
||||||
ImGui::DragFloat("Max Luminance", &render_options.max_luminance);
|
ImGui::DragFloat("Max Luminance", &render_options.max_luminance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Depth of Field")) {
|
if (ImGui::CollapsingHeader("Depth of Field")) {
|
||||||
ImGui::Checkbox("Enable DoF", &render_options.enable_depth_of_field);
|
ImGui::Checkbox("Enable DoF", &render_options.enable_depth_of_field);
|
||||||
ImGui::DragFloat("DoF Strength", &render_options.depth_of_field_strength);
|
ImGui::DragFloat("DoF Strength", &render_options.depth_of_field_strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_recompile = false;
|
bool should_recompile = false;
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Dynamic Resolution")) {
|
if (ImGui::CollapsingHeader("Dynamic Resolution")) {
|
||||||
ImGui::Checkbox("Enable Dynamic Resolution", &render_options.dynamic_resolution);
|
ImGui::Checkbox("Enable Dynamic Resolution", &render_options.dynamic_resolution);
|
||||||
|
|
||||||
float render_scale = render_options.render_scale;
|
float render_scale = render_options.render_scale;
|
||||||
if (ImGui::DragFloat("Render Scale", &render_scale, 0.1f, 1.0f, 0.1f)
|
if (ImGui::DragFloat("Render Scale", &render_scale, 0.1f, 1.0f, 0.1f) && render_scale > 0.0f) {
|
||||||
&& render_scale > 0.0f) {
|
|
||||||
render_options.render_scale = render_scale;
|
render_options.render_scale = render_scale;
|
||||||
engine->get_renderer()->recreate_all_render_targets();
|
engine->get_renderer()->recreate_all_render_targets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::InputInt("Shadow Resolution", &render_options.shadow_resolution)) {
|
if (ImGui::InputInt("Shadow Resolution", &render_options.shadow_resolution)) {
|
||||||
engine->get_renderer()->shadow_pass->create_scene_resources(*engine->get_scene());
|
engine->get_renderer()->shadow_pass->create_scene_resources(*engine->get_scene());
|
||||||
engine->get_scene()->reset_shadows();
|
engine->get_scene()->reset_shadows();
|
||||||
}
|
}
|
||||||
|
@ -195,8 +194,8 @@ void draw_renderer() {
|
||||||
ImGui::Checkbox("Enable Extra Passes", &render_options.enable_extra_passes);
|
ImGui::Checkbox("Enable Extra Passes", &render_options.enable_extra_passes);
|
||||||
ImGui::Checkbox("Enable Frustum Culling", &render_options.enable_frustum_culling);
|
ImGui::Checkbox("Enable Frustum Culling", &render_options.enable_frustum_culling);
|
||||||
|
|
||||||
if(ImGui::Button("Force recompile materials (needed for some render option changes!)") || should_recompile) {
|
if (ImGui::Button("Force recompile materials (needed for some render option changes!)") || should_recompile) {
|
||||||
for(auto material : assetm->get_all<Material>()) {
|
for (auto material : assetm->get_all<Material>()) {
|
||||||
material->capture_pipeline = nullptr;
|
material->capture_pipeline = nullptr;
|
||||||
material->skinned_pipeline = nullptr;
|
material->skinned_pipeline = nullptr;
|
||||||
material->static_pipeline = nullptr;
|
material->static_pipeline = nullptr;
|
||||||
|
@ -208,18 +207,18 @@ static inline std::string selected_shader;
|
||||||
static inline std::string loaded_shader_string;
|
static inline std::string loaded_shader_string;
|
||||||
|
|
||||||
void draw_shader_editor() {
|
void draw_shader_editor() {
|
||||||
if(options.shader_source_path.empty()) {
|
if (options.shader_source_path.empty()) {
|
||||||
ImGui::Text("You haven't specified a shader source path yet. Please select one below:");
|
ImGui::Text("You haven't specified a shader source path yet. Please select one below:");
|
||||||
if(ImGui::Button("Select Path")) {
|
if (ImGui::Button("Select Path")) {
|
||||||
engine->get_imgui().open_dialog(false, [](std::string path) {
|
engine->get_imgui().open_dialog(false, [](std::string path) {
|
||||||
// open_dialog() can't select folders yet, so use this as a workaround
|
// open_dialog() can't select folders yet, so use this as a workaround
|
||||||
options.shader_source_path = prism::path(path).parent_path().string();
|
options.shader_source_path = prism::path(path).parent_path().string();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(ImGui::BeginCombo("Select", nullptr)) {
|
if (ImGui::BeginCombo("Select", nullptr)) {
|
||||||
for(auto& shader : engine->get_renderer()->registered_shaders) {
|
for (auto& shader : engine->get_renderer()->registered_shaders) {
|
||||||
if(ImGui::Selectable(shader.filename.data())) {
|
if (ImGui::Selectable(shader.filename.data())) {
|
||||||
selected_shader = shader.filename;
|
selected_shader = shader.filename;
|
||||||
loaded_shader_string.clear();
|
loaded_shader_string.clear();
|
||||||
}
|
}
|
||||||
|
@ -228,49 +227,50 @@ void draw_shader_editor() {
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!selected_shader.empty()) {
|
if (!selected_shader.empty()) {
|
||||||
if(loaded_shader_string.empty()) {
|
if (loaded_shader_string.empty()) {
|
||||||
prism::path base_shader_path = options.shader_source_path;
|
prism::path base_shader_path = options.shader_source_path;
|
||||||
|
|
||||||
shader_compiler.set_include_path(base_shader_path.string());
|
shader_compiler.set_include_path(base_shader_path.string());
|
||||||
|
|
||||||
prism::path shader_path = prism::path(selected_shader);
|
prism::path shader_path = prism::path(selected_shader);
|
||||||
|
|
||||||
auto file = prism::open_file(base_shader_path / shader_path.replace_extension(shader_path.extension().string() + ".glsl"));
|
auto file = prism::open_file(
|
||||||
|
base_shader_path / shader_path.replace_extension(shader_path.extension().string() + ".glsl"));
|
||||||
|
|
||||||
loaded_shader_string = file->read_as_string();
|
loaded_shader_string = file->read_as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::InputTextMultiline("Source", &loaded_shader_string);
|
ImGui::InputTextMultiline("Source", &loaded_shader_string);
|
||||||
|
|
||||||
if(ImGui::Button("Reload"))
|
if (ImGui::Button("Reload"))
|
||||||
engine->get_renderer()->reload_shader(selected_shader, loaded_shader_string);
|
engine->get_renderer()->reload_shader(selected_shader, loaded_shader_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_debug_ui() {
|
void draw_debug_ui() {
|
||||||
if(ImGui::Begin("General"))
|
if (ImGui::Begin("General"))
|
||||||
draw_general();
|
draw_general();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Lighting"))
|
if (ImGui::Begin("Lighting"))
|
||||||
draw_lighting();
|
draw_lighting();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Assets"))
|
if (ImGui::Begin("Assets"))
|
||||||
draw_asset();
|
draw_asset();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Rendering"))
|
if (ImGui::Begin("Rendering"))
|
||||||
draw_renderer();
|
draw_renderer();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if(ImGui::Begin("Shader Editor"))
|
if (ImGui::Begin("Shader Editor"))
|
||||||
draw_shader_editor();
|
draw_shader_editor();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -311,14 +311,14 @@ void draw_console() {
|
||||||
|
|
||||||
const bool input_return = ImGui::InputText("##console_input", &console_input, ImGuiInputTextFlags_EnterReturnsTrue);
|
const bool input_return = ImGui::InputText("##console_input", &console_input, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||||
|
|
||||||
if(input_return)
|
if (input_return)
|
||||||
ImGui::SetKeyboardFocusHere(-1);
|
ImGui::SetKeyboardFocusHere(-1);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
const bool button_return = ImGui::Button("Submit");
|
const bool button_return = ImGui::Button("Submit");
|
||||||
|
|
||||||
if(input_return || button_return) {
|
if (input_return || button_return) {
|
||||||
prism::console::parse_and_invoke_command(console_input);
|
prism::console::parse_and_invoke_command(console_input);
|
||||||
console_input.clear();
|
console_input.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include "scene.hpp"
|
|
||||||
#include "console.hpp"
|
|
||||||
#include "log.hpp"
|
|
||||||
#include "asset.hpp"
|
|
||||||
#include "json_conversions.hpp"
|
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
#include "assertions.hpp"
|
#include "assertions.hpp"
|
||||||
#include "renderer.hpp"
|
#include "asset.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
#include "debug.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "imgui_backend.hpp"
|
#include "imgui_backend.hpp"
|
||||||
#include "debug.hpp"
|
|
||||||
#include "timer.hpp"
|
|
||||||
#include "physics.hpp"
|
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
|
#include "json_conversions.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "physics.hpp"
|
||||||
|
#include "renderer.hpp"
|
||||||
|
#include "scene.hpp"
|
||||||
|
#include "timer.hpp"
|
||||||
|
|
||||||
// TODO: remove these in the future
|
// TODO: remove these in the future
|
||||||
#include "shadowpass.hpp"
|
|
||||||
#include "scenecapture.hpp"
|
#include "scenecapture.hpp"
|
||||||
|
#include "shadowpass.hpp"
|
||||||
|
|
||||||
using prism::engine;
|
using prism::engine;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ engine::engine(const int argc, char* argv[]) {
|
||||||
console::register_variable("rs_frustum_culling", render_options.enable_frustum_culling);
|
console::register_variable("rs_frustum_culling", render_options.enable_frustum_culling);
|
||||||
|
|
||||||
console::register_command("rebuild_mat", console::argument_format(0), [this](const console::arguments&) {
|
console::register_command("rebuild_mat", console::argument_format(0), [this](const console::arguments&) {
|
||||||
for(auto material : assetm->get_all<Material>()) {
|
for (auto material : assetm->get_all<Material>()) {
|
||||||
material->capture_pipeline = nullptr;
|
material->capture_pipeline = nullptr;
|
||||||
material->skinned_pipeline = nullptr;
|
material->skinned_pipeline = nullptr;
|
||||||
material->static_pipeline = nullptr;
|
material->static_pipeline = nullptr;
|
||||||
|
@ -62,7 +62,7 @@ engine::engine(const int argc, char* argv[]) {
|
||||||
quit();
|
quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
for(int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
command_line_arguments.emplace_back(argv[i]);
|
command_line_arguments.emplace_back(argv[i]);
|
||||||
|
|
||||||
input = std::make_unique<input_system>();
|
input = std::make_unique<input_system>();
|
||||||
|
@ -78,7 +78,7 @@ void engine::set_app(prism::app* p_app) {
|
||||||
|
|
||||||
this->current_app = p_app;
|
this->current_app = p_app;
|
||||||
|
|
||||||
if(platform::supports_feature(PlatformFeature::Windowing) && get_app()->is_multimodal()) {
|
if (platform::supports_feature(PlatformFeature::Windowing) && get_app()->is_multimodal()) {
|
||||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,12 +102,12 @@ bool engine::is_paused() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::quit() {
|
void engine::quit() {
|
||||||
if(!windows.empty())
|
if (!windows.empty())
|
||||||
windows[0]->quit_requested = true;
|
windows[0]->quit_requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool engine::is_quitting() const {
|
bool engine::is_quitting() const {
|
||||||
if(!windows.empty())
|
if (!windows.empty())
|
||||||
return windows[0]->quit_requested;
|
return windows[0]->quit_requested;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -154,7 +154,7 @@ Scene* engine::load_scene(const prism::path& path) {
|
||||||
Expects(!path.empty());
|
Expects(!path.empty());
|
||||||
|
|
||||||
auto file = prism::open_file(path);
|
auto file = prism::open_file(path);
|
||||||
if(!file.has_value()) {
|
if (!file.has_value()) {
|
||||||
prism::log("Failed to load scene from {}!", path.string());
|
prism::log("Failed to load scene from {}!", path.string());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -166,8 +166,8 @@ Scene* engine::load_scene(const prism::path& path) {
|
||||||
|
|
||||||
std::map<Object, std::string> parentQueue;
|
std::map<Object, std::string> parentQueue;
|
||||||
|
|
||||||
for(auto& obj : j["objects"]) {
|
for (auto& obj : j["objects"]) {
|
||||||
if(obj.contains("prefabPath")) {
|
if (obj.contains("prefabPath")) {
|
||||||
Object o = add_prefab(*scene, prism::game_domain / obj["prefabPath"].get<std::string_view>());
|
Object o = add_prefab(*scene, prism::game_domain / obj["prefabPath"].get<std::string_view>());
|
||||||
|
|
||||||
scene->get(o).name = obj["name"];
|
scene->get(o).name = obj["name"];
|
||||||
|
@ -179,12 +179,12 @@ Scene* engine::load_scene(const prism::path& path) {
|
||||||
} else {
|
} else {
|
||||||
auto o = load_object(*scene, obj);
|
auto o = load_object(*scene, obj);
|
||||||
|
|
||||||
if(obj.contains("parent"))
|
if (obj.contains("parent"))
|
||||||
parentQueue[o] = obj["parent"];
|
parentQueue[o] = obj["parent"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [obj, toParent] : parentQueue)
|
for (auto& [obj, toParent] : parentQueue)
|
||||||
scene->get<Data>(obj).parent = scene->find_object(toParent);
|
scene->get<Data>(obj).parent = scene->find_object(toParent);
|
||||||
|
|
||||||
setup_scene(*scene);
|
setup_scene(*scene);
|
||||||
|
@ -201,8 +201,8 @@ void engine::save_scene(const std::string_view path) {
|
||||||
|
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
|
|
||||||
for(auto& obj : current_scene->get_objects()) {
|
for (auto& obj : current_scene->get_objects()) {
|
||||||
if(!current_scene->get(obj).editor_object)
|
if (!current_scene->get(obj).editor_object)
|
||||||
j["objects"].push_back(save_object(obj));
|
j["objects"].push_back(save_object(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ void engine::save_scene(const std::string_view path) {
|
||||||
AnimationChannel engine::load_animation(nlohmann::json a) {
|
AnimationChannel engine::load_animation(nlohmann::json a) {
|
||||||
AnimationChannel animation;
|
AnimationChannel animation;
|
||||||
|
|
||||||
for(auto& kf : a["frames"]) {
|
for (auto& kf : a["frames"]) {
|
||||||
PositionKeyFrame keyframe;
|
PositionKeyFrame keyframe;
|
||||||
keyframe.time = kf["time"];
|
keyframe.time = kf["time"];
|
||||||
keyframe.value = kf["value"];
|
keyframe.value = kf["value"];
|
||||||
|
@ -228,7 +228,7 @@ Animation engine::load_animation(const prism::path& path) {
|
||||||
Expects(!path.empty());
|
Expects(!path.empty());
|
||||||
|
|
||||||
auto file = prism::open_file(path, true);
|
auto file = prism::open_file(path, true);
|
||||||
if(!file.has_value()) {
|
if (!file.has_value()) {
|
||||||
prism::log("Failed to load animation from {}!", path.string());
|
prism::log("Failed to load animation from {}!", path.string());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ Animation engine::load_animation(const prism::path& path) {
|
||||||
unsigned int num_channels;
|
unsigned int num_channels;
|
||||||
file->read(&num_channels);
|
file->read(&num_channels);
|
||||||
|
|
||||||
for(unsigned int i = 0; i < num_channels; i++) {
|
for (unsigned int i = 0; i < num_channels; i++) {
|
||||||
AnimationChannel channel;
|
AnimationChannel channel;
|
||||||
|
|
||||||
file->read_string(channel.id);
|
file->read_string(channel.id);
|
||||||
|
@ -249,7 +249,7 @@ Animation engine::load_animation(const prism::path& path) {
|
||||||
unsigned int num_positions;
|
unsigned int num_positions;
|
||||||
file->read(&num_positions);
|
file->read(&num_positions);
|
||||||
|
|
||||||
for(unsigned int j = 0; j < num_positions; j++) {
|
for (unsigned int j = 0; j < num_positions; j++) {
|
||||||
PositionKeyFrame key;
|
PositionKeyFrame key;
|
||||||
file->read(&key);
|
file->read(&key);
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ Animation engine::load_animation(const prism::path& path) {
|
||||||
unsigned int num_rotations;
|
unsigned int num_rotations;
|
||||||
file->read(&num_rotations);
|
file->read(&num_rotations);
|
||||||
|
|
||||||
for(unsigned int j = 0; j < num_rotations; j++) {
|
for (unsigned int j = 0; j < num_rotations; j++) {
|
||||||
RotationKeyFrame key;
|
RotationKeyFrame key;
|
||||||
file->read(&key);
|
file->read(&key);
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ Animation engine::load_animation(const prism::path& path) {
|
||||||
unsigned int num_scales;
|
unsigned int num_scales;
|
||||||
file->read(&num_scales);
|
file->read(&num_scales);
|
||||||
|
|
||||||
for(unsigned int j = 0; j < num_scales; j++) {
|
for (unsigned int j = 0; j < num_scales; j++) {
|
||||||
ScaleKeyFrame key;
|
ScaleKeyFrame key;
|
||||||
file->read(&key);
|
file->read(&key);
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ void engine::load_cutscene(const prism::path& path) {
|
||||||
cutscene = std::make_unique<Cutscene>();
|
cutscene = std::make_unique<Cutscene>();
|
||||||
|
|
||||||
auto file = prism::open_file(path);
|
auto file = prism::open_file(path);
|
||||||
if(!file.has_value()) {
|
if (!file.has_value()) {
|
||||||
prism::log("Failed to load cutscene from {}!", path.string());
|
prism::log("Failed to load cutscene from {}!", path.string());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -296,36 +296,36 @@ void engine::load_cutscene(const prism::path& path) {
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
file->read_as_stream() >> j;
|
file->read_as_stream() >> j;
|
||||||
|
|
||||||
for(auto& s : j["shots"]) {
|
for (auto& s : j["shots"]) {
|
||||||
Shot shot;
|
Shot shot;
|
||||||
shot.begin = s["begin"];
|
shot.begin = s["begin"];
|
||||||
shot.length = s["end"];
|
shot.length = s["end"];
|
||||||
|
|
||||||
for(auto& animation : s["animations"]) {
|
for (auto& animation : s["animations"]) {
|
||||||
shot.channels.push_back(load_animation(animation));
|
shot.channels.push_back(load_animation(animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path_to_scene.count(s["scene"])) {
|
if (path_to_scene.count(s["scene"])) {
|
||||||
shot.scene = path_to_scene[s["scene"]];
|
shot.scene = path_to_scene[s["scene"]];
|
||||||
|
|
||||||
// try to find main camera
|
// try to find main camera
|
||||||
auto [obj, cam] = shot.scene->get_all<Camera>()[0];
|
auto [obj, cam] = shot.scene->get_all<Camera>()[0];
|
||||||
|
|
||||||
for(auto& anim : shot.channels) {
|
for (auto& anim : shot.channels) {
|
||||||
if(anim.target == NullObject)
|
if (anim.target == NullObject)
|
||||||
anim.target = obj;
|
anim.target = obj;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
load_scene(prism::root_path(path) / s["scene"].get<std::string_view>());
|
load_scene(prism::root_path(path) / s["scene"].get<std::string_view>());
|
||||||
|
|
||||||
if(get_scene() == nullptr)
|
if (get_scene() == nullptr)
|
||||||
create_empty_scene();
|
create_empty_scene();
|
||||||
|
|
||||||
auto cameraObj = get_scene()->add_object();
|
auto cameraObj = get_scene()->add_object();
|
||||||
get_scene()->add<Camera>(cameraObj);
|
get_scene()->add<Camera>(cameraObj);
|
||||||
|
|
||||||
for(auto& anim : shot.channels) {
|
for (auto& anim : shot.channels) {
|
||||||
if(anim.target == NullObject)
|
if (anim.target == NullObject)
|
||||||
anim.target = cameraObj;
|
anim.target = cameraObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,13 +342,13 @@ void engine::save_cutscene(const std::string_view path) {
|
||||||
|
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
|
|
||||||
for(auto& shot : cutscene->shots) {
|
for (auto& shot : cutscene->shots) {
|
||||||
nlohmann::json s;
|
nlohmann::json s;
|
||||||
s["begin"] = shot.begin;
|
s["begin"] = shot.begin;
|
||||||
s["end"] = shot.length;
|
s["end"] = shot.length;
|
||||||
|
|
||||||
for(auto& [scene_path, scene] : path_to_scene) {
|
for (auto& [scene_path, scene] : path_to_scene) {
|
||||||
if(shot.scene == scene)
|
if (shot.scene == scene)
|
||||||
s["scene"] = scene_path;
|
s["scene"] = scene_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ prism::Object engine::add_prefab(Scene& scene, const prism::path& path, const st
|
||||||
Expects(!path.empty());
|
Expects(!path.empty());
|
||||||
|
|
||||||
auto file = prism::open_file(path);
|
auto file = prism::open_file(path);
|
||||||
if(!file.has_value()) {
|
if (!file.has_value()) {
|
||||||
prism::log("Failed to load prefab from {}!", path.string());
|
prism::log("Failed to load prefab from {}!", path.string());
|
||||||
return NullObject;
|
return NullObject;
|
||||||
}
|
}
|
||||||
|
@ -375,20 +375,20 @@ prism::Object engine::add_prefab(Scene& scene, const prism::path& path, const st
|
||||||
|
|
||||||
std::map<Object, std::string> parent_queue;
|
std::map<Object, std::string> parent_queue;
|
||||||
|
|
||||||
for(const auto& obj : j["objects"]) {
|
for (const auto& obj : j["objects"]) {
|
||||||
auto o = load_object(scene, obj);
|
auto o = load_object(scene, obj);
|
||||||
|
|
||||||
if(obj.contains("parent")) {
|
if (obj.contains("parent")) {
|
||||||
parent_queue[o] = obj["parent"];
|
parent_queue[o] = obj["parent"];
|
||||||
} else {
|
} else {
|
||||||
root_node = o;
|
root_node = o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [obj, parent_name] : parent_queue)
|
for (auto& [obj, parent_name] : parent_queue)
|
||||||
scene.get(obj).parent = scene.find_object(parent_name);
|
scene.get(obj).parent = scene.find_object(parent_name);
|
||||||
|
|
||||||
if(!override_name.empty() && root_node != NullObject)
|
if (!override_name.empty() && root_node != NullObject)
|
||||||
scene.get(root_node).name = override_name;
|
scene.get(root_node).name = override_name;
|
||||||
|
|
||||||
return root_node;
|
return root_node;
|
||||||
|
@ -400,8 +400,8 @@ void engine::save_prefab(const Object root, const std::string_view path) {
|
||||||
|
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
|
|
||||||
for(auto& obj : current_scene->get_objects()) {
|
for (auto& obj : current_scene->get_objects()) {
|
||||||
if(!current_scene->get(obj).editor_object)
|
if (!current_scene->get(obj).editor_object)
|
||||||
j["objects"].push_back(save_object(obj));
|
j["objects"].push_back(save_object(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ void engine::add_window(void* native_handle, const platform::window_ptr window_p
|
||||||
|
|
||||||
window->identifier = window_ptr;
|
window->identifier = window_ptr;
|
||||||
|
|
||||||
if(platform::is_main_window(window_ptr)) {
|
if (platform::is_main_window(window_ptr)) {
|
||||||
current_renderer = std::make_unique<prism::renderer>(gfx);
|
current_renderer = std::make_unique<prism::renderer>(gfx);
|
||||||
|
|
||||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
|
@ -462,18 +462,18 @@ void engine::move(const platform::window_ptr identifier) {
|
||||||
void engine::process_key_down(const unsigned int keyCode) {
|
void engine::process_key_down(const unsigned int keyCode) {
|
||||||
Expects(keyCode >= 0);
|
Expects(keyCode >= 0);
|
||||||
|
|
||||||
if(input->is_text_input() && !input->get_allowable_text_button(keyCode))
|
if (input->is_text_input() && !input->get_allowable_text_button(keyCode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
imgui->process_key_down(keyCode);
|
imgui->process_key_down(keyCode);
|
||||||
|
|
||||||
if(keyCode == platform::get_keycode(debug_button) && !ImGui::GetIO().WantTextInput)
|
if (keyCode == platform::get_keycode(debug_button) && !ImGui::GetIO().WantTextInput)
|
||||||
debug_enabled = !debug_enabled;
|
debug_enabled = !debug_enabled;
|
||||||
|
|
||||||
if(keyCode == platform::get_keycode(InputButton::C))
|
if (keyCode == platform::get_keycode(InputButton::C))
|
||||||
console_enabled = !console_enabled;
|
console_enabled = !console_enabled;
|
||||||
|
|
||||||
if(keyCode == platform::get_keycode(InputButton::Backspace))
|
if (keyCode == platform::get_keycode(InputButton::Backspace))
|
||||||
ui_enabled = !ui_enabled;
|
ui_enabled = !ui_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,11 +488,11 @@ void engine::process_mouse_down(const int button, const prism::Offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, const Bone* parent_bone) {
|
void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, const Bone* parent_bone) {
|
||||||
if(part.offset_matrices.empty())
|
if (part.offset_matrices.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Matrix4x4 parent_matrix;
|
Matrix4x4 parent_matrix;
|
||||||
if(parent_bone != nullptr)
|
if (parent_bone != nullptr)
|
||||||
parent_matrix = parent_bone->local_transform;
|
parent_matrix = parent_bone->local_transform;
|
||||||
|
|
||||||
Matrix4x4 local = prism::translate(Matrix4x4(), bone.position);
|
Matrix4x4 local = prism::translate(Matrix4x4(), bone.position);
|
||||||
|
@ -503,15 +503,15 @@ void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, cons
|
||||||
|
|
||||||
bone.final_transform = mesh.global_inverse_transformation * bone.local_transform * part.offset_matrices[bone.index];
|
bone.final_transform = mesh.global_inverse_transformation * bone.local_transform * part.offset_matrices[bone.index];
|
||||||
|
|
||||||
for(auto& b : mesh.bones) {
|
for (auto& b : mesh.bones) {
|
||||||
if(b.parent != nullptr && b.parent->index == bone.index)
|
if (b.parent != nullptr && b.parent->index == bone.index)
|
||||||
calculate_bone(mesh, part, b, &bone);
|
calculate_bone(mesh, part, b, &bone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::calculate_object(Scene& scene, Object object, const Object parent_object) {
|
void engine::calculate_object(Scene& scene, Object object, const Object parent_object) {
|
||||||
Matrix4x4 parent_matrix;
|
Matrix4x4 parent_matrix;
|
||||||
if(parent_object != NullObject)
|
if (parent_object != NullObject)
|
||||||
parent_matrix = scene.get<Transform>(parent_object).model;
|
parent_matrix = scene.get<Transform>(parent_object).model;
|
||||||
|
|
||||||
auto& transform = scene.get<Transform>(object);
|
auto& transform = scene.get<Transform>(object);
|
||||||
|
@ -522,40 +522,47 @@ void engine::calculate_object(Scene& scene, Object object, const Object parent_o
|
||||||
|
|
||||||
transform.model = parent_matrix * local;
|
transform.model = parent_matrix * local;
|
||||||
|
|
||||||
if(scene.has<Renderable>(object)) {
|
if (scene.has<Renderable>(object)) {
|
||||||
auto& mesh = scene.get<Renderable>(object);
|
auto& mesh = scene.get<Renderable>(object);
|
||||||
|
|
||||||
if(mesh.mesh && !mesh.mesh->bones.empty()) {
|
if (mesh.mesh && !mesh.mesh->bones.empty()) {
|
||||||
if(mesh.temp_bone_data.empty())
|
if (mesh.temp_bone_data.empty())
|
||||||
mesh.temp_bone_data.resize(mesh.mesh->bones.size());
|
mesh.temp_bone_data.resize(mesh.mesh->bones.size());
|
||||||
|
|
||||||
for(auto& part : mesh.mesh->parts) {
|
for (auto& part : mesh.mesh->parts) {
|
||||||
if(scene.get(object).parent != NullObject && scene.has<Renderable>(scene.get(object).parent) && !scene.get<Renderable>(scene.get(object).parent).mesh->bones.empty()) {
|
if (scene.get(object).parent != NullObject && scene.has<Renderable>(scene.get(object).parent) &&
|
||||||
for(auto [i, ourBone] : utility::enumerate(mesh.mesh->bones)) {
|
!scene.get<Renderable>(scene.get(object).parent).mesh->bones.empty()) {
|
||||||
for(auto& theirBone : scene.get<Renderable>(scene.get(object).parent).mesh->bones) {
|
for (auto [i, ourBone] : utility::enumerate(mesh.mesh->bones)) {
|
||||||
if(ourBone.name == theirBone.name)
|
for (auto& theirBone : scene.get<Renderable>(scene.get(object).parent).mesh->bones) {
|
||||||
mesh.temp_bone_data[i] = mesh.mesh->global_inverse_transformation * theirBone.local_transform * part.offset_matrices[ourBone.index];
|
if (ourBone.name == theirBone.name)
|
||||||
|
mesh.temp_bone_data[i] = mesh.mesh->global_inverse_transformation *
|
||||||
|
theirBone.local_transform *
|
||||||
|
part.offset_matrices[ourBone.index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
calculate_bone(*mesh.mesh.handle, part, *mesh.mesh->root_bone);
|
calculate_bone(*mesh.mesh.handle, part, *mesh.mesh->root_bone);
|
||||||
|
|
||||||
for(auto [i, bone] : utility::enumerate(mesh.temp_bone_data))
|
for (auto [i, bone] : utility::enumerate(mesh.temp_bone_data))
|
||||||
mesh.temp_bone_data[i] = mesh.mesh->bones[i].final_transform;
|
mesh.temp_bone_data[i] = mesh.mesh->bones[i].final_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx->copy_buffer(part.bone_batrix_buffer, mesh.temp_bone_data.data(), 0, mesh.temp_bone_data.size() * sizeof(Matrix4x4));
|
gfx->copy_buffer(
|
||||||
|
part.bone_batrix_buffer,
|
||||||
|
mesh.temp_bone_data.data(),
|
||||||
|
0,
|
||||||
|
mesh.temp_bone_data.size() * sizeof(Matrix4x4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& child : scene.children_of(object))
|
for (auto& child : scene.children_of(object))
|
||||||
calculate_object(scene, child, object);
|
calculate_object(scene, child, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shot* engine::get_shot(const float time) const {
|
Shot* engine::get_shot(const float time) const {
|
||||||
for(auto& shot : cutscene->shots) {
|
for (auto& shot : cutscene->shots) {
|
||||||
if(time >= shot.begin && time <= (shot.begin + shot.length))
|
if (time >= shot.begin && time <= (shot.begin + shot.length))
|
||||||
return &shot;
|
return &shot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,32 +573,35 @@ void engine::update_animation_channel(Scene& scene, const AnimationChannel& chan
|
||||||
{
|
{
|
||||||
int keyframeIndex = -1;
|
int keyframeIndex = -1;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(auto& frame : channel.positions) {
|
for (auto& frame : channel.positions) {
|
||||||
if(time >= frame.time)
|
if (time >= frame.time)
|
||||||
keyframeIndex = i;
|
keyframeIndex = i;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(keyframeIndex != -1) {
|
if (keyframeIndex != -1) {
|
||||||
prism::float3* targetVec = nullptr;
|
prism::float3* targetVec = nullptr;
|
||||||
if(channel.bone != nullptr)
|
if (channel.bone != nullptr)
|
||||||
targetVec = &channel.bone->position;
|
targetVec = &channel.bone->position;
|
||||||
|
|
||||||
if(channel.target != NullObject && scene.has<Data>(channel.target))
|
if (channel.target != NullObject && scene.has<Data>(channel.target))
|
||||||
targetVec = &scene.get<Transform>(channel.target).position;
|
targetVec = &scene.get<Transform>(channel.target).position;
|
||||||
|
|
||||||
auto& startFrame = channel.positions[keyframeIndex];
|
auto& startFrame = channel.positions[keyframeIndex];
|
||||||
|
|
||||||
int endFrameIndex = keyframeIndex + 1;
|
int endFrameIndex = keyframeIndex + 1;
|
||||||
if(endFrameIndex > channel.positions.size() - 1) {
|
if (endFrameIndex > channel.positions.size() - 1) {
|
||||||
if(targetVec != nullptr)
|
if (targetVec != nullptr)
|
||||||
*targetVec = startFrame.value;
|
*targetVec = startFrame.value;
|
||||||
} else {
|
} else {
|
||||||
auto& endFrame = channel.positions[endFrameIndex];
|
auto& endFrame = channel.positions[endFrameIndex];
|
||||||
|
|
||||||
if(targetVec != nullptr)
|
if (targetVec != nullptr)
|
||||||
*targetVec = lerp(startFrame.value, endFrame.value, (float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
*targetVec = lerp(
|
||||||
|
startFrame.value,
|
||||||
|
endFrame.value,
|
||||||
|
(float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,29 +609,32 @@ void engine::update_animation_channel(Scene& scene, const AnimationChannel& chan
|
||||||
{
|
{
|
||||||
int keyframeIndex = -1;
|
int keyframeIndex = -1;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(auto& frame : channel.rotations) {
|
for (auto& frame : channel.rotations) {
|
||||||
if(time >= frame.time)
|
if (time >= frame.time)
|
||||||
keyframeIndex = i;
|
keyframeIndex = i;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(keyframeIndex != -1) {
|
if (keyframeIndex != -1) {
|
||||||
Quaternion* targetVec = nullptr;
|
Quaternion* targetVec = nullptr;
|
||||||
if(channel.bone != nullptr)
|
if (channel.bone != nullptr)
|
||||||
targetVec = &channel.bone->rotation;
|
targetVec = &channel.bone->rotation;
|
||||||
|
|
||||||
auto& startFrame = channel.rotations[keyframeIndex];
|
auto& startFrame = channel.rotations[keyframeIndex];
|
||||||
|
|
||||||
int endFrameIndex = keyframeIndex + 1;
|
int endFrameIndex = keyframeIndex + 1;
|
||||||
if(endFrameIndex > channel.rotations.size() - 1) {
|
if (endFrameIndex > channel.rotations.size() - 1) {
|
||||||
if(targetVec != nullptr)
|
if (targetVec != nullptr)
|
||||||
*targetVec = startFrame.value;
|
*targetVec = startFrame.value;
|
||||||
} else {
|
} else {
|
||||||
auto& endFrame = channel.rotations[endFrameIndex];
|
auto& endFrame = channel.rotations[endFrameIndex];
|
||||||
|
|
||||||
if(targetVec != nullptr)
|
if (targetVec != nullptr)
|
||||||
*targetVec = lerp(startFrame.value, endFrame.value, (float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
*targetVec = lerp(
|
||||||
|
startFrame.value,
|
||||||
|
endFrame.value,
|
||||||
|
(float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,10 +642,10 @@ void engine::update_animation_channel(Scene& scene, const AnimationChannel& chan
|
||||||
|
|
||||||
void engine::update_cutscene(const float time) {
|
void engine::update_cutscene(const float time) {
|
||||||
Shot* currentShot = get_shot(time);
|
Shot* currentShot = get_shot(time);
|
||||||
if(currentShot != nullptr) {
|
if (currentShot != nullptr) {
|
||||||
current_scene = currentShot->scene;
|
current_scene = currentShot->scene;
|
||||||
|
|
||||||
for(auto& channel : currentShot->channels)
|
for (auto& channel : currentShot->channels)
|
||||||
update_animation_channel(*current_scene, channel, time);
|
update_animation_channel(*current_scene, channel, time);
|
||||||
} else {
|
} else {
|
||||||
current_scene = nullptr;
|
current_scene = nullptr;
|
||||||
|
@ -640,14 +653,14 @@ void engine::update_cutscene(const float time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::update_animation(const Animation& anim, const float time) {
|
void engine::update_animation(const Animation& anim, const float time) {
|
||||||
for(const auto& channel : anim.channels)
|
for (const auto& channel : anim.channels)
|
||||||
update_animation_channel(*current_scene, channel, time);
|
update_animation_channel(*current_scene, channel, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::begin_frame(const float delta_time) {
|
void engine::begin_frame(const float delta_time) {
|
||||||
imgui->begin_frame(delta_time);
|
imgui->begin_frame(delta_time);
|
||||||
|
|
||||||
if(ui_enabled) {
|
if (ui_enabled) {
|
||||||
if (debug_enabled)
|
if (debug_enabled)
|
||||||
draw_debug_ui();
|
draw_debug_ui();
|
||||||
|
|
||||||
|
@ -655,7 +668,7 @@ void engine::begin_frame(const float delta_time) {
|
||||||
draw_console();
|
draw_console();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current_app != nullptr)
|
if (current_app != nullptr)
|
||||||
current_app->begin_frame();
|
current_app->begin_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,11 +682,11 @@ const int frame_delay_between_resolution_change = 60;
|
||||||
void engine::update(const float delta_time) {
|
void engine::update(const float delta_time) {
|
||||||
const float ideal_delta_time = 0.01667f;
|
const float ideal_delta_time = 0.01667f;
|
||||||
|
|
||||||
if(render_options.dynamic_resolution) {
|
if (render_options.dynamic_resolution) {
|
||||||
frame_delay++;
|
frame_delay++;
|
||||||
|
|
||||||
if(frame_delay >= frame_delay_between_resolution_change) {
|
if (frame_delay >= frame_delay_between_resolution_change) {
|
||||||
if(delta_time > ideal_delta_time) {
|
if (delta_time > ideal_delta_time) {
|
||||||
render_options.render_scale -= 0.1f;
|
render_options.render_scale -= 0.1f;
|
||||||
|
|
||||||
render_options.render_scale = std::fmax(render_options.render_scale, 0.1f);
|
render_options.render_scale = std::fmax(render_options.render_scale, 0.1f);
|
||||||
|
@ -687,21 +700,21 @@ void engine::update(const float delta_time) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& timer : timers) {
|
for (auto& timer : timers) {
|
||||||
if(!paused || (paused && timer->continue_during_pause))
|
if (!paused || (paused && timer->continue_during_pause))
|
||||||
timer->current_time += delta_time;
|
timer->current_time += delta_time;
|
||||||
|
|
||||||
if(timer->current_time >= timer->duration) {
|
if (timer->current_time >= timer->duration) {
|
||||||
timer->callback();
|
timer->callback();
|
||||||
|
|
||||||
timer->current_time = 0.0f;
|
timer->current_time = 0.0f;
|
||||||
|
|
||||||
if(timer->remove_on_trigger)
|
if (timer->remove_on_trigger)
|
||||||
timers_to_remove.push_back(timer);
|
timers_to_remove.push_back(timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& timer : timers_to_remove)
|
for (auto& timer : timers_to_remove)
|
||||||
utility::erase(timers, timer);
|
utility::erase(timers, timer);
|
||||||
|
|
||||||
timers_to_remove.clear();
|
timers_to_remove.clear();
|
||||||
|
@ -710,19 +723,19 @@ void engine::update(const float delta_time) {
|
||||||
|
|
||||||
current_app->update(delta_time);
|
current_app->update(delta_time);
|
||||||
|
|
||||||
if(cutscene != nullptr && play_cutscene && !paused) {
|
if (cutscene != nullptr && play_cutscene && !paused) {
|
||||||
update_cutscene(current_cutscene_time);
|
update_cutscene(current_cutscene_time);
|
||||||
|
|
||||||
current_cutscene_time += delta_time;
|
current_cutscene_time += delta_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current_scene != nullptr) {
|
if (current_scene != nullptr) {
|
||||||
if(update_physics && !paused)
|
if (update_physics && !paused)
|
||||||
physics->update(delta_time);
|
physics->update(delta_time);
|
||||||
|
|
||||||
for(auto& target : animation_targets) {
|
for (auto& target : animation_targets) {
|
||||||
if((target.current_time * target.animation.ticks_per_second) > target.animation.duration) {
|
if ((target.current_time * target.animation.ticks_per_second) > target.animation.duration) {
|
||||||
if(target.looping) {
|
if (target.looping) {
|
||||||
target.current_time = 0.0f;
|
target.current_time = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
utility::erase(animation_targets, target);
|
utility::erase(animation_targets, target);
|
||||||
|
@ -741,27 +754,31 @@ void engine::update(const float delta_time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::update_scene(Scene& scene) {
|
void engine::update_scene(Scene& scene) {
|
||||||
for(auto& obj : scene.get_objects()) {
|
for (auto& obj : scene.get_objects()) {
|
||||||
if(scene.get(obj).parent == NullObject)
|
if (scene.get(obj).parent == NullObject)
|
||||||
calculate_object(scene, obj);
|
calculate_object(scene, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::render(const platform::window_ptr index) {
|
void engine::render(const platform::window_ptr index) {
|
||||||
auto window = get_window(index);
|
auto window = get_window(index);
|
||||||
if(window == nullptr)
|
if (window == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GFXCommandBuffer* commandbuffer = gfx->acquire_command_buffer(true);
|
GFXCommandBuffer* commandbuffer = gfx->acquire_command_buffer(true);
|
||||||
|
|
||||||
if(platform::is_main_window(index)) {
|
if (platform::is_main_window(index)) {
|
||||||
imgui->render();
|
imgui->render();
|
||||||
|
|
||||||
current_app->render(commandbuffer);
|
current_app->render(commandbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current_renderer != nullptr)
|
if (current_renderer != nullptr)
|
||||||
current_renderer->render(commandbuffer, current_app->wants_no_scene_rendering() ? nullptr : current_scene, *window->render_target, index);
|
current_renderer->render(
|
||||||
|
commandbuffer,
|
||||||
|
current_app->wants_no_scene_rendering() ? nullptr : current_scene,
|
||||||
|
*window->render_target,
|
||||||
|
index);
|
||||||
|
|
||||||
gfx->submit(commandbuffer, index);
|
gfx->submit(commandbuffer, index);
|
||||||
}
|
}
|
||||||
|
@ -785,8 +802,8 @@ void engine::set_current_scene(Scene* scene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view engine::get_scene_path() const {
|
std::string_view engine::get_scene_path() const {
|
||||||
for(auto& [path, scene] : path_to_scene) {
|
for (auto& [path, scene] : path_to_scene) {
|
||||||
if(scene == this->current_scene)
|
if (scene == this->current_scene)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,7 +819,7 @@ void engine::on_remove(Object object) {
|
||||||
void engine::play_animation(Animation animation, Object object, bool looping) {
|
void engine::play_animation(Animation animation, Object object, bool looping) {
|
||||||
Expects(object != NullObject);
|
Expects(object != NullObject);
|
||||||
|
|
||||||
if(!current_scene->has<Renderable>(object))
|
if (!current_scene->has<Renderable>(object))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AnimationTarget target;
|
AnimationTarget target;
|
||||||
|
@ -810,9 +827,9 @@ void engine::play_animation(Animation animation, Object object, bool looping) {
|
||||||
target.target = object;
|
target.target = object;
|
||||||
target.looping = looping;
|
target.looping = looping;
|
||||||
|
|
||||||
for(auto& channel : target.animation.channels) {
|
for (auto& channel : target.animation.channels) {
|
||||||
for(auto& bone : current_scene->get<Renderable>(object).mesh->bones) {
|
for (auto& bone : current_scene->get<Renderable>(object).mesh->bones) {
|
||||||
if(channel.id == bone.name)
|
if (channel.id == bone.name)
|
||||||
channel.bone = &bone;
|
channel.bone = &bone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,15 +838,15 @@ void engine::play_animation(Animation animation, Object object, bool looping) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::set_animation_speed_modifier(Object target, float modifier) {
|
void engine::set_animation_speed_modifier(Object target, float modifier) {
|
||||||
for(auto& animation : animation_targets) {
|
for (auto& animation : animation_targets) {
|
||||||
if(animation.target == target)
|
if (animation.target == target)
|
||||||
animation.animation_speed_modifier = modifier;
|
animation.animation_speed_modifier = modifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void engine::stop_animation(Object target) {
|
void engine::stop_animation(Object target) {
|
||||||
for(auto& animation : animation_targets) {
|
for (auto& animation : animation_targets) {
|
||||||
if(animation.target == target)
|
if (animation.target == target)
|
||||||
utility::erase(animation_targets, animation);
|
utility::erase(animation_targets, animation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "log.hpp"
|
|
||||||
#include "assertions.hpp"
|
#include "assertions.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
|
||||||
prism::path prism::root_path(const path& path) {
|
prism::path prism::root_path(const path& path) {
|
||||||
auto p = path;
|
auto p = path;
|
||||||
while(p.parent_path() != p && p.parent_path() != "/") {
|
while (p.parent_path() != p && p.parent_path() != "/") {
|
||||||
p = p.parent_path();
|
p = p.parent_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ std::optional<prism::file> prism::open_file(const prism::path& path, const bool
|
||||||
|
|
||||||
auto str = get_file_path(path).string();
|
auto str = get_file_path(path).string();
|
||||||
FILE* file = fopen(str.c_str(), binary_mode ? "rb" : "r");
|
FILE* file = fopen(str.c_str(), binary_mode ? "rb" : "r");
|
||||||
if(file == nullptr) {
|
if (file == nullptr) {
|
||||||
prism::log("Failed to open file handle from {}!", str);
|
prism::log("Failed to open file handle from {}!", str);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@ std::optional<prism::file> prism::open_file(const prism::path& path, const bool
|
||||||
prism::path prism::get_file_path(const prism::path& path) {
|
prism::path prism::get_file_path(const prism::path& path) {
|
||||||
auto fixed_path = path;
|
auto fixed_path = path;
|
||||||
auto root = root_path(path);
|
auto root = root_path(path);
|
||||||
if(root == game_domain) {
|
if (root == game_domain) {
|
||||||
fixed_path = domain_data[static_cast<int>(domain::game)] / path.lexically_relative(root_path(path));
|
fixed_path = domain_data[static_cast<int>(domain::game)] / path.lexically_relative(root_path(path));
|
||||||
} else if(root == base_domain) {
|
} else if (root == base_domain) {
|
||||||
fixed_path = domain_data[static_cast<int>(domain::base)] / path.lexically_relative(root_path(path));
|
fixed_path = domain_data[static_cast<int>(domain::base)] / path.lexically_relative(root_path(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_stdlib.h>
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
#include "engine.hpp"
|
|
||||||
#include "platform.hpp"
|
|
||||||
#include "assertions.hpp"
|
|
||||||
#include "input.hpp"
|
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
|
#include "assertions.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
#include "input.hpp"
|
||||||
|
#include "platform.hpp"
|
||||||
|
|
||||||
using prism::imgui_backend;
|
using prism::imgui_backend;
|
||||||
|
|
||||||
|
@ -32,8 +32,7 @@ const std::map<ImGuiKey, InputButton> imToPl = {
|
||||||
{ImGuiKey_V, InputButton::V},
|
{ImGuiKey_V, InputButton::V},
|
||||||
{ImGuiKey_X, InputButton::X},
|
{ImGuiKey_X, InputButton::X},
|
||||||
{ImGuiKey_Y, InputButton::Y},
|
{ImGuiKey_Y, InputButton::Y},
|
||||||
{ImGuiKey_Z, InputButton::Z}
|
{ImGuiKey_Z, InputButton::Z}};
|
||||||
};
|
|
||||||
|
|
||||||
imgui_backend::imgui_backend() {
|
imgui_backend::imgui_backend() {
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
@ -49,12 +48,11 @@ imgui_backend::imgui_backend() {
|
||||||
io.KeyMap[im] = platform::get_keycode(pl);
|
io.KeyMap[im] = platform::get_keycode(pl);
|
||||||
|
|
||||||
const auto theme = platform::get_theme();
|
const auto theme = platform::get_theme();
|
||||||
switch(theme) {
|
switch (theme) {
|
||||||
case PlatformTheme::Light:
|
case PlatformTheme::Light:
|
||||||
ImGui::StyleColorsLight();
|
ImGui::StyleColorsLight();
|
||||||
break;
|
break;
|
||||||
case PlatformTheme::Dark:
|
case PlatformTheme::Dark: {
|
||||||
{
|
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
auto& style = ImGui::GetStyle();
|
auto& style = ImGui::GetStyle();
|
||||||
|
@ -88,8 +86,7 @@ imgui_backend::imgui_backend() {
|
||||||
colors[ImGuiCol_Tab] = ImVec4(0.22f, 0.27f, 0.33f, 0.86f);
|
colors[ImGuiCol_Tab] = ImVec4(0.22f, 0.27f, 0.33f, 0.86f);
|
||||||
colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.51f, 0.75f, 1.00f);
|
colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.51f, 0.75f, 1.00f);
|
||||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.30f, 0.33f, 0.38f, 1.00f);
|
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.30f, 0.33f, 0.38f, 1.00f);
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
@ -109,7 +106,8 @@ imgui_backend::imgui_backend() {
|
||||||
platform_io.Monitors.push_back(monitor);
|
platform_io.Monitors.push_back(monitor);
|
||||||
|
|
||||||
platform_io.Platform_CreateWindow = [](ImGuiViewport* viewport) {
|
platform_io.Platform_CreateWindow = [](ImGuiViewport* viewport) {
|
||||||
viewport->PlatformHandle = platform::open_window("", {viewport->Pos, viewport->Size}, WindowFlags::Borderless | WindowFlags::Hidden);
|
viewport->PlatformHandle =
|
||||||
|
platform::open_window("", {viewport->Pos, viewport->Size}, WindowFlags::Borderless | WindowFlags::Hidden);
|
||||||
};
|
};
|
||||||
|
|
||||||
platform_io.Platform_DestroyWindow = [](ImGuiViewport* viewport) {
|
platform_io.Platform_DestroyWindow = [](ImGuiViewport* viewport) {
|
||||||
|
@ -156,13 +154,13 @@ imgui_backend::imgui_backend() {
|
||||||
|
|
||||||
void imgui_backend::process_move(platform::window_ptr identifier) {
|
void imgui_backend::process_move(platform::window_ptr identifier) {
|
||||||
auto viewport = ImGui::FindViewportByPlatformHandle(identifier);
|
auto viewport = ImGui::FindViewportByPlatformHandle(identifier);
|
||||||
if(viewport != nullptr)
|
if (viewport != nullptr)
|
||||||
viewport->PlatformRequestMove = true;
|
viewport->PlatformRequestMove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void imgui_backend::process_resize(platform::window_ptr identifier) {
|
void imgui_backend::process_resize(platform::window_ptr identifier) {
|
||||||
auto viewport = ImGui::FindViewportByPlatformHandle(identifier);
|
auto viewport = ImGui::FindViewportByPlatformHandle(identifier);
|
||||||
if(viewport != nullptr)
|
if (viewport != nullptr)
|
||||||
viewport->PlatformRequestResize = true;
|
viewport->PlatformRequestResize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +170,8 @@ void imgui_backend::begin_frame(const float delta_time) {
|
||||||
const bool imgui_wants_text = io.WantTextInput;
|
const bool imgui_wants_text = io.WantTextInput;
|
||||||
const bool input_is_text = ::engine->get_input()->is_text_input();
|
const bool input_is_text = ::engine->get_input()->is_text_input();
|
||||||
|
|
||||||
if(imgui_wants_text != input_is_text) {
|
if (imgui_wants_text != input_is_text) {
|
||||||
if(imgui_wants_text) {
|
if (imgui_wants_text) {
|
||||||
::engine->get_input()->begin_text_input();
|
::engine->get_input()->begin_text_input();
|
||||||
} else {
|
} else {
|
||||||
::engine->get_input()->end_text_input();
|
::engine->get_input()->end_text_input();
|
||||||
|
@ -184,7 +182,8 @@ void imgui_backend::begin_frame(const float delta_time) {
|
||||||
const auto drawableSize = platform::get_window_drawable_size(::engine->get_main_window());
|
const auto drawableSize = platform::get_window_drawable_size(::engine->get_main_window());
|
||||||
|
|
||||||
io.DisplaySize = size;
|
io.DisplaySize = size;
|
||||||
io.DisplayFramebufferScale = ImVec2(static_cast<float>(drawableSize.width) / static_cast<float>(size.width),
|
io.DisplayFramebufferScale = ImVec2(
|
||||||
|
static_cast<float>(drawableSize.width) / static_cast<float>(size.width),
|
||||||
static_cast<float>(drawableSize.height) / static_cast<float>(size.height));
|
static_cast<float>(drawableSize.height) / static_cast<float>(size.height));
|
||||||
io.DeltaTime = delta_time;
|
io.DeltaTime = delta_time;
|
||||||
io.KeyCtrl = platform::get_key_down(InputButton::Ctrl);
|
io.KeyCtrl = platform::get_key_down(InputButton::Ctrl);
|
||||||
|
@ -197,7 +196,7 @@ void imgui_backend::begin_frame(const float delta_time) {
|
||||||
io.MouseWheel = sy;
|
io.MouseWheel = sy;
|
||||||
io.MouseWheelH = sx;
|
io.MouseWheelH = sx;
|
||||||
|
|
||||||
if(io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||||
const auto [x, y] = platform::get_screen_cursor_position();
|
const auto [x, y] = platform::get_screen_cursor_position();
|
||||||
|
|
||||||
io.MousePos = ImVec2(static_cast<float>(x), static_cast<float>(y));
|
io.MousePos = ImVec2(static_cast<float>(x), static_cast<float>(y));
|
||||||
|
@ -214,28 +213,31 @@ void imgui_backend::begin_frame(const float delta_time) {
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
if(open_dialog_next_frame) {
|
if (open_dialog_next_frame) {
|
||||||
ImGui::OpenPopup("Open File");
|
ImGui::OpenPopup("Open File");
|
||||||
open_dialog_next_frame = false;
|
open_dialog_next_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(save_dialog_next_frame) {
|
if (save_dialog_next_frame) {
|
||||||
ImGui::OpenPopup("Save File");
|
ImGui::OpenPopup("Save File");
|
||||||
save_dialog_next_frame = false;
|
save_dialog_next_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto dialog_function = [](dialog_data& data) {
|
const auto dialog_function = [](dialog_data& data) {
|
||||||
if(ImGui::Selectable("..", false, ImGuiSelectableFlags_DontClosePopups))
|
if (ImGui::Selectable("..", false, ImGuiSelectableFlags_DontClosePopups))
|
||||||
data.current_path = data.current_path.parent_path();
|
data.current_path = data.current_path.parent_path();
|
||||||
|
|
||||||
if(data.select_directory) {
|
if (data.select_directory) {
|
||||||
if(ImGui::Selectable(".", false, ImGuiSelectableFlags_DontClosePopups))
|
if (ImGui::Selectable(".", false, ImGuiSelectableFlags_DontClosePopups))
|
||||||
data.selected_path = data.current_path;
|
data.selected_path = data.current_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto& dir_ent : std::filesystem::directory_iterator(data.current_path)) {
|
for (const auto& dir_ent : std::filesystem::directory_iterator(data.current_path)) {
|
||||||
if(ImGui::Selectable(dir_ent.path().string().c_str(), data.selected_path == dir_ent.path(), ImGuiSelectableFlags_DontClosePopups)) {
|
if (ImGui::Selectable(
|
||||||
if(dir_ent.is_directory())
|
dir_ent.path().string().c_str(),
|
||||||
|
data.selected_path == dir_ent.path(),
|
||||||
|
ImGuiSelectableFlags_DontClosePopups)) {
|
||||||
|
if (dir_ent.is_directory())
|
||||||
data.current_path = dir_ent.path();
|
data.current_path = dir_ent.path();
|
||||||
else
|
else
|
||||||
data.selected_path = dir_ent.path();
|
data.selected_path = dir_ent.path();
|
||||||
|
@ -244,21 +246,21 @@ void imgui_backend::begin_frame(const float delta_time) {
|
||||||
|
|
||||||
ImGui::TextDisabled("Selected: %s", data.selected_path.c_str());
|
ImGui::TextDisabled("Selected: %s", data.selected_path.c_str());
|
||||||
|
|
||||||
if(ImGui::Button("OK")) {
|
if (ImGui::Button("OK")) {
|
||||||
data.return_function(data.selected_path.string());
|
data.return_function(data.selected_path.string());
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::Button("Cancel"))
|
if (ImGui::Button("Cancel"))
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
};
|
};
|
||||||
|
|
||||||
if(ImGui::BeginPopup("Open File")) {
|
if (ImGui::BeginPopup("Open File")) {
|
||||||
dialog_function(open_dialog_data);
|
dialog_function(open_dialog_data);
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::BeginPopup("Save File")) {
|
if (ImGui::BeginPopup("Save File")) {
|
||||||
dialog_function(save_dialog_data);
|
dialog_function(save_dialog_data);
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
@ -294,7 +296,10 @@ void prism::imgui_backend::process_text_input(const std::string_view string) {
|
||||||
io.AddInputCharactersUTF8(string.data());
|
io.AddInputCharactersUTF8(string.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void prism::imgui_backend::open_dialog(const bool, std::function<void(std::string)> returnFunction, bool openDirectory) {
|
void prism::imgui_backend::open_dialog(
|
||||||
|
const bool,
|
||||||
|
std::function<void(std::string)> returnFunction,
|
||||||
|
bool openDirectory) {
|
||||||
open_dialog_next_frame = true;
|
open_dialog_next_frame = true;
|
||||||
open_dialog_data.current_path = std::filesystem::current_path();
|
open_dialog_data.current_path = std::filesystem::current_path();
|
||||||
open_dialog_data.return_function = returnFunction;
|
open_dialog_data.return_function = returnFunction;
|
||||||
|
|
|
@ -17,8 +17,7 @@ void input_system::update() {
|
||||||
const auto& [x, y] = platform::get_cursor_position();
|
const auto& [x, y] = platform::get_cursor_position();
|
||||||
auto& [oldX, oldY] = _last_cursor_position;
|
auto& [oldX, oldY] = _last_cursor_position;
|
||||||
|
|
||||||
const auto [width, height] =
|
const auto [width, height] = platform::get_window_size(::engine->get_main_window());
|
||||||
platform::get_window_size(::engine->get_main_window());
|
|
||||||
|
|
||||||
float xDelta = (x - oldX) / (float)width;
|
float xDelta = (x - oldX) / (float)width;
|
||||||
float yDelta = (y - oldY) / (float)height;
|
float yDelta = (y - oldY) / (float)height;
|
||||||
|
@ -112,8 +111,7 @@ void input_system::add_binding(const std::string& name) {
|
||||||
_input_bindings.push_back(data);
|
_input_bindings.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_system::add_binding_button(const std::string& name, InputButton key,
|
void input_system::add_binding_button(const std::string& name, InputButton key, float value) {
|
||||||
float value) {
|
|
||||||
for (auto& binding : _input_bindings) {
|
for (auto& binding : _input_bindings) {
|
||||||
if (binding.name == name)
|
if (binding.name == name)
|
||||||
binding.buttons[key] = value;
|
binding.buttons[key] = value;
|
||||||
|
@ -166,7 +164,9 @@ void input_system::end_text_input() {
|
||||||
platform::end_text_input();
|
platform::end_text_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool input_system::is_text_input() const { return _in_text_input; }
|
bool input_system::is_text_input() const {
|
||||||
|
return _in_text_input;
|
||||||
|
}
|
||||||
|
|
||||||
bool input_system::get_allowable_text_button(unsigned int keycode) const {
|
bool input_system::get_allowable_text_button(unsigned int keycode) const {
|
||||||
if (platform::get_keycode(InputButton::Backspace) == keycode)
|
if (platform::get_keycode(InputButton::Backspace) == keycode)
|
||||||
|
|
|
@ -12,14 +12,15 @@ Physics::Physics() {
|
||||||
Physics::~Physics() {}
|
Physics::~Physics() {}
|
||||||
|
|
||||||
void Physics::update(float deltaTime) {
|
void Physics::update(float deltaTime) {
|
||||||
if(engine->get_scene() == nullptr)
|
if (engine->get_scene() == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(auto [obj, rigidbody] : engine->get_scene()->get_all<Rigidbody>()) {
|
for (auto [obj, rigidbody] : engine->get_scene()->get_all<Rigidbody>()) {
|
||||||
if(rigidbody.body != nullptr) {
|
if (rigidbody.body != nullptr) {
|
||||||
if(rigidbody.type == Rigidbody::Type::Dynamic) {
|
if (rigidbody.type == Rigidbody::Type::Dynamic) {
|
||||||
if(rigidbody.stored_force != prism::float3(0.0f)) {
|
if (rigidbody.stored_force != prism::float3(0.0f)) {
|
||||||
rigidbody.body->setLinearVelocity(btVector3(rigidbody.stored_force.x, rigidbody.stored_force.y, rigidbody.stored_force.z));
|
rigidbody.body->setLinearVelocity(
|
||||||
|
btVector3(rigidbody.stored_force.x, rigidbody.stored_force.y, rigidbody.stored_force.z));
|
||||||
rigidbody.stored_force = prism::float3(0.0f);
|
rigidbody.stored_force = prism::float3(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,11 +29,12 @@ void Physics::update(float deltaTime) {
|
||||||
|
|
||||||
world->stepSimulation(deltaTime);
|
world->stepSimulation(deltaTime);
|
||||||
|
|
||||||
for(auto [object, collision] : engine->get_scene()->get_all<Collision>()) {
|
for (auto [object, collision] : engine->get_scene()->get_all<Collision>()) {
|
||||||
if(collision.shape == nullptr && !collision.is_trigger) {
|
if (collision.shape == nullptr && !collision.is_trigger) {
|
||||||
switch(collision.type) {
|
switch (collision.type) {
|
||||||
case Collision::Type::Cube:
|
case Collision::Type::Cube:
|
||||||
collision.shape = new btBoxShape(btVector3(collision.size.x / 2.0f, collision.size.y / 2.0f, collision.size.z / 2.0f));
|
collision.shape = new btBoxShape(
|
||||||
|
btVector3(collision.size.x / 2.0f, collision.size.y / 2.0f, collision.size.z / 2.0f));
|
||||||
break;
|
break;
|
||||||
case Collision::Type::Capsule:
|
case Collision::Type::Capsule:
|
||||||
collision.shape = new btCapsuleShape(0.5f, collision.size.y);
|
collision.shape = new btCapsuleShape(0.5f, collision.size.y);
|
||||||
|
@ -41,34 +43,36 @@ void Physics::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto [obj, rigidbody] : engine->get_scene()->get_all<Rigidbody>()) {
|
for (auto [obj, rigidbody] : engine->get_scene()->get_all<Rigidbody>()) {
|
||||||
auto& transform = engine->get_scene()->get<Transform>(obj);
|
auto& transform = engine->get_scene()->get<Transform>(obj);
|
||||||
|
|
||||||
if(rigidbody.body == nullptr) {
|
if (rigidbody.body == nullptr) {
|
||||||
btTransform t;
|
btTransform t;
|
||||||
t.setIdentity();
|
t.setIdentity();
|
||||||
|
|
||||||
t.setOrigin(btVector3(transform.position.x, transform.position.y, transform.position.z));
|
t.setOrigin(btVector3(transform.position.x, transform.position.y, transform.position.z));
|
||||||
t.setRotation(btQuaternion(transform.rotation.x, transform.rotation.y, transform.rotation.z, transform.rotation.w));
|
t.setRotation(
|
||||||
|
btQuaternion(transform.rotation.x, transform.rotation.y, transform.rotation.z, transform.rotation.w));
|
||||||
|
|
||||||
btDefaultMotionState* motionState = new btDefaultMotionState(t);
|
btDefaultMotionState* motionState = new btDefaultMotionState(t);
|
||||||
|
|
||||||
btScalar bodyMass = rigidbody.mass;
|
btScalar bodyMass = rigidbody.mass;
|
||||||
btVector3 bodyInertia;
|
btVector3 bodyInertia;
|
||||||
|
|
||||||
if(rigidbody.mass != 0)
|
if (rigidbody.mass != 0)
|
||||||
engine->get_scene()->get<Collision>(obj).shape->calculateLocalInertia(bodyMass, bodyInertia);
|
engine->get_scene()->get<Collision>(obj).shape->calculateLocalInertia(bodyMass, bodyInertia);
|
||||||
|
|
||||||
btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(bodyMass, motionState, engine->get_scene()->get<Collision>(obj).shape, bodyInertia);
|
btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(
|
||||||
|
bodyMass, motionState, engine->get_scene()->get<Collision>(obj).shape, bodyInertia);
|
||||||
|
|
||||||
bodyCI.m_friction = rigidbody.friction;
|
bodyCI.m_friction = rigidbody.friction;
|
||||||
|
|
||||||
rigidbody.body = new btRigidBody(bodyCI);
|
rigidbody.body = new btRigidBody(bodyCI);
|
||||||
|
|
||||||
if(!rigidbody.enable_deactivation)
|
if (!rigidbody.enable_deactivation)
|
||||||
rigidbody.body->setActivationState(DISABLE_DEACTIVATION);
|
rigidbody.body->setActivationState(DISABLE_DEACTIVATION);
|
||||||
|
|
||||||
if(!rigidbody.enable_rotation)
|
if (!rigidbody.enable_rotation)
|
||||||
rigidbody.body->setAngularFactor(btVector3(0, 0, 0));
|
rigidbody.body->setAngularFactor(btVector3(0, 0, 0));
|
||||||
|
|
||||||
world->addRigidBody(rigidbody.body);
|
world->addRigidBody(rigidbody.body);
|
||||||
|
@ -76,7 +80,7 @@ void Physics::update(float deltaTime) {
|
||||||
rigidbody.body->setUserIndex(obj);
|
rigidbody.body->setUserIndex(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rigidbody.type == Rigidbody::Type::Dynamic) {
|
if (rigidbody.type == Rigidbody::Type::Dynamic) {
|
||||||
btTransform trans = rigidbody.body->getWorldTransform();
|
btTransform trans = rigidbody.body->getWorldTransform();
|
||||||
transform.position = prism::float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z());
|
transform.position = prism::float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z());
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,7 +88,8 @@ void Physics::update(float deltaTime) {
|
||||||
t.setIdentity();
|
t.setIdentity();
|
||||||
|
|
||||||
t.setOrigin(btVector3(transform.position.x, transform.position.y, transform.position.z));
|
t.setOrigin(btVector3(transform.position.x, transform.position.y, transform.position.z));
|
||||||
t.setRotation(btQuaternion(transform.rotation.x, transform.rotation.y, transform.rotation.z, transform.rotation.w));
|
t.setRotation(
|
||||||
|
btQuaternion(transform.rotation.x, transform.rotation.y, transform.rotation.z, transform.rotation.w));
|
||||||
|
|
||||||
rigidbody.body->setWorldTransform(t);
|
rigidbody.body->setWorldTransform(t);
|
||||||
}
|
}
|
||||||
|
@ -92,11 +97,11 @@ void Physics::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physics::remove_object(prism::Object object) {
|
void Physics::remove_object(prism::Object object) {
|
||||||
if(engine->get_scene()->has<Rigidbody>(object)) {
|
if (engine->get_scene()->has<Rigidbody>(object)) {
|
||||||
for(int i = 0 ; i < world->getNumCollisionObjects(); i++) {
|
for (int i = 0; i < world->getNumCollisionObjects(); i++) {
|
||||||
auto obj = world->getCollisionObjectArray()[i];
|
auto obj = world->getCollisionObjectArray()[i];
|
||||||
|
|
||||||
if(obj->getUserIndex() == object) {
|
if (obj->getUserIndex() == object) {
|
||||||
world->removeCollisionObject(obj);
|
world->removeCollisionObject(obj);
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
|
@ -117,16 +122,16 @@ Physics::RayResult Physics::raycast(prism::float3 from, prism::float3 to) {
|
||||||
int closestCollisionObject = prism::NullObject;
|
int closestCollisionObject = prism::NullObject;
|
||||||
float closestHitFraction = 1000.0f;
|
float closestHitFraction = 1000.0f;
|
||||||
|
|
||||||
for(int i = 0; i < res.m_collisionObjects.size(); i++) {
|
for (int i = 0; i < res.m_collisionObjects.size(); i++) {
|
||||||
if(!engine->get_scene()->get<Collision>(res.m_collisionObjects[i]->getUserIndex()).exclude_from_raycast) {
|
if (!engine->get_scene()->get<Collision>(res.m_collisionObjects[i]->getUserIndex()).exclude_from_raycast) {
|
||||||
if(res.m_hitFractions[i] < closestHitFraction) {
|
if (res.m_hitFractions[i] < closestHitFraction) {
|
||||||
closestCollisionObject = i;
|
closestCollisionObject = i;
|
||||||
closestHitFraction = res.m_hitFractions[i];
|
closestHitFraction = res.m_hitFractions[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(closestCollisionObject != prism::NullObject) {
|
if (closestCollisionObject != prism::NullObject) {
|
||||||
result.hasHit = true;
|
result.hasHit = true;
|
||||||
|
|
||||||
auto vec = res.m_hitPointWorld[closestCollisionObject];
|
auto vec = res.m_hitPointWorld[closestCollisionObject];
|
||||||
|
@ -138,7 +143,7 @@ Physics::RayResult Physics::raycast(prism::float3 from, prism::float3 to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physics::reset() {
|
void Physics::reset() {
|
||||||
if(world != nullptr)
|
if (world != nullptr)
|
||||||
world.reset();
|
world.reset();
|
||||||
|
|
||||||
broadphase = std::make_unique<btDbvtBroadphase>();
|
broadphase = std::make_unique<btDbvtBroadphase>();
|
||||||
|
@ -148,6 +153,7 @@ void Physics::reset() {
|
||||||
|
|
||||||
solver = std::make_unique<btSequentialImpulseConstraintSolver>();
|
solver = std::make_unique<btSequentialImpulseConstraintSolver>();
|
||||||
|
|
||||||
world = std::make_unique<btDiscreteDynamicsWorld>(dispatcher.get(), broadphase.get(), solver.get(), collisionConfiguration.get());
|
world = std::make_unique<btDiscreteDynamicsWorld>(
|
||||||
|
dispatcher.get(), broadphase.get(), solver.get(), collisionConfiguration.get());
|
||||||
world->setGravity(btVector3(0.0f, -9.8f, 0.0f));
|
world->setGravity(btVector3(0.0f, -9.8f, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "scene.hpp"
|
#include "scene.hpp"
|
||||||
|
|
||||||
#include "json_conversions.hpp"
|
|
||||||
#include "file.hpp"
|
|
||||||
#include "engine.hpp"
|
|
||||||
#include "transform.hpp"
|
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "json_conversions.hpp"
|
||||||
|
#include "transform.hpp"
|
||||||
|
|
||||||
void camera_look_at(Scene& scene, prism::Object cam, prism::float3 pos, prism::float3 target) {
|
void camera_look_at(Scene& scene, prism::Object cam, prism::float3 pos, prism::float3 target) {
|
||||||
scene.get<Transform>(cam).position = pos;
|
scene.get<Transform>(cam).position = pos;
|
||||||
|
@ -18,15 +18,15 @@ void load_transform_component(nlohmann::json j, Transform& t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_renderable_component(nlohmann::json j, Renderable& t) {
|
void load_renderable_component(nlohmann::json j, Renderable& t) {
|
||||||
if(j.contains("path"))
|
if (j.contains("path"))
|
||||||
t.mesh = assetm->get<Mesh>(prism::game_domain / j["path"].get<std::string_view>());
|
t.mesh = assetm->get<Mesh>(prism::game_domain / j["path"].get<std::string_view>());
|
||||||
|
|
||||||
for(auto& material : j["materials"])
|
for (auto& material : j["materials"])
|
||||||
t.materials.push_back(assetm->get<Material>(prism::game_domain / material.get<std::string_view>()));
|
t.materials.push_back(assetm->get<Material>(prism::game_domain / material.get<std::string_view>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_camera_component(nlohmann::json j, Camera& camera) {
|
void load_camera_component(nlohmann::json j, Camera& camera) {
|
||||||
if(j.contains("fov"))
|
if (j.contains("fov"))
|
||||||
camera.fov = j["fov"];
|
camera.fov = j["fov"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ void load_light_component(nlohmann::json j, Light& light) {
|
||||||
light.power = j["power"];
|
light.power = j["power"];
|
||||||
light.type = j["type"];
|
light.type = j["type"];
|
||||||
|
|
||||||
if(j.count("size") && !j.count("spot_size"))
|
if (j.count("size") && !j.count("spot_size"))
|
||||||
light.size = j["size"];
|
light.size = j["size"];
|
||||||
else if(j.count("spot_size")) {
|
else if (j.count("spot_size")) {
|
||||||
light.size = j["size"];
|
light.size = j["size"];
|
||||||
light.spot_size = j["spot_size"];
|
light.spot_size = j["spot_size"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(j.count("enable_shadows")) {
|
if (j.count("enable_shadows")) {
|
||||||
light.enable_shadows = j["enable_shadows"];
|
light.enable_shadows = j["enable_shadows"];
|
||||||
light.use_dynamic_shadows = j["use_dynamic_shadows"];
|
light.use_dynamic_shadows = j["use_dynamic_shadows"];
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,10 @@ void load_collision_component(nlohmann::json j, Collision& collision) {
|
||||||
collision.type = j["type"];
|
collision.type = j["type"];
|
||||||
collision.size = j["size"];
|
collision.size = j["size"];
|
||||||
|
|
||||||
if(j.contains("is_trigger")) {
|
if (j.contains("is_trigger")) {
|
||||||
collision.is_trigger = j["is_trigger"];
|
collision.is_trigger = j["is_trigger"];
|
||||||
|
|
||||||
if(collision.is_trigger)
|
if (collision.is_trigger)
|
||||||
collision.trigger_id = j["trigger_id"];
|
collision.trigger_id = j["trigger_id"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,13 @@ void load_rigidbody_component(nlohmann::json j, Rigidbody& rigidbody) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_probe_component(nlohmann::json j, EnvironmentProbe& probe) {
|
void load_probe_component(nlohmann::json j, EnvironmentProbe& probe) {
|
||||||
if(j.contains("size"))
|
if (j.contains("size"))
|
||||||
probe.size = j["size"];
|
probe.size = j["size"];
|
||||||
|
|
||||||
if(j.contains("is_sized"))
|
if (j.contains("is_sized"))
|
||||||
probe.is_sized = j["is_sized"];
|
probe.is_sized = j["is_sized"];
|
||||||
|
|
||||||
if(j.contains("intensity"))
|
if (j.contains("intensity"))
|
||||||
probe.intensity = j["intensity"];
|
probe.intensity = j["intensity"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,22 +84,22 @@ prism::Object load_object(Scene& scene, const nlohmann::json& obj) {
|
||||||
|
|
||||||
load_transform_component(obj["transform"], scene.get<Transform>(o));
|
load_transform_component(obj["transform"], scene.get<Transform>(o));
|
||||||
|
|
||||||
if(obj.contains("renderable"))
|
if (obj.contains("renderable"))
|
||||||
load_renderable_component(obj["renderable"], scene.add<Renderable>(o));
|
load_renderable_component(obj["renderable"], scene.add<Renderable>(o));
|
||||||
|
|
||||||
if(obj.contains("light"))
|
if (obj.contains("light"))
|
||||||
load_light_component(obj["light"], scene.add<Light>(o));
|
load_light_component(obj["light"], scene.add<Light>(o));
|
||||||
|
|
||||||
if(obj.contains("camera"))
|
if (obj.contains("camera"))
|
||||||
load_camera_component(obj["camera"], scene.add<Camera>(o));
|
load_camera_component(obj["camera"], scene.add<Camera>(o));
|
||||||
|
|
||||||
if(obj.contains("collision"))
|
if (obj.contains("collision"))
|
||||||
load_collision_component(obj["collision"], scene.add<Collision>(o));
|
load_collision_component(obj["collision"], scene.add<Collision>(o));
|
||||||
|
|
||||||
if(obj.contains("rigidbody"))
|
if (obj.contains("rigidbody"))
|
||||||
load_rigidbody_component(obj["rigidbody"], scene.add<Rigidbody>(o));
|
load_rigidbody_component(obj["rigidbody"], scene.add<Rigidbody>(o));
|
||||||
|
|
||||||
if(obj.contains("environment_probe"))
|
if (obj.contains("environment_probe"))
|
||||||
load_probe_component(obj["environment_probe"], scene.add<EnvironmentProbe>(o));
|
load_probe_component(obj["environment_probe"], scene.add<EnvironmentProbe>(o));
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
|
@ -111,12 +111,12 @@ void save_transform_component(nlohmann::json& j, const Transform& t) {
|
||||||
j["rotation"] = t.rotation;
|
j["rotation"] = t.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_renderable_component(nlohmann::json& j, const Renderable &mesh) {
|
void save_renderable_component(nlohmann::json& j, const Renderable& mesh) {
|
||||||
if(mesh.mesh)
|
if (mesh.mesh)
|
||||||
j["path"] = mesh.mesh->path;
|
j["path"] = mesh.mesh->path;
|
||||||
|
|
||||||
for(auto& material : mesh.materials) {
|
for (auto& material : mesh.materials) {
|
||||||
if(material)
|
if (material)
|
||||||
j["materials"].push_back(material->path);
|
j["materials"].push_back(material->path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ void save_collision_component(nlohmann::json& j, const Collision& collision) {
|
||||||
j["size"] = collision.size;
|
j["size"] = collision.size;
|
||||||
|
|
||||||
j["is_trigger"] = collision.is_trigger;
|
j["is_trigger"] = collision.is_trigger;
|
||||||
if(collision.is_trigger)
|
if (collision.is_trigger)
|
||||||
j["trigger_id"] = collision.trigger_id;
|
j["trigger_id"] = collision.trigger_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,29 +162,29 @@ nlohmann::json save_object(prism::Object obj) {
|
||||||
|
|
||||||
j["name"] = data.name;
|
j["name"] = data.name;
|
||||||
|
|
||||||
if(data.parent != prism::NullObject)
|
if (data.parent != prism::NullObject)
|
||||||
j["parent"] = engine->get_scene()->get(data.parent).name;
|
j["parent"] = engine->get_scene()->get(data.parent).name;
|
||||||
|
|
||||||
save_transform_component(j["transform"], engine->get_scene()->get<Transform>(obj));
|
save_transform_component(j["transform"], engine->get_scene()->get<Transform>(obj));
|
||||||
|
|
||||||
auto scene = engine->get_scene();
|
auto scene = engine->get_scene();
|
||||||
|
|
||||||
if(scene->has<Renderable>(obj))
|
if (scene->has<Renderable>(obj))
|
||||||
save_renderable_component(j["renderable"], scene->get<Renderable>(obj));
|
save_renderable_component(j["renderable"], scene->get<Renderable>(obj));
|
||||||
|
|
||||||
if(scene->has<Light>(obj))
|
if (scene->has<Light>(obj))
|
||||||
save_light_component(j["light"], scene->get<Light>(obj));
|
save_light_component(j["light"], scene->get<Light>(obj));
|
||||||
|
|
||||||
if(scene->has<Camera>(obj))
|
if (scene->has<Camera>(obj))
|
||||||
save_camera_component(j["camera"], scene->get<Camera>(obj));
|
save_camera_component(j["camera"], scene->get<Camera>(obj));
|
||||||
|
|
||||||
if(scene->has<Collision>(obj))
|
if (scene->has<Collision>(obj))
|
||||||
save_collision_component(j["collision"], scene->get<Collision>(obj));
|
save_collision_component(j["collision"], scene->get<Collision>(obj));
|
||||||
|
|
||||||
if(scene->has<Rigidbody>(obj))
|
if (scene->has<Rigidbody>(obj))
|
||||||
save_rigidbody_component(j["rigidbody"], scene->get<Rigidbody>(obj));
|
save_rigidbody_component(j["rigidbody"], scene->get<Rigidbody>(obj));
|
||||||
|
|
||||||
if(scene->has<EnvironmentProbe>(obj))
|
if (scene->has<EnvironmentProbe>(obj))
|
||||||
save_probe_component(j["environment_probe"], scene->get<EnvironmentProbe>(obj));
|
save_probe_component(j["environment_probe"], scene->get<EnvironmentProbe>(obj));
|
||||||
|
|
||||||
return j;
|
return j;
|
||||||
|
|
Reference in a new issue