add organizer scene, and add scene tools time delta context editor

This commit is contained in:
Green Sky 2021-01-17 16:53:01 +01:00
parent 9bcaf87788
commit 39b0677c3a
6 changed files with 274 additions and 9 deletions

View File

@ -9,6 +9,7 @@ add_subdirectory(std_utils)
add_subdirectory(screen_director)
add_subdirectory(filesystem)
add_subdirectory(simple_scene)
add_subdirectory(organizer_scene)
if(NOT MM_HEADLESS)
add_subdirectory(sdl_service)

View File

@ -6,6 +6,7 @@
#include <mm/engine.hpp>
#include "./imgui_menu_bar.hpp"
#include "mm/components/time_delta.hpp"
#include <imgui/imgui.h>
@ -70,6 +71,17 @@ namespace MM::Services {
ImGui::MenuItem("Camera3D Tool", NULL, &_show_camera_tool);
};
menu_bar.menu_tree["Scene"]["TimeCtx"] = [this](Engine& e) {
MM::Components::TimeDelta* td_ptr = nullptr;
if (auto* ssi_ptr = e.tryService<MM::Services::SceneServiceInterface>()) {
auto& scene = ssi_ptr->getScene();
td_ptr = scene.try_ctx<MM::Components::TimeDelta>();
}
ImGui::MenuItem("TimeDelta Context", NULL, &_show_time_delta_ctx, td_ptr);
};
return true;
}
@ -78,6 +90,8 @@ namespace MM::Services {
menu_bar.menu_tree["Scene"].erase("Metrics");
menu_bar.menu_tree["Scene"].erase("EntityEditor");
menu_bar.menu_tree["Scene"].erase("CameraTool");
menu_bar.menu_tree["Scene"].erase("TimeCtx");
}
std::vector<UpdateStrategies::UpdateCreationInfo> ImGuiSceneToolsService::registerUpdates(void) {
@ -97,15 +111,6 @@ namespace MM::Services {
}
void ImGuiSceneToolsService::renderImGui(Engine& engine) {
//if (show_menu && ImGui::BeginMainMenuBar()) {
//if (ImGui::BeginMenu("Windows")) {
//ImGui::MenuItem("Camera Tool", NULL, &_show_camera_tool);
//ImGui::EndMenu();
//}
//}
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
if (_show_scene_metrics) {
@ -150,6 +155,16 @@ namespace MM::Services {
}
ImGui::End();
}
if (_show_time_delta_ctx) {
if (ImGui::Begin("Scene TimeDelta Context", &_show_time_delta_ctx)) {
auto* td_ptr = scene.try_ctx<MM::Components::TimeDelta>();
ImGui::Value("tickDelta", td_ptr->tickDelta);
ImGui::SliderFloat("deltaFactor", &td_ptr->deltaFactor, 0.f, 10.f, "%.5f", ImGuiSliderFlags_Logarithmic);
}
ImGui::End();
}
}
EntityEditor<Entity>& ImGuiSceneToolsService::getEntityEditor(void) {

View File

@ -23,6 +23,7 @@ namespace MM::Services {
bool _show_entity_editor = false;
bool _show_entity_list = true;
bool _show_camera_tool = false;
bool _show_time_delta_ctx = false;
EntityEditor<Entity> _entity_editor;
// for list

View File

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.2)
project(organizer_scene CXX)
add_library(organizer_scene
src/mm/services/organizer_scene.hpp
src/mm/services/organizer_scene.cpp
)
target_include_directories(organizer_scene PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(organizer_scene
engine
common_components
)
if (BUILD_TESTING)
#add_subdirectory(test)
endif()

View File

@ -0,0 +1,174 @@
#include "./organizer_scene.hpp"
#include <mm/components/time_delta.hpp>
#include <entt/entity/registry.hpp>
#include <entt/entity/organizer.hpp>
#include <tracy/Tracy.hpp>
#include <mm/logger.hpp>
#include <spdlog/fmt/ostr.h>
#define LOG_OSS(x) LOG("OrganizerSceneService", x)
namespace entt {
// graphviz dot export
static std::ostream& operator<<(std::ostream& out, const std::vector<entt::organizer::vertex>& nodes) {
out << "digraph EnTT_organizer {\nrankdir=RL;\n";
for (size_t i = 0; i < nodes.size(); i++) {
out << "n" << i << "[shape=" << (nodes[i].top_level() ? "doublecircle" : "circle") << " label=\"" << (nodes[i].name() == nullptr ? "NoName" : nodes[i].name()) << "\"];\n";
}
for (size_t i = 0; i < nodes.size(); i++) {
for (const size_t child : nodes[i].children()) {
out << "n" << child << " -> " << "n" << i << ";\n";
}
}
out << "}";
return out;
}
} // entt
namespace MM::Services {
bool OrganizerSceneService::enable(Engine& engine) {
// default scene
if (!_scene) {
_scene = std::make_unique<Scene>();
_scene->set<MM::Engine*>(&engine);
updateOrganizerVertices(*_scene);
}
resetTime();
return true;
}
void OrganizerSceneService::disable(Engine&) {
}
std::vector<UpdateStrategies::UpdateCreationInfo> OrganizerSceneService::registerUpdates(void) {
using namespace entt::literals;
return {
{
"OrganizerSceneService::scene_update"_hs,
"OrganizerSceneService::scene_update",
[this](Engine& e) { sceneUpdate(e); },
// depends on imgui
},
{
"OrganizerSceneService::scene_tick"_hs,
"OrganizerSceneService::scene_tick",
[this](Engine& e) { sceneFixedUpdate(e); },
UpdateStrategies::update_phase_t::MAIN,
true,
{
"OrganizerSceneService::scene_update"_hs, // bc it renders imgui, but this is not "hard"
}
},
{
"OrganizerSceneService::scene_changer"_hs,
"OrganizerSceneService::scene_changer",
[this](Engine& e) { changeSceneFixedUpdate(e); },
UpdateStrategies::update_phase_t::MAIN,
true,
{
"OrganizerSceneService::scene_tick"_hs,
}
},
};
}
void OrganizerSceneService::sceneFixedUpdate(Engine&) {
ZoneScoped;
auto newNow = clock::now();
auto deltaTime = std::chrono::duration_cast<std::chrono::nanoseconds>(newNow - _last_time);
_last_time = newNow;
_accumulator += deltaTime.count();
const double dt = f_delta * 1'000'000'000.0;
size_t continuous_counter = 0;
auto& time_ctx = _scene->ctx_or_set<MM::Components::TimeDelta>(f_delta, delta_factor);
time_ctx.tickDelta = f_delta * delta_factor;
time_ctx.deltaFactor = delta_factor;
// TODO: this while is just cancer
while (_accumulator >= static_cast<decltype(_accumulator)>(dt)){
_accumulator -= static_cast<decltype(_accumulator)>(dt);
continuous_counter++;
for (auto&& v : _scene->ctx<std::vector<entt::organizer::vertex>>()) {
v.callback()(v.data(), *_scene);
}
TracyPlot("MM::Services::OrganizerSceneService::_scene.alive", (int64_t)_scene->alive());
}
if (continuous_counter > 2) {
LOG_OSS(fmt::format("had {} contiguous scene ticks!", continuous_counter));
}
}
void OrganizerSceneService::changeSceneFixedUpdate(Engine& engine) {
if (_next_scene) {
LOG_OSS("changing scene...");
_scene = std::move(_next_scene);
_scene->set<MM::Engine*>(&engine); // make engine accessible from scene
updateOrganizerVertices(*_scene);
}
}
void OrganizerSceneService::sceneUpdate(Engine&) {
ZoneScoped;
//if (ImGui::Begin("OrganizerScene")) {
//ImGui::SliderFloat("time_factor", &delta_factor, 0.f, 10.f, "%.5f", ImGuiSliderFlags_Logarithmic);
//}
//ImGui::End();
//for (auto&& v : _scene->ctx<std::vector<entt::organizer::vertex>>()) {
//v.callback()(v.data(), *_scene);
//}
//TracyPlot("MM::Services::OrganizerSceneService::_scene.alive", (int64_t)_scene->alive());
}
void OrganizerSceneService::changeScene(std::unique_ptr<Scene>&& new_scene) {
if (_next_scene) {
LOG_OSS("warn: already next scene enqueued! overwriting...");
}
_next_scene = std::move(new_scene);
}
void OrganizerSceneService::changeSceneNow(std::unique_ptr<Scene>&& new_scene) {
_scene = std::move(new_scene);
//_scene->set<MM::Engine*>(&engine); // make engine accessible from scene
updateOrganizerVertices(*_scene);
}
void OrganizerSceneService::updateOrganizerVertices(Scene& scene) {
scene.ctx_or_set<std::vector<entt::organizer::vertex>>() =
scene.ctx_or_set<entt::organizer>().graph();
if (!scene.try_ctx<MM::Components::TimeDelta>()) {
scene.set<MM::Components::TimeDelta>();
}
SPDLOG_DEBUG("graph:\n{}", scene.ctx<std::vector<entt::organizer::vertex>>());
}
void OrganizerSceneService::resetTime(void) {
_last_time = clock::now();
_accumulator = 0;
}
} // MM::Services

View File

@ -0,0 +1,55 @@
#pragma once
#include <mm/services/scene_service_interface.hpp>
#include <entt/fwd.hpp>
#include <chrono>
namespace MM::Services {
// provides an ~implementation for SceneServiceInterface
// !! IMPORTANT: relies on entt::organizer. Use it to add systems!
class OrganizerSceneService : public SceneServiceInterface {
private:
std::unique_ptr<Scene> _scene;
std::unique_ptr<Scene> _next_scene; // enqueued next scene
using clock = std::chrono::high_resolution_clock;
long long int _accumulator = 0;
std::chrono::time_point<clock> _last_time;
public:
const float f_delta;
float delta_factor = 1.f;
public: // service
explicit OrganizerSceneService(const float update_delta = 1.f/60.f) : f_delta(update_delta) {}
const char* name(void) override { return "OrganizerSceneService"; }
bool enable(Engine& engine) override;
void disable(Engine& engine) override;
std::vector<UpdateStrategies::UpdateCreationInfo> registerUpdates(void) override;
public: // scene interface
Scene& getScene(void) override { return *_scene; }
void changeScene(std::unique_ptr<Scene>&& new_scene) override;
// be carefull of that one
void changeSceneNow(std::unique_ptr<Scene>&& new_scene) override;
public:
void sceneFixedUpdate(Engine& engine);
void changeSceneFixedUpdate(Engine& engine);
void sceneUpdate(Engine& engine);
void updateOrganizerVertices(Scene& scene);
void resetTime(void);
};
} // MM::Services