2020-08-11 12:07:21 -04:00
|
|
|
#include "engine.hpp"
|
|
|
|
|
|
|
|
#include <nlohmann/json.hpp>
|
2021-04-19 12:35:52 -04:00
|
|
|
#include <utility>
|
2020-09-22 22:52:39 -04:00
|
|
|
#include <imgui.h>
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "scene.hpp"
|
|
|
|
#include "console.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
#include "log.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "asset.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
#include "json_conversions.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "app.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
#include "assertions.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "renderer.hpp"
|
|
|
|
#include "gfx.hpp"
|
2021-04-20 10:37:56 -04:00
|
|
|
#include "imgui_backend.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "debug.hpp"
|
|
|
|
#include "timer.hpp"
|
|
|
|
#include "physics.hpp"
|
|
|
|
#include "input.hpp"
|
|
|
|
|
|
|
|
// TODO: remove these in the future
|
|
|
|
#include "shadowpass.hpp"
|
|
|
|
#include "scenecapture.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
using prism::engine;
|
2021-04-19 12:06:44 -04:00
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
engine::engine(const int argc, char* argv[]) {
|
2021-09-13 23:41:54 -04:00
|
|
|
log("Prism Engine loading...");
|
2021-10-12 10:22:38 -04:00
|
|
|
|
2022-02-21 11:03:34 -05:00
|
|
|
log("starting gfx debug:");
|
|
|
|
|
|
|
|
for(auto [t, t_name] : magic_enum::enum_entries<GFXContext>()) {
|
|
|
|
log("does platform support {}? {}", t_name, platform::supports_context(t));
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:38 -04:00
|
|
|
console::register_command("echo", console::argument_format(1), [](const console::arguments& args) {
|
|
|
|
log(std::get<std::string>(args[0].data));
|
|
|
|
});
|
2021-10-12 10:27:03 -04:00
|
|
|
|
2021-10-12 10:22:38 -04:00
|
|
|
console::register_command("platform_info", console::argument_format(0), [this](const console::arguments&) {
|
|
|
|
log("Platform: {}", platform::get_name());
|
|
|
|
log("GFX: {}", gfx->get_name());
|
2020-09-20 22:37:15 -04:00
|
|
|
});
|
2022-02-21 17:17:55 -05:00
|
|
|
|
|
|
|
console::register_variable("rs_exposure", render_options.exposure);
|
|
|
|
console::register_variable("rs_dof", render_options.enable_depth_of_field);
|
2020-09-22 22:43:30 -04:00
|
|
|
console::register_variable("rs_dynamic_resolution", render_options.dynamic_resolution);
|
2022-02-21 17:17:55 -05:00
|
|
|
console::register_variable("rs_render_scale", render_options.render_scale);
|
|
|
|
console::register_variable("rs_shadow_resolution", render_options.shadow_resolution);
|
|
|
|
console::register_variable("rs_aa", render_options.enable_aa);
|
|
|
|
console::register_variable("rs_ibl", render_options.enable_ibl);
|
|
|
|
console::register_variable("rs_normal_mapping", render_options.enable_normal_mapping);
|
|
|
|
console::register_variable("rs_normal_shadowing", render_options.enable_normal_shadowing);
|
|
|
|
console::register_variable("rs_point_shadows", render_options.enable_point_shadows);
|
|
|
|
console::register_variable("rs_extra_passes", render_options.enable_extra_passes);
|
|
|
|
console::register_variable("rs_frustum_culling", render_options.enable_frustum_culling);
|
|
|
|
|
|
|
|
console::register_command("rebuild_mat", console::argument_format(0), [this](const console::arguments&) {
|
|
|
|
for(auto material : assetm->get_all<Material>()) {
|
|
|
|
material->capture_pipeline = nullptr;
|
|
|
|
material->skinned_pipeline = nullptr;
|
|
|
|
material->static_pipeline = nullptr;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-20 11:23:53 -04:00
|
|
|
console::register_command("quit", console::argument_format(0), [this](const console::arguments&) {
|
2020-09-22 13:28:08 -04:00
|
|
|
quit();
|
|
|
|
});
|
2022-02-21 17:37:10 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
for(int i = 0; i < argc; i++)
|
2021-04-19 12:35:52 -04:00
|
|
|
command_line_arguments.emplace_back(argv[i]);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-20 11:53:38 -04:00
|
|
|
input = std::make_unique<input_system>();
|
2021-04-19 12:29:49 -04:00
|
|
|
physics = std::make_unique<Physics>();
|
2021-04-20 10:37:56 -04:00
|
|
|
imgui = std::make_unique<prism::imgui_backend>();
|
2020-08-11 12:07:21 -04:00
|
|
|
assetm = std::make_unique<AssetManager>();
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:35:52 -04:00
|
|
|
engine::~engine() = default;
|
2020-09-21 09:37:52 -04:00
|
|
|
|
2021-04-19 12:35:52 -04:00
|
|
|
void engine::set_app(prism::app* p_app) {
|
|
|
|
Expects(p_app != nullptr);
|
2021-04-19 12:29:49 -04:00
|
|
|
|
2021-10-12 10:27:03 -04:00
|
|
|
this->current_app = p_app;
|
2021-10-12 11:47:13 -04:00
|
|
|
|
2022-03-04 19:17:07 -05:00
|
|
|
if(platform::supports_feature(PlatformFeature::Windowing) && get_app()->is_multimodal()) {
|
2021-10-12 11:47:13 -04:00
|
|
|
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
|
|
|
}
|
2022-02-22 09:34:00 -05:00
|
|
|
|
|
|
|
console::load_cfg(prism::app_domain / "render_options.cfg");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
prism::app* engine::get_app() const {
|
2021-10-12 10:27:03 -04:00
|
|
|
return current_app;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::pause() {
|
2021-04-19 12:29:49 -04:00
|
|
|
paused = true;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::unpause() {
|
2021-04-19 12:29:49 -04:00
|
|
|
paused = false;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
bool engine::is_paused() const {
|
2021-04-19 12:29:49 -04:00
|
|
|
return paused;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::quit() {
|
2021-04-20 12:17:49 -04:00
|
|
|
if(!windows.empty())
|
|
|
|
windows[0]->quit_requested = true;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
bool engine::is_quitting() const {
|
2021-04-20 12:17:49 -04:00
|
|
|
if(!windows.empty())
|
|
|
|
return windows[0]->quit_requested;
|
2021-09-13 22:53:42 -04:00
|
|
|
|
|
|
|
return false;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::prepare_quit() {
|
2021-10-12 10:27:03 -04:00
|
|
|
current_app->prepare_quit();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:35:52 -04:00
|
|
|
void engine::set_gfx(GFX* p_gfx) {
|
|
|
|
Expects(p_gfx != nullptr);
|
|
|
|
|
2022-02-21 11:03:34 -05:00
|
|
|
prism::log("this gfx has a context of {}", utility::enum_to_string(p_gfx->required_context()));
|
|
|
|
|
2021-04-19 12:35:52 -04:00
|
|
|
this->gfx = p_gfx;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
GFX* engine::get_gfx() {
|
2021-04-19 12:29:49 -04:00
|
|
|
return gfx;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-20 11:53:38 -04:00
|
|
|
prism::input_system* engine::get_input() {
|
2021-04-19 12:29:49 -04:00
|
|
|
return input.get();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-20 13:53:38 -04:00
|
|
|
prism::renderer* engine::get_renderer() {
|
2021-10-12 10:27:03 -04:00
|
|
|
return current_renderer.get();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
Physics* engine::get_physics() {
|
2021-04-19 12:29:49 -04:00
|
|
|
return physics.get();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::create_empty_scene() {
|
2020-08-11 12:07:21 -04:00
|
|
|
auto scene = std::make_unique<Scene>();
|
|
|
|
|
|
|
|
setup_scene(*scene);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
scenes.push_back(std::move(scene));
|
|
|
|
current_scene = scenes.back().get();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-05-12 09:05:56 -04:00
|
|
|
Scene* engine::load_scene(const prism::path& path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
2021-05-12 08:50:02 -04:00
|
|
|
auto file = prism::open_file(path);
|
2020-08-11 12:07:21 -04:00
|
|
|
if(!file.has_value()) {
|
2021-09-13 23:41:54 -04:00
|
|
|
prism::log("Failed to load scene from {}!", path.string());
|
2020-08-11 12:07:21 -04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
file->read_as_stream() >> j;
|
|
|
|
|
|
|
|
auto scene = std::make_unique<Scene>();
|
|
|
|
|
|
|
|
std::map<Object, std::string> parentQueue;
|
|
|
|
|
|
|
|
for(auto& obj : j["objects"]) {
|
|
|
|
if(obj.contains("prefabPath")) {
|
2021-05-12 08:50:02 -04:00
|
|
|
Object o = add_prefab(*scene, prism::app_domain / obj["prefabPath"].get<std::string_view>());
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
scene->get(o).name = obj["name"];
|
|
|
|
|
|
|
|
auto& transform = scene->get<Transform>(o);
|
|
|
|
transform.position = obj["position"];
|
|
|
|
transform.rotation = obj["rotation"];
|
|
|
|
transform.scale = obj["scale"];
|
|
|
|
} else {
|
2021-04-19 12:35:52 -04:00
|
|
|
auto o = load_object(*scene, obj);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
if(obj.contains("parent"))
|
|
|
|
parentQueue[o] = obj["parent"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto& [obj, toParent] : parentQueue)
|
|
|
|
scene->get<Data>(obj).parent = scene->find_object(toParent);
|
|
|
|
|
|
|
|
setup_scene(*scene);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
scenes.push_back(std::move(scene));
|
|
|
|
current_scene = scenes.back().get();
|
|
|
|
path_to_scene[path.string()] = scenes.back().get();
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
return scenes.back().get();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::save_scene(const std::string_view path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& obj : current_scene->get_objects()) {
|
|
|
|
if(!current_scene->get(obj).editor_object)
|
2020-08-11 12:07:21 -04:00
|
|
|
j["objects"].push_back(save_object(obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ofstream out(path.data());
|
|
|
|
out << j;
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
AnimationChannel engine::load_animation(nlohmann::json a) {
|
2020-08-11 12:07:21 -04:00
|
|
|
AnimationChannel animation;
|
|
|
|
|
|
|
|
for(auto& kf : a["frames"]) {
|
|
|
|
PositionKeyFrame keyframe;
|
|
|
|
keyframe.time = kf["time"];
|
|
|
|
keyframe.value = kf["value"];
|
|
|
|
|
|
|
|
animation.positions.push_back(keyframe);
|
|
|
|
}
|
|
|
|
|
|
|
|
return animation;
|
|
|
|
}
|
|
|
|
|
2021-05-12 09:05:56 -04:00
|
|
|
Animation engine::load_animation(const prism::path& path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
2021-05-12 08:50:02 -04:00
|
|
|
auto file = prism::open_file(path, true);
|
2020-08-11 12:07:21 -04:00
|
|
|
if(!file.has_value()) {
|
2021-09-13 23:41:54 -04:00
|
|
|
prism::log("Failed to load animation from {}!", path.string());
|
2020-08-11 12:07:21 -04:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
Animation anim;
|
|
|
|
|
|
|
|
file->read(&anim.duration);
|
|
|
|
file->read(&anim.ticks_per_second);
|
|
|
|
|
|
|
|
unsigned int num_channels;
|
|
|
|
file->read(&num_channels);
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < num_channels; i++) {
|
|
|
|
AnimationChannel channel;
|
|
|
|
|
|
|
|
file->read_string(channel.id);
|
|
|
|
|
|
|
|
unsigned int num_positions;
|
|
|
|
file->read(&num_positions);
|
|
|
|
|
|
|
|
for(unsigned int j = 0; j < num_positions; j++) {
|
|
|
|
PositionKeyFrame key;
|
|
|
|
file->read(&key);
|
|
|
|
|
|
|
|
channel.positions.push_back(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int num_rotations;
|
|
|
|
file->read(&num_rotations);
|
|
|
|
|
|
|
|
for(unsigned int j = 0; j < num_rotations; j++) {
|
|
|
|
RotationKeyFrame key;
|
|
|
|
file->read(&key);
|
|
|
|
|
|
|
|
channel.rotations.push_back(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int num_scales;
|
|
|
|
file->read(&num_scales);
|
|
|
|
|
|
|
|
for(unsigned int j = 0; j < num_scales; j++) {
|
|
|
|
ScaleKeyFrame key;
|
|
|
|
file->read(&key);
|
|
|
|
|
|
|
|
channel.scales.push_back(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
anim.channels.push_back(channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return anim;
|
|
|
|
}
|
|
|
|
|
2021-05-12 09:05:56 -04:00
|
|
|
void engine::load_cutscene(const prism::path& path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
|
|
|
cutscene = std::make_unique<Cutscene>();
|
|
|
|
|
2021-05-12 08:50:02 -04:00
|
|
|
auto file = prism::open_file(path);
|
2020-08-11 12:07:21 -04:00
|
|
|
if(!file.has_value()) {
|
2021-09-13 23:41:54 -04:00
|
|
|
prism::log("Failed to load cutscene from {}!", path.string());
|
2020-08-11 12:07:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
file->read_as_stream() >> j;
|
|
|
|
|
|
|
|
for(auto& s : j["shots"]) {
|
|
|
|
Shot shot;
|
|
|
|
shot.begin = s["begin"];
|
|
|
|
shot.length = s["end"];
|
|
|
|
|
|
|
|
for(auto& animation : s["animations"]) {
|
|
|
|
shot.channels.push_back(load_animation(animation));
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
if(path_to_scene.count(s["scene"])) {
|
|
|
|
shot.scene = path_to_scene[s["scene"]];
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
// try to find main camera
|
|
|
|
auto [obj, cam] = shot.scene->get_all<Camera>()[0];
|
|
|
|
|
|
|
|
for(auto& anim : shot.channels) {
|
|
|
|
if(anim.target == NullObject)
|
|
|
|
anim.target = obj;
|
|
|
|
}
|
|
|
|
} else {
|
2021-05-12 08:50:02 -04:00
|
|
|
load_scene(prism::root_path(path) / s["scene"].get<std::string_view>());
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
if(get_scene() == nullptr)
|
|
|
|
create_empty_scene();
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
auto cameraObj = get_scene()->add_object();
|
|
|
|
get_scene()->add<Camera>(cameraObj);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
for(auto& anim : shot.channels) {
|
|
|
|
if(anim.target == NullObject)
|
|
|
|
anim.target = cameraObj;
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
path_to_scene[s["scene"]] = current_scene;
|
|
|
|
shot.scene = current_scene;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
cutscene->shots.push_back(shot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::save_cutscene(const std::string_view path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
for(auto& shot : cutscene->shots) {
|
2020-08-11 12:07:21 -04:00
|
|
|
nlohmann::json s;
|
|
|
|
s["begin"] = shot.begin;
|
|
|
|
s["end"] = shot.length;
|
|
|
|
|
2021-10-14 08:51:58 -04:00
|
|
|
for(auto& [scene_path, scene] : path_to_scene) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(shot.scene == scene)
|
2021-10-14 08:51:58 -04:00
|
|
|
s["scene"] = scene_path;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
j["shots"].push_back(s);
|
|
|
|
}
|
|
|
|
|
2021-02-15 15:06:13 -05:00
|
|
|
std::ofstream out(path.data());
|
2020-08-11 12:07:21 -04:00
|
|
|
out << j;
|
|
|
|
}
|
|
|
|
|
2022-02-15 11:25:13 -05:00
|
|
|
prism::Object engine::add_prefab(Scene& scene, const prism::path& path, const std::string_view override_name) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!path.empty());
|
|
|
|
|
2021-05-12 08:50:02 -04:00
|
|
|
auto file = prism::open_file(path);
|
2020-08-11 12:07:21 -04:00
|
|
|
if(!file.has_value()) {
|
2021-09-13 23:41:54 -04:00
|
|
|
prism::log("Failed to load prefab from {}!", path.string());
|
2020-08-11 12:07:21 -04:00
|
|
|
return NullObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
file->read_as_stream() >> j;
|
|
|
|
|
|
|
|
Object root_node = NullObject;
|
|
|
|
|
|
|
|
std::map<Object, std::string> parent_queue;
|
|
|
|
|
2021-10-14 08:51:58 -04:00
|
|
|
for(const auto& obj : j["objects"]) {
|
2020-08-11 12:07:21 -04:00
|
|
|
auto o = load_object(scene, obj);
|
|
|
|
|
|
|
|
if(obj.contains("parent")) {
|
|
|
|
parent_queue[o] = obj["parent"];
|
|
|
|
} else {
|
|
|
|
root_node = o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto& [obj, parent_name] : parent_queue)
|
|
|
|
scene.get(obj).parent = scene.find_object(parent_name);
|
|
|
|
|
|
|
|
if(!override_name.empty() && root_node != NullObject)
|
|
|
|
scene.get(root_node).name = override_name;
|
|
|
|
|
|
|
|
return root_node;
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::save_prefab(const Object root, const std::string_view path) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(root != NullObject);
|
|
|
|
Expects(!path.empty());
|
|
|
|
|
|
|
|
nlohmann::json j;
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& obj : current_scene->get_objects()) {
|
|
|
|
if(!current_scene->get(obj).editor_object)
|
2020-08-11 12:07:21 -04:00
|
|
|
j["objects"].push_back(save_object(obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ofstream out(path.data());
|
|
|
|
out << j;
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
void engine::add_window(void* native_handle, const platform::window_ptr window_ptr, const prism::Extent extent) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(native_handle != nullptr);
|
2021-10-12 10:22:16 -04:00
|
|
|
|
|
|
|
auto* window = new Window();
|
|
|
|
windows.push_back(window);
|
|
|
|
|
|
|
|
window->identifier = window_ptr;
|
|
|
|
|
|
|
|
if(platform::is_main_window(window_ptr)) {
|
2021-10-12 10:27:03 -04:00
|
|
|
current_renderer = std::make_unique<prism::renderer>(gfx);
|
2021-10-12 10:22:16 -04:00
|
|
|
|
|
|
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
2022-03-04 19:17:07 -05:00
|
|
|
main_viewport->PlatformHandle = get_main_window();
|
2021-02-16 19:22:32 -05:00
|
|
|
}
|
2021-10-12 10:27:03 -04:00
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
const auto drawable_extent = platform::get_window_drawable_size(window_ptr);
|
2021-10-12 10:27:03 -04:00
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
gfx->initialize_view(native_handle, window_ptr, drawable_extent.width, drawable_extent.height);
|
|
|
|
|
2021-02-17 01:09:12 -05:00
|
|
|
window->extent = extent;
|
2021-10-12 10:27:03 -04:00
|
|
|
window->render_target = current_renderer->allocate_render_target(drawable_extent);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
render_ready = true;
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
void engine::remove_window(const platform::window_ptr identifier) {
|
2021-04-19 12:29:49 -04:00
|
|
|
utility::erase_if(windows, [identifier](Window*& w) {
|
2021-02-17 01:09:12 -05:00
|
|
|
return w->identifier == identifier;
|
2020-08-11 12:07:21 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
void engine::resize(const platform::window_ptr identifier, const prism::Extent extent) {
|
2020-08-11 12:07:21 -04:00
|
|
|
auto window = get_window(identifier);
|
2021-02-04 08:21:40 -05:00
|
|
|
if (window == nullptr)
|
|
|
|
return;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
window->extent = extent;
|
|
|
|
|
|
|
|
const auto drawable_extent = platform::get_window_drawable_size(identifier);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
gfx->recreate_view(identifier, drawable_extent.width, drawable_extent.height);
|
2021-10-12 10:27:03 -04:00
|
|
|
current_renderer->resize_render_target(*window->render_target, drawable_extent);
|
2021-10-12 11:06:59 -04:00
|
|
|
|
|
|
|
imgui->process_resize(identifier);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
void engine::move(const platform::window_ptr identifier) {
|
|
|
|
imgui->process_move(identifier);
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::process_key_down(const unsigned int keyCode) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(keyCode >= 0);
|
2021-10-07 17:46:28 -04:00
|
|
|
|
|
|
|
if(input->is_text_input() && !input->get_allowable_text_button(keyCode))
|
|
|
|
return;
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
imgui->process_key_down(keyCode);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-09-22 22:52:39 -04:00
|
|
|
if(keyCode == platform::get_keycode(debug_button) && !ImGui::GetIO().WantTextInput)
|
2020-08-11 12:07:21 -04:00
|
|
|
debug_enabled = !debug_enabled;
|
2021-10-07 17:46:28 -04:00
|
|
|
|
|
|
|
if(keyCode == platform::get_keycode(InputButton::C))
|
|
|
|
console_enabled = !console_enabled;
|
2022-02-15 09:01:52 -05:00
|
|
|
|
|
|
|
if(keyCode == platform::get_keycode(InputButton::Backspace))
|
|
|
|
ui_enabled = !ui_enabled;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::process_key_up(const unsigned int keyCode) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(keyCode >= 0);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
imgui->process_key_up(keyCode);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-10-14 08:51:58 -04:00
|
|
|
void engine::process_mouse_down(const int button, const prism::Offset) {
|
2021-05-11 17:05:29 -04:00
|
|
|
imgui->process_mouse_down(button);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::calculate_bone(Mesh& mesh, const Mesh::Part& part, Bone& bone, const Bone* parent_bone) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(part.offset_matrices.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Matrix4x4 parent_matrix;
|
|
|
|
if(parent_bone != nullptr)
|
|
|
|
parent_matrix = parent_bone->local_transform;
|
|
|
|
|
2021-05-12 09:56:44 -04:00
|
|
|
Matrix4x4 local = prism::translate(Matrix4x4(), bone.position);
|
2020-08-11 12:07:21 -04:00
|
|
|
local *= matrix_from_quat(bone.rotation);
|
2021-05-12 09:56:44 -04:00
|
|
|
local = prism::scale(local, bone.scale);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
bone.local_transform = parent_matrix * local;
|
|
|
|
|
|
|
|
bone.final_transform = mesh.global_inverse_transformation * bone.local_transform * part.offset_matrices[bone.index];
|
|
|
|
|
|
|
|
for(auto& b : mesh.bones) {
|
|
|
|
if(b.parent != nullptr && b.parent->index == bone.index)
|
|
|
|
calculate_bone(mesh, part, b, &bone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::calculate_object(Scene& scene, Object object, const Object parent_object) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Matrix4x4 parent_matrix;
|
|
|
|
if(parent_object != NullObject)
|
|
|
|
parent_matrix = scene.get<Transform>(parent_object).model;
|
|
|
|
|
|
|
|
auto& transform = scene.get<Transform>(object);
|
|
|
|
|
2021-05-12 09:56:44 -04:00
|
|
|
Matrix4x4 local = prism::translate(Matrix4x4(), transform.position);
|
2020-08-11 12:07:21 -04:00
|
|
|
local *= matrix_from_quat(transform.rotation);
|
2021-05-12 09:56:44 -04:00
|
|
|
local = prism::scale(local, transform.scale);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
transform.model = parent_matrix * local;
|
|
|
|
|
|
|
|
if(scene.has<Renderable>(object)) {
|
|
|
|
auto& mesh = scene.get<Renderable>(object);
|
|
|
|
|
|
|
|
if(mesh.mesh && !mesh.mesh->bones.empty()) {
|
2020-08-11 16:21:42 -04:00
|
|
|
if(mesh.temp_bone_data.empty())
|
|
|
|
mesh.temp_bone_data.resize(mesh.mesh->bones.size());
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
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()) {
|
|
|
|
for(auto [i, ourBone] : utility::enumerate(mesh.mesh->bones)) {
|
|
|
|
for(auto& theirBone : scene.get<Renderable>(scene.get(object).parent).mesh->bones) {
|
|
|
|
if(ourBone.name == theirBone.name)
|
2020-08-11 16:21:42 -04:00
|
|
|
mesh.temp_bone_data[i] = mesh.mesh->global_inverse_transformation * theirBone.local_transform * part.offset_matrices[ourBone.index];
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
calculate_bone(*mesh.mesh.handle, part, *mesh.mesh->root_bone);
|
|
|
|
|
2020-08-11 16:21:42 -04:00
|
|
|
for(auto [i, bone] : utility::enumerate(mesh.temp_bone_data))
|
|
|
|
mesh.temp_bone_data[i] = mesh.mesh->bones[i].final_transform;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
gfx->copy_buffer(part.bone_batrix_buffer, mesh.temp_bone_data.data(), 0, mesh.temp_bone_data.size() * sizeof(Matrix4x4));
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto& child : scene.children_of(object))
|
|
|
|
calculate_object(scene, child, object);
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:35:52 -04:00
|
|
|
Shot* engine::get_shot(const float time) const {
|
2021-04-19 12:23:18 -04:00
|
|
|
for(auto& shot : cutscene->shots) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(time >= shot.begin && time <= (shot.begin + shot.length))
|
|
|
|
return &shot;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::update_animation_channel(Scene& scene, const AnimationChannel& channel, const float time) {
|
2020-08-11 12:07:21 -04:00
|
|
|
{
|
|
|
|
int keyframeIndex = -1;
|
|
|
|
int i = 0;
|
|
|
|
for(auto& frame : channel.positions) {
|
|
|
|
if(time >= frame.time)
|
|
|
|
keyframeIndex = i;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(keyframeIndex != -1) {
|
2021-05-12 09:56:44 -04:00
|
|
|
prism::float3* targetVec = nullptr;
|
2020-08-11 12:07:21 -04:00
|
|
|
if(channel.bone != nullptr)
|
|
|
|
targetVec = &channel.bone->position;
|
|
|
|
|
|
|
|
if(channel.target != NullObject && scene.has<Data>(channel.target))
|
|
|
|
targetVec = &scene.get<Transform>(channel.target).position;
|
|
|
|
|
|
|
|
auto& startFrame = channel.positions[keyframeIndex];
|
|
|
|
|
|
|
|
int endFrameIndex = keyframeIndex + 1;
|
|
|
|
if(endFrameIndex > channel.positions.size() - 1) {
|
|
|
|
if(targetVec != nullptr)
|
|
|
|
*targetVec = startFrame.value;
|
|
|
|
} else {
|
|
|
|
auto& endFrame = channel.positions[endFrameIndex];
|
|
|
|
|
|
|
|
if(targetVec != nullptr)
|
|
|
|
*targetVec = lerp(startFrame.value, endFrame.value, (float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int keyframeIndex = -1;
|
|
|
|
int i = 0;
|
|
|
|
for(auto& frame : channel.rotations) {
|
|
|
|
if(time >= frame.time)
|
|
|
|
keyframeIndex = i;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(keyframeIndex != -1) {
|
|
|
|
Quaternion* targetVec = nullptr;
|
|
|
|
if(channel.bone != nullptr)
|
|
|
|
targetVec = &channel.bone->rotation;
|
|
|
|
|
|
|
|
auto& startFrame = channel.rotations[keyframeIndex];
|
|
|
|
|
|
|
|
int endFrameIndex = keyframeIndex + 1;
|
|
|
|
if(endFrameIndex > channel.rotations.size() - 1) {
|
|
|
|
if(targetVec != nullptr)
|
|
|
|
*targetVec = startFrame.value;
|
|
|
|
} else {
|
|
|
|
auto& endFrame = channel.rotations[endFrameIndex];
|
|
|
|
|
|
|
|
if(targetVec != nullptr)
|
|
|
|
*targetVec = lerp(startFrame.value, endFrame.value, (float)(time - startFrame.time) / (float)(endFrame.time - startFrame.time));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::update_cutscene(const float time) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Shot* currentShot = get_shot(time);
|
|
|
|
if(currentShot != nullptr) {
|
2021-04-19 12:29:49 -04:00
|
|
|
current_scene = currentShot->scene;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
for(auto& channel : currentShot->channels)
|
2021-04-19 12:29:49 -04:00
|
|
|
update_animation_channel(*current_scene, channel, time);
|
2020-08-11 12:07:21 -04:00
|
|
|
} else {
|
2021-04-19 12:29:49 -04:00
|
|
|
current_scene = nullptr;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::update_animation(const Animation& anim, const float time) {
|
2020-08-11 12:07:21 -04:00
|
|
|
for(const auto& channel : anim.channels)
|
2021-04-19 12:29:49 -04:00
|
|
|
update_animation_channel(*current_scene, channel, time);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::begin_frame(const float delta_time) {
|
2021-04-19 12:29:49 -04:00
|
|
|
imgui->begin_frame(delta_time);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2022-02-15 09:01:52 -05:00
|
|
|
if(ui_enabled) {
|
|
|
|
if (debug_enabled)
|
|
|
|
draw_debug_ui();
|
|
|
|
|
|
|
|
if (console_enabled)
|
|
|
|
draw_console();
|
|
|
|
}
|
2021-10-07 17:46:28 -04:00
|
|
|
|
2021-10-12 10:27:03 -04:00
|
|
|
if(current_app != nullptr)
|
|
|
|
current_app->begin_frame();
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::end_frame() {
|
2021-02-17 01:09:12 -05:00
|
|
|
ImGui::UpdatePlatformWindows();
|
|
|
|
}
|
|
|
|
|
2020-09-22 22:10:02 -04:00
|
|
|
int frame_delay = 0;
|
|
|
|
const int frame_delay_between_resolution_change = 60;
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::update(const float delta_time) {
|
2020-08-11 12:07:21 -04:00
|
|
|
const float ideal_delta_time = 0.01667f;
|
|
|
|
|
|
|
|
if(render_options.dynamic_resolution) {
|
2020-09-22 22:10:02 -04:00
|
|
|
frame_delay++;
|
|
|
|
|
|
|
|
if(frame_delay >= frame_delay_between_resolution_change) {
|
|
|
|
if(delta_time > ideal_delta_time) {
|
|
|
|
render_options.render_scale -= 0.1f;
|
|
|
|
|
|
|
|
render_options.render_scale = std::fmax(render_options.render_scale, 0.1f);
|
|
|
|
} else {
|
|
|
|
render_options.render_scale += 0.1f;
|
|
|
|
|
|
|
|
render_options.render_scale = std::fmin(render_options.render_scale, 1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
frame_delay = 0;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& timer : timers) {
|
|
|
|
if(!paused || (paused && timer->continue_during_pause))
|
2020-08-11 12:07:21 -04:00
|
|
|
timer->current_time += delta_time;
|
|
|
|
|
|
|
|
if(timer->current_time >= timer->duration) {
|
|
|
|
timer->callback();
|
|
|
|
|
|
|
|
timer->current_time = 0.0f;
|
|
|
|
|
|
|
|
if(timer->remove_on_trigger)
|
2021-04-19 12:29:49 -04:00
|
|
|
timers_to_remove.push_back(timer);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& timer : timers_to_remove)
|
|
|
|
utility::erase(timers, timer);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
timers_to_remove.clear();
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
input->update();
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-10-12 10:27:03 -04:00
|
|
|
current_app->update(delta_time);
|
|
|
|
|
|
|
|
if(cutscene != nullptr && play_cutscene && !paused) {
|
|
|
|
update_cutscene(current_cutscene_time);
|
|
|
|
|
|
|
|
current_cutscene_time += delta_time;
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
if(current_scene != nullptr) {
|
|
|
|
if(update_physics && !paused)
|
|
|
|
physics->update(delta_time);
|
2021-10-12 10:27:03 -04:00
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& target : animation_targets) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if((target.current_time * target.animation.ticks_per_second) > target.animation.duration) {
|
|
|
|
if(target.looping) {
|
|
|
|
target.current_time = 0.0f;
|
|
|
|
} else {
|
2021-04-19 12:29:49 -04:00
|
|
|
utility::erase(animation_targets, target);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
update_animation(target.animation, target.current_time * target.animation.ticks_per_second);
|
|
|
|
|
|
|
|
target.current_time += delta_time * target.animation_speed_modifier;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
update_scene(*current_scene);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
assetm->perform_cleanup();
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::update_scene(Scene& scene) {
|
2020-08-11 12:07:21 -04:00
|
|
|
for(auto& obj : scene.get_objects()) {
|
|
|
|
if(scene.get(obj).parent == NullObject)
|
|
|
|
calculate_object(scene, obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
void engine::render(const platform::window_ptr index) {
|
2020-08-11 12:07:21 -04:00
|
|
|
auto window = get_window(index);
|
|
|
|
if(window == nullptr)
|
|
|
|
return;
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
GFXCommandBuffer* commandbuffer = gfx->acquire_command_buffer(true);
|
2021-02-17 01:32:46 -05:00
|
|
|
|
2021-10-12 10:22:16 -04:00
|
|
|
if(platform::is_main_window(index)) {
|
|
|
|
imgui->render();
|
2021-02-17 01:32:46 -05:00
|
|
|
|
2021-10-12 10:27:03 -04:00
|
|
|
current_app->render(commandbuffer);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-10-12 10:27:03 -04:00
|
|
|
if(current_renderer != nullptr)
|
|
|
|
current_renderer->render(commandbuffer, current_app->wants_no_scene_rendering() ? nullptr : current_scene, *window->render_target, index);
|
2021-02-05 19:35:13 -05:00
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
gfx->submit(commandbuffer, index);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::add_timer(Timer& timer) {
|
2021-04-19 12:29:49 -04:00
|
|
|
timers.push_back(&timer);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
Scene* engine::get_scene() {
|
2021-04-19 12:29:49 -04:00
|
|
|
return current_scene;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
Scene* engine::get_scene(const std::string_view name) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(!name.empty());
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
return path_to_scene[name.data()];
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::set_current_scene(Scene* scene) {
|
2021-04-19 12:29:49 -04:00
|
|
|
current_scene = scene;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
std::string_view engine::get_scene_path() const {
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& [path, scene] : path_to_scene) {
|
|
|
|
if(scene == this->current_scene)
|
2020-08-11 12:07:21 -04:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::on_remove(Object object) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(object != NullObject);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
physics->remove_object(object);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::play_animation(Animation animation, Object object, bool looping) {
|
2020-08-11 12:07:21 -04:00
|
|
|
Expects(object != NullObject);
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
if(!current_scene->has<Renderable>(object))
|
2020-08-11 12:07:21 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
AnimationTarget target;
|
2021-04-19 12:35:52 -04:00
|
|
|
target.animation = std::move(animation);
|
2020-08-11 12:07:21 -04:00
|
|
|
target.target = object;
|
|
|
|
target.looping = looping;
|
|
|
|
|
|
|
|
for(auto& channel : target.animation.channels) {
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& bone : current_scene->get<Renderable>(object).mesh->bones) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(channel.id == bone.name)
|
|
|
|
channel.bone = &bone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:29:49 -04:00
|
|
|
animation_targets.push_back(target);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::set_animation_speed_modifier(Object target, float modifier) {
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& animation : animation_targets) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(animation.target == target)
|
|
|
|
animation.animation_speed_modifier = modifier;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::stop_animation(Object target) {
|
2021-04-19 12:29:49 -04:00
|
|
|
for(auto& animation : animation_targets) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(animation.target == target)
|
2021-04-19 12:29:49 -04:00
|
|
|
utility::erase(animation_targets, animation);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:23:18 -04:00
|
|
|
void engine::setup_scene(Scene& scene) {
|
2021-04-19 12:29:49 -04:00
|
|
|
physics->reset();
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
scene.on_remove = [this](Object obj) {
|
|
|
|
on_remove(obj);
|
|
|
|
};
|
|
|
|
|
|
|
|
get_renderer()->shadow_pass->create_scene_resources(scene);
|
|
|
|
get_renderer()->scene_capture->create_scene_resources(scene);
|
|
|
|
|
|
|
|
scene.reset_shadows();
|
|
|
|
scene.reset_environment();
|
|
|
|
}
|
2021-10-07 17:46:28 -04:00
|
|
|
|
|
|
|
void prism::engine::process_text_input(const std::string_view string) {
|
|
|
|
imgui->process_text_input(string);
|
|
|
|
}
|