improve nf7::Node interface
This commit is contained in:
parent
901f5c4ab9
commit
cf771824dc
@ -47,6 +47,7 @@ class Window {
|
||||
}
|
||||
|
||||
void SetFocus() noexcept {
|
||||
shown_ = true;
|
||||
set_focus_ = true;
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,14 @@ class Node : public File::Interface {
|
||||
class Lambda;
|
||||
|
||||
enum Flag : uint8_t {
|
||||
kUI = 1 << 0, // UpdateNode() is called to display node
|
||||
kMenu = 1 << 1,
|
||||
kNone = 0,
|
||||
kCustomNode = 1 << 0,
|
||||
kMenu = 1 << 1,
|
||||
kMenu_DirItem = 1 << 2, // use DirItem::UpdateMenu() method instead of Node's
|
||||
};
|
||||
using Flags = uint8_t;
|
||||
|
||||
Node(Flags f = 0) noexcept : flags_(f) { }
|
||||
Node(Flags f) noexcept : flags_(f) { }
|
||||
Node(const Node&) = default;
|
||||
Node(Node&&) = default;
|
||||
Node& operator=(const Node&) = default;
|
||||
|
@ -65,7 +65,8 @@ class Device final : public nf7::FileBase, public nf7::DirItem, public nf7::Node
|
||||
}
|
||||
Device(nf7::Env& env, Selector&& sel = size_t{0}, const ma_device_config& cfg = defaultConfig()) noexcept :
|
||||
nf7::FileBase(kType, env),
|
||||
nf7::DirItem(DirItem::kMenu | DirItem::kTooltip),
|
||||
nf7::DirItem(nf7::DirItem::kMenu | nf7::DirItem::kTooltip),
|
||||
nf7::Node(nf7::Node::kNone),
|
||||
data_(std::make_shared<AsyncData>(*this)),
|
||||
selector_(std::move(sel)), cfg_(cfg),
|
||||
config_popup_(std::make_shared<ConfigPopup>()) {
|
||||
@ -90,7 +91,6 @@ class Device final : public nf7::FileBase, public nf7::DirItem, public nf7::Node
|
||||
void Update() noexcept override;
|
||||
void UpdateMenu() noexcept override;
|
||||
void UpdateTooltip() noexcept override;
|
||||
void UpdateNode(Node::Editor&) noexcept override { }
|
||||
|
||||
static bool UpdateModeSelector(ma_device_type*) noexcept;
|
||||
static const ma_device_info* UpdateSelector(Selector*, ma_device_info*, size_t) noexcept;
|
||||
|
@ -59,6 +59,7 @@ class InlineNode final : public nf7::FileBase, public nf7::DirItem, public nf7::
|
||||
InlineNode(nf7::Env& env, Data&& data = {}) noexcept :
|
||||
nf7::FileBase(kType, env, {&socket_popup_}),
|
||||
nf7::DirItem(nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kCustomNode),
|
||||
life_(*this),
|
||||
log_(std::make_shared<nf7::LoggerRef>(*this)),
|
||||
mem_(std::move(data), *this) {
|
||||
|
@ -63,6 +63,7 @@ class Node final : public nf7::FileBase, public nf7::DirItem, public nf7::Node {
|
||||
Node(Env& env, Data&& data = {}) noexcept :
|
||||
nf7::FileBase(kType, env, {&obj_, &obj_editor_, &socket_popup_}),
|
||||
nf7::DirItem(nf7::DirItem::kTooltip | nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kNone),
|
||||
life_(*this),
|
||||
log_(std::make_shared<nf7::LoggerRef>(*this)),
|
||||
obj_(*this, "obj_factory", mem_),
|
||||
@ -294,7 +295,7 @@ void Node::UpdateWidget() noexcept {
|
||||
mem_.Commit();
|
||||
}
|
||||
|
||||
if (ImGui::Button("input/output list")) {
|
||||
if (ImGui::Button("I/O list")) {
|
||||
socket_popup_.Open(data().inputs, data().outputs);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ class Imm final : public nf7::File, public nf7::DirItem, public nf7::Node {
|
||||
|
||||
Imm(nf7::Env& env, nf7::gui::Value&& v = {}) noexcept :
|
||||
nf7::File(kType, env),
|
||||
nf7::DirItem(DirItem::kWidget),
|
||||
nf7::DirItem(nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kCustomNode),
|
||||
life_(*this), mem_(std::move(v), *this) {
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ class Network final : public nf7::FileBase, public nf7::DirItem, public nf7::Nod
|
||||
nf7::DirItem(nf7::DirItem::kMenu |
|
||||
nf7::DirItem::kTooltip |
|
||||
nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kCustomNode),
|
||||
life_(*this),
|
||||
win_(*this, "Editor Node/Network", win),
|
||||
items_(std::move(items)), links_(std::move(links)),
|
||||
@ -118,7 +119,8 @@ class Network final : public nf7::FileBase, public nf7::DirItem, public nf7::Nod
|
||||
void UpdateMenu() noexcept override;
|
||||
void UpdateTooltip() noexcept override;
|
||||
void UpdateWidget() noexcept override;
|
||||
void UpdateNode(Node::Editor&) noexcept override;
|
||||
void UpdateMenu(nf7::Node::Editor&) noexcept override { UpdateMenu(); }
|
||||
void UpdateNode(nf7::Node::Editor&) noexcept override;
|
||||
|
||||
std::shared_ptr<nf7::Node::Lambda> CreateLambda(
|
||||
const std::shared_ptr<nf7::Node::Lambda>&) noexcept override;
|
||||
@ -700,7 +702,8 @@ class Network::Initiator final : public nf7::File,
|
||||
ImGui::Bullet(); ImGui::TextUnformatted("implements nf7::Node");
|
||||
}
|
||||
|
||||
Initiator(nf7::Env& env) noexcept : File(kType, env) {
|
||||
Initiator(nf7::Env& env) noexcept :
|
||||
nf7::File(kType, env), nf7::Node(nf7::Node::kCustomNode) {
|
||||
}
|
||||
|
||||
Initiator(nf7::Deserializer& ar) : Initiator(ar.env()) {
|
||||
@ -751,7 +754,7 @@ class Network::Terminal : public nf7::File,
|
||||
public nf7::Node,
|
||||
public Network::InternalNode {
|
||||
public:
|
||||
static inline const GenericTypeInfo<Terminal> kType = {
|
||||
static inline const nf7::GenericTypeInfo<Terminal> kType = {
|
||||
"Node/Network/Terminal", {}};
|
||||
|
||||
enum Type { kInput, kOutput, };
|
||||
@ -762,6 +765,7 @@ class Network::Terminal : public nf7::File,
|
||||
|
||||
Terminal(nf7::Env& env, Data&& data = {}) noexcept :
|
||||
nf7::File(kType, env),
|
||||
nf7::Node(nf7::Node::kCustomNode),
|
||||
life_(*this), mem_(std::move(data), *this) {
|
||||
}
|
||||
|
||||
@ -1128,19 +1132,20 @@ void Network::Update() noexcept {
|
||||
}
|
||||
}
|
||||
void Network::UpdateMenu() noexcept {
|
||||
if (ImGui::MenuItem("Editor", nullptr, &win_.shown()) && win_.shown()) {
|
||||
win_.SetFocus();
|
||||
}
|
||||
if (ImGui::MenuItem("I/O sockets")) {
|
||||
socket_popup_.Open(inputs_, outputs_);
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Network Editor", nullptr, &win_.shown());
|
||||
}
|
||||
void Network::UpdateTooltip() noexcept {
|
||||
ImGui::Text("nodes active: %zu", items_.size());
|
||||
}
|
||||
void Network::UpdateWidget() noexcept {
|
||||
ImGui::TextUnformatted("Node/Network");
|
||||
if (ImGui::Button("open network editor")) {
|
||||
win_.shown() = true;
|
||||
if (ImGui::Button("open editor")) {
|
||||
win_.SetFocus();
|
||||
}
|
||||
if (ImGui::Button("I/O sockets")) {
|
||||
socket_popup_.Open(inputs_, outputs_);
|
||||
@ -1148,7 +1153,23 @@ void Network::UpdateWidget() noexcept {
|
||||
|
||||
socket_popup_.Update();
|
||||
}
|
||||
void Network::UpdateNode(Node::Editor&) noexcept {
|
||||
void Network::UpdateNode(nf7::Node::Editor&) noexcept {
|
||||
ImGui::TextUnformatted("Node/Network");
|
||||
|
||||
ImGui::BeginGroup();
|
||||
nf7::gui::NodeInputSockets(inputs_);
|
||||
ImGui::SameLine();
|
||||
nf7::gui::NodeOutputSockets(outputs_);
|
||||
ImGui::EndGroup();
|
||||
|
||||
if (ImGui::Button("open editor")) {
|
||||
win_.SetFocus();
|
||||
}
|
||||
if (ImGui::Button("I/O sockets")) {
|
||||
socket_popup_.Open(inputs_, outputs_);
|
||||
}
|
||||
|
||||
socket_popup_.Update();
|
||||
}
|
||||
|
||||
void Network::Item::UpdateNode(Node::Editor& ed) noexcept {
|
||||
@ -1157,7 +1178,14 @@ void Network::Item::UpdateNode(Node::Editor& ed) noexcept {
|
||||
|
||||
const auto id = reinterpret_cast<void*>(id_);
|
||||
if (ImNodes::BeginNode(id, &pos_, &select_)) {
|
||||
node_->UpdateNode(ed);
|
||||
if (node_->flags() & nf7::Node::kCustomNode) {
|
||||
node_->UpdateNode(ed);
|
||||
} else {
|
||||
ImGui::TextUnformatted(file_->type().name().c_str());
|
||||
nf7::gui::NodeInputSockets(node_->GetInputs());
|
||||
ImGui::SameLine();
|
||||
nf7::gui::NodeOutputSockets(node_->GetOutputs());
|
||||
}
|
||||
}
|
||||
ImNodes::EndNode();
|
||||
|
||||
@ -1179,6 +1207,16 @@ void Network::Item::UpdateNode(Node::Editor& ed) noexcept {
|
||||
owner_->ExecAddItem(
|
||||
std::make_unique<Item>(owner_->next_++, file_->Clone(env())));
|
||||
}
|
||||
if (node_->flags() & nf7::Node::kMenu_DirItem) {
|
||||
ImGui::Separator();
|
||||
auto dir = file_->interface<nf7::DirItem>();
|
||||
assert(dir);
|
||||
dir->UpdateMenu();
|
||||
}
|
||||
if (node_->flags() & nf7::Node::kMenu) {
|
||||
ImGui::Separator();
|
||||
node_->UpdateMenu(ed);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
|
165
file/node_ref.cc
165
file/node_ref.cc
@ -15,12 +15,14 @@
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/dir_item.hh"
|
||||
#include "common/file_base.hh"
|
||||
#include "common/generic_context.hh"
|
||||
#include "common/generic_memento.hh"
|
||||
#include "common/generic_type_info.hh"
|
||||
#include "common/gui_dnd.hh"
|
||||
#include "common/gui_node.hh"
|
||||
#include "common/gui_popup.hh"
|
||||
#include "common/life.hh"
|
||||
#include "common/logger_ref.hh"
|
||||
#include "common/memento.hh"
|
||||
@ -55,10 +57,12 @@ class Ref final : public nf7::FileBase, public nf7::Node {
|
||||
};
|
||||
|
||||
Ref(nf7::Env& env, Data&& data = {}) noexcept :
|
||||
nf7::FileBase(kType, env),
|
||||
nf7::FileBase(kType, env, {&config_popup_}),
|
||||
nf7::Node(nf7::Node::kCustomNode | nf7::Node::kMenu),
|
||||
life_(*this),
|
||||
log_(std::make_shared<nf7::LoggerRef>(*this)),
|
||||
mem_(std::move(data), *this) {
|
||||
mem_(std::move(data), *this),
|
||||
config_popup_(*this) {
|
||||
nf7::FileBase::Install(*log_);
|
||||
}
|
||||
|
||||
@ -81,8 +85,8 @@ class Ref final : public nf7::FileBase, public nf7::Node {
|
||||
return data().outputs;
|
||||
}
|
||||
|
||||
void Update() noexcept override;
|
||||
void UpdateNode(nf7::Node::Editor&) noexcept override;
|
||||
void UpdateMenu(nf7::Node::Editor&) noexcept override;
|
||||
|
||||
nf7::File::Interface* interface(const std::type_info& t) noexcept override {
|
||||
return nf7::InterfaceSelector<nf7::Memento, nf7::Node>(t).Select(this, &mem_);
|
||||
@ -93,27 +97,43 @@ class Ref final : public nf7::FileBase, public nf7::Node {
|
||||
|
||||
std::shared_ptr<nf7::LoggerRef> log_;
|
||||
|
||||
const char* popup_ = nullptr;
|
||||
|
||||
nf7::GenericMemento<Data> mem_;
|
||||
|
||||
const Data& data() const noexcept { return mem_.data(); }
|
||||
Data& data() noexcept { return mem_.data(); }
|
||||
|
||||
nf7::Node& target() const {
|
||||
|
||||
// GUI popup
|
||||
class ConfigPopup final : public nf7::FileBase::Feature, private nf7::gui::Popup {
|
||||
public:
|
||||
ConfigPopup(Ref& f) noexcept : nf7::gui::Popup("ConfigPopup"), f_(&f) {
|
||||
}
|
||||
|
||||
void Open() noexcept {
|
||||
path_ = f_->data().target.Stringify();
|
||||
nf7::gui::Popup::Open();
|
||||
}
|
||||
void Update() noexcept override;
|
||||
|
||||
private:
|
||||
Ref* const f_;
|
||||
std::string path_;
|
||||
} config_popup_;
|
||||
|
||||
// accessors
|
||||
nf7::File& target() const {
|
||||
auto& f = ResolveOrThrow(data().target);
|
||||
if (&f == this) throw nf7::Exception("self reference");
|
||||
return f.interfaceOrThrow<nf7::Node>();
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
// socket synchronization
|
||||
bool SyncQuiet() noexcept {
|
||||
auto& dsti = data().inputs;
|
||||
auto& dsto = data().outputs;
|
||||
|
||||
bool mod = false;
|
||||
try {
|
||||
auto& n = target();
|
||||
auto& n = target().interfaceOrThrow<nf7::Node>();
|
||||
|
||||
const auto srci = n.GetInputs();
|
||||
mod |= std::equal(dsti.begin(), dsti.end(), srci.begin(), srci.end());
|
||||
@ -135,9 +155,17 @@ class Ref final : public nf7::FileBase, public nf7::Node {
|
||||
mem_.Commit();
|
||||
}
|
||||
}
|
||||
void ExecChangePath(Path&& p) noexcept {
|
||||
void ExecSync() noexcept {
|
||||
env().ExecMain(
|
||||
std::make_shared<nf7::GenericContext>(*this, "synchornizing"),
|
||||
[this]() { Sync(); });
|
||||
}
|
||||
|
||||
// referencee operation
|
||||
void ExecChangeTarget(Path&& p) noexcept {
|
||||
auto& target = mem_.data().target;
|
||||
if (p == target) return;
|
||||
|
||||
env().ExecMain(
|
||||
std::make_shared<nf7::GenericContext>(*this, "change path"),
|
||||
[this, &target, p = std::move(p)]() mutable {
|
||||
@ -174,7 +202,9 @@ class Ref::Lambda final : public Node::Lambda,
|
||||
log_->Error("stack overflow");
|
||||
return;
|
||||
}
|
||||
base_ = f_->target().CreateLambda(shared_from_this());
|
||||
base_ = f_->target().
|
||||
interfaceOrThrow<nf7::Node>().
|
||||
CreateLambda(shared_from_this());
|
||||
}
|
||||
base_->Handle(name, v, shared_from_this());
|
||||
}
|
||||
@ -206,46 +236,6 @@ try {
|
||||
}
|
||||
|
||||
|
||||
void Ref::Update() noexcept {
|
||||
nf7::FileBase::Update();
|
||||
|
||||
if (auto popup = std::exchange(popup_, nullptr)) {
|
||||
ImGui::OpenPopup(popup);
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("ConfigPopup")) {
|
||||
static std::string pathstr;
|
||||
|
||||
if (ImGui::IsWindowAppearing()) {
|
||||
pathstr = data().target.Stringify();
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("Node/Ref: config");
|
||||
const bool submit = ImGui::InputText(
|
||||
"path", &pathstr, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
|
||||
bool err = false;
|
||||
|
||||
Path path;
|
||||
try {
|
||||
path = Path::Parse(pathstr);
|
||||
} catch (nf7::Exception& e) {
|
||||
ImGui::Bullet(); ImGui::Text("invalid path: %s", e.msg().c_str());
|
||||
err = true;
|
||||
}
|
||||
try {
|
||||
ResolveOrThrow(path);
|
||||
} catch (File::NotFoundException&) {
|
||||
ImGui::Bullet(); ImGui::Text("target seems to be missing");
|
||||
}
|
||||
|
||||
if (!err && (ImGui::Button("ok") || submit)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ExecChangePath(std::move(path));
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
void Ref::UpdateNode(Node::Editor&) noexcept {
|
||||
const auto& style = ImGui::GetStyle();
|
||||
const auto em = ImGui::GetFontSize();
|
||||
@ -253,9 +243,7 @@ void Ref::UpdateNode(Node::Editor&) noexcept {
|
||||
ImGui::TextUnformatted("Node/Ref");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("sync")) {
|
||||
env().ExecMain(
|
||||
std::make_shared<nf7::GenericContext>(*this, "synchornizing with target node"),
|
||||
[this]() { Sync(); });
|
||||
ExecSync();
|
||||
}
|
||||
|
||||
const auto pathstr = mem_.data().target.Stringify();
|
||||
@ -277,11 +265,11 @@ void Ref::UpdateNode(Node::Editor&) noexcept {
|
||||
}
|
||||
|
||||
if (ImGui::Button(pathstr.c_str(), {w, 0})) {
|
||||
popup_ = "ConfigPopup";
|
||||
config_popup_.Open();
|
||||
}
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (auto p = gui::dnd::Accept<Path>(gui::dnd::kFilePath)) {
|
||||
ExecChangePath(std::move(*p));
|
||||
ExecChangeTarget(std::move(*p));
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
@ -311,6 +299,69 @@ void Ref::UpdateNode(Node::Editor&) noexcept {
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
config_popup_.Update();
|
||||
}
|
||||
void Ref::UpdateMenu(nf7::Node::Editor& ed) noexcept {
|
||||
if (ImGui::MenuItem("sync")) {
|
||||
ExecSync();
|
||||
}
|
||||
if (ImGui::MenuItem("replace target")) {
|
||||
config_popup_.Open();
|
||||
}
|
||||
try {
|
||||
auto& f = target();
|
||||
auto& n = f.interfaceOrThrow<nf7::Node>();
|
||||
auto d = f.interface<nf7::DirItem>();
|
||||
|
||||
const bool dmenu = n.flags() & nf7::Node::kMenu_DirItem;
|
||||
const bool menu = n.flags() & nf7::Node::kMenu;
|
||||
|
||||
if ((dmenu || menu) && ImGui::BeginMenu("target")) {
|
||||
if (dmenu) {
|
||||
assert(d);
|
||||
ImGui::Separator();
|
||||
d->UpdateMenu();
|
||||
}
|
||||
if (menu) {
|
||||
ImGui::Separator();
|
||||
n.UpdateMenu(ed);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
} catch (nf7::Exception&) {
|
||||
}
|
||||
}
|
||||
|
||||
void Ref::ConfigPopup::Update() noexcept {
|
||||
if (nf7::gui::Popup::Begin()) {
|
||||
ImGui::TextUnformatted("Node/Ref: config");
|
||||
const bool submit = ImGui::InputText(
|
||||
"path", &path_, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
|
||||
bool err = false;
|
||||
|
||||
Path path;
|
||||
try {
|
||||
path = Path::Parse(path_);
|
||||
} catch (nf7::Exception& e) {
|
||||
ImGui::Bullet(); ImGui::Text("invalid path: %s", e.msg().c_str());
|
||||
err = true;
|
||||
}
|
||||
try {
|
||||
f_->ResolveOrThrow(path).interfaceOrThrow<nf7::Node>();
|
||||
} catch (nf7::File::NotFoundException&) {
|
||||
ImGui::Bullet(); ImGui::Text("target seems to be missing");
|
||||
} catch (nf7::File::NotImplementedException&) {
|
||||
ImGui::Bullet(); ImGui::Text("target doesn't seem to have Node interface");
|
||||
}
|
||||
|
||||
if (!err && (ImGui::Button("ok") || submit)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
f_->ExecChangeTarget(std::move(path));
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ class TL final : public nf7::FileBase, public nf7::DirItem, public nf7::Node {
|
||||
const nf7::gui::Window* win = nullptr) noexcept :
|
||||
nf7::FileBase(kType, env, {&popup_socket_, &popup_add_item_}),
|
||||
nf7::DirItem(nf7::DirItem::kMenu | nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kMenu_DirItem),
|
||||
life_(*this),
|
||||
layers_(std::move(layers)), next_(next),
|
||||
win_(*this, "Timeline Editor", win), tl_("timeline"),
|
||||
@ -1237,16 +1238,21 @@ void TL::Update() noexcept {
|
||||
}
|
||||
}
|
||||
void TL::UpdateMenu() noexcept {
|
||||
ImGui::MenuItem("Editor", nullptr, &win_.shown());
|
||||
if (ImGui::MenuItem("editor", nullptr, &win_.shown()) && win_.shown()) {
|
||||
win_.SetFocus();
|
||||
}
|
||||
if (ImGui::MenuItem("I/O list")) {
|
||||
popup_socket_.Open(seq_inputs_, seq_outputs_);
|
||||
}
|
||||
}
|
||||
void TL::UpdateWidget() noexcept {
|
||||
ImGui::TextUnformatted("Sequencer/Timeline");
|
||||
|
||||
|
||||
if (ImGui::Button("Timeline Editor")) {
|
||||
win_.shown() = true;
|
||||
if (ImGui::Button("Editor")) {
|
||||
win_.SetFocus();
|
||||
}
|
||||
if (ImGui::Button("I/O socket list")) {
|
||||
if (ImGui::Button("I/O list")) {
|
||||
popup_socket_.Open(seq_inputs_, seq_outputs_);
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ class NativeFile final : public nf7::FileBase,
|
||||
nf7::DirItem(nf7::DirItem::kMenu |
|
||||
nf7::DirItem::kTooltip |
|
||||
nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kMenu_DirItem),
|
||||
life_(*this),
|
||||
shared_(std::make_shared<SharedData>(*this)),
|
||||
th_(std::make_shared<Thread>(*this, Runner {shared_})),
|
||||
|
@ -68,6 +68,7 @@ class Curve final : public nf7::File,
|
||||
Curve(nf7::Env& env, Data&& data = {}) noexcept :
|
||||
nf7::File(kType, env),
|
||||
nf7::DirItem(nf7::DirItem::kWidget),
|
||||
nf7::Node(nf7::Node::kCustomNode),
|
||||
nf7::Sequencer(nf7::Sequencer::kCustomItem |
|
||||
nf7::Sequencer::kParamPanel),
|
||||
life_(*this), mem_(std::move(data), *this) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user