From a93787b43b0e1d2170882fc663d4dfb2680c6ac6 Mon Sep 17 00:00:00 2001 From: falsycat Date: Sat, 27 Aug 2022 12:40:51 +0900 Subject: [PATCH] add System/Call --- CMakeLists.txt | 1 + file/system_call.cc | 129 ++++++++++++++++++++++++++++++++++++++++++++ main.cc | 10 +++- nf7.hh | 3 ++ 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 file/system_call.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index ec9028c..2262435 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ target_sources(nf7 file/sequencer_adaptor.cc file/sequencer_call.cc file/sequencer_timeline.cc + file/system_call.cc file/system_dir.cc file/system_imgui.cc file/system_logger.cc diff --git a/file/system_call.cc b/file/system_call.cc new file mode 100644 index 0000000..c7e4829 --- /dev/null +++ b/file/system_call.cc @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "nf7.hh" + +#include "common/generic_context.hh" +#include "common/generic_type_info.hh" +#include "common/gui_node.hh" +#include "common/node.hh" +#include "common/ptr_selector.hh" +#include "common/yas_std_atomic.hh" + + +using namespace std::literals; + +namespace nf7 { +namespace { + +class Call final : public nf7::File, public nf7::Node { + public: + static inline const nf7::GenericTypeInfo kType = { + "System/Call", {"nf7::Node"}}; + static void UpdateTypeTooltip() noexcept { + ImGui::TextUnformatted("Call system features."); + ImGui::Bullet(); ImGui::TextUnformatted("implements nf7::Node"); + } + + class Lambda; + + Call(nf7::Env& env) noexcept : + nf7::File(kType, env), + nf7::Node(nf7::Node::kCustomNode) { + } + + Call(nf7::Deserializer& ar) : Call(ar.env()) { + } + void Serialize(nf7::Serializer&) const noexcept override { + } + std::unique_ptr Clone(nf7::Env& env) const noexcept override { + return std::make_unique(env); + } + + std::shared_ptr CreateLambda( + const std::shared_ptr&) noexcept override; + std::span GetInputs() const noexcept override { + static const std::vector kInputs = {"save", "exit", "abort", "panic"}; + return kInputs; + } + std::span GetOutputs() const noexcept override { + return {}; + } + + void UpdateNode(nf7::Node::Editor&) noexcept override; + + nf7::File::Interface* interface(const std::type_info& t) noexcept override { + return nf7::InterfaceSelector(t).Select(this); + } +}; + +class Call::Lambda final : public nf7::Node::Lambda, + public std::enable_shared_from_this { + public: + Lambda(Call& f, const std::shared_ptr& parent) noexcept : + nf7::Node::Lambda(f, parent) { + } + + void Handle(std::string_view name, const nf7::Value& v, + const std::shared_ptr&) noexcept override { + if (name == "save") { + env().ExecMain(shared_from_this(), [this]() { + env().Save(); + }); + } else if (name == "exit") { + env().Exit(); + } else if (name == "abort") { + std::abort(); + } else if (name == "panic") { + try { + if (v.isString()) { + throw nf7::Exception {v.string()}; + } else { + throw nf7::Exception { + "'panic' input can take a string as message shown here :)"}; + } + } catch (nf7::Exception&) { + env().Throw(std::make_exception_ptr({"panic caused by System/Call"})); + } + } + } +}; +std::shared_ptr Call::CreateLambda( + const std::shared_ptr& parent) noexcept { + return std::make_shared(*this, parent); +} + + +void Call::UpdateNode(nf7::Node::Editor&) noexcept { + ImGui::TextUnformatted("System/Call"); + + static const std::vector> kSockets = { + {"save", "save entire nf7 system when get any value"}, + {"exit", "exit nf7 after saving when get any value"}, + {"abort", "[DANGER] abort nf7 process WITHOUT SAVING when get any value"}, + {"panic", "take a string message and make a panic to notify user"}, + }; + for (auto& sock : kSockets) { + if (ImNodes::BeginInputSlot(sock.first.c_str(), 1)) { + nf7::gui::NodeSocket(); + ImGui::SameLine(); + ImGui::TextUnformatted(sock.first.c_str()); + ImNodes::EndSlot(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(sock.second.c_str()); + } + } +} + +} // namespace +} // namespace nf7 diff --git a/main.cc b/main.cc index 01240e0..8bbdae9 100644 --- a/main.cc +++ b/main.cc @@ -99,6 +99,9 @@ class Env final : public nf7::Env { } catch (ExpiredException&) { } + void Exit() noexcept override { + exit_requested_ = true; + } void Save() noexcept override { try { nf7::Serializer::Save(kFileName, root_); @@ -129,6 +132,8 @@ class Env final : public nf7::Env { cv_.notify_one(); } + bool exitRequested() const noexcept { return exit_requested_; } + protected: File* GetFile(File::Id id) const noexcept override { auto itr = files_.find(id); @@ -158,6 +163,7 @@ class Env final : public nf7::Env { private: std::unique_ptr root_; + std::atomic exit_requested_ = false; std::atomic alive_ = true; std::exception_ptr panic_; @@ -185,7 +191,7 @@ class Env final : public nf7::Env { void UpdatePanic() noexcept { const auto em = ImGui::GetFontSize(); - ImGui::SetNextWindowSize({16*em, 12*em}, ImGuiCond_Appearing); + ImGui::SetNextWindowSize({32*em, 24*em}, ImGuiCond_Appearing); if (ImGui::BeginPopupModal("panic")) { ImGui::TextUnformatted("something went wrong X("); @@ -315,7 +321,7 @@ int main(int, char**) { { ::Env env; glfwShowWindow(window); - while (!glfwWindowShouldClose(window)) { + while (!glfwWindowShouldClose(window) && !env.exitRequested()) { // new frame glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); diff --git a/nf7.hh b/nf7.hh index 249a183..5199f77 100644 --- a/nf7.hh +++ b/nf7.hh @@ -273,6 +273,9 @@ class Env { virtual void Handle(const File::Event&) noexcept = 0; + // thread-safe + virtual void Exit() noexcept = 0; + virtual void Save() noexcept = 0; virtual void Throw(std::exception_ptr&&) noexcept = 0;