Browse Source

[BORKED] did stuff

main
Annwan 3 months ago
parent
commit
fcc022dfd6
  1. 76
      src/Application.cppm
  2. 115
      src/Node.cppm
  3. 18
      src/Nodes/InputNode.cpp
  4. 18
      src/Nodes/OutputNode.cpp
  5. 34
      src/Nodes/SplitterNode.cpp
  6. 2
      src/Nodes/StreamSpecConstantNode.cpp
  7. 18
      src/Port.cppm
  8. 5
      src/Ports/InputPort.cpp
  9. 10
      src/Ports/Label.cpp
  10. 11
      src/Ports/OutputPort.cpp

76
src/Application.cppm

@ -2,6 +2,7 @@ module;
#include "macros.hpp" #include "macros.hpp"
#include <algorithm> #include <algorithm>
#include <clopts.hh>
#include <cmath> #include <cmath>
#include <deque> #include <deque>
#include <memory> #include <memory>
@ -16,6 +17,7 @@ export module Application;
import Node; import Node;
import Base; import Base;
import Button; import Button;
using command_line_options::detail::list;
namespace ffmpegraph { namespace ffmpegraph {
export class Application { export class Application {
public: public:
@ -60,11 +62,12 @@ Application::Application(std::string _title)
InitWindow(800, 600, this->title.c_str()); InitWindow(800, 600, this->title.c_str());
SetTargetFPS(60); SetTargetFPS(60);
SetExitKey(KEY_NULL); SetExitKey(KEY_NULL);
add_buttons.emplace_back(10, 10, 100, 20, "String Constant");
add_buttons.emplace_back(10, 35, 100, 20, "Input File");
add_buttons.emplace_back(10, 60, 100, 20, "Output File");
add_buttons.emplace_back(10, 85 , 100, 20, "Stream Spec Constant");
add_buttons.emplace_back(0, 0, 200, 20, "String Constant");
add_buttons.emplace_back(0, 0, 200, 20, "File Input");
add_buttons.emplace_back(0, 0, 200, 20, "File Output");
add_buttons.emplace_back(0, 0, 200, 20, "Stream Spec Constant");
add_buttons.emplace_back(0, 0, 200, 20, "Splitter");
AllOptions::each([&]<class T>() { add_buttons.emplace_back(0, 0, 200, 20, std::string(T::label_view)); });
run_button.width = 10 + MeasureText("Run", 10); run_button.width = 10 + MeasureText("Run", 10);
} }
@ -83,19 +86,25 @@ void Application::ProcessEvents() {
void Application::OnLeftClick() { void Application::OnLeftClick() {
if (current_state == State::ADDING) { if (current_state == State::ADDING) {
if (add_buttons[0].IsHovered()) {
nodes.push_back(std::make_unique<StringConstantNode>());
} else if (add_buttons[1].IsHovered()) {
nodes.push_back(std::make_unique<InputNode>());
} else if (add_buttons[2].IsHovered()) {
nodes.push_back(std::make_unique<OutputNode>());
} else if (add_buttons[3].IsHovered()) {
nodes.push_back(std::make_unique<StreamSpecConstantNode>());
}
usz i = 0;
current_state = State::DEFAULT; current_state = State::DEFAULT;
return;
list<StringConstantNode, InputNode, OutputNode, StreamSpecConstantNode, SplitterNode>::each([&]<class T>() {
if (add_buttons[i++].IsHovered()) {
nodes.push_back(std::make_unique<T>());
selected_node = nodes.back().get();
current_state = State::EDITING;
} }
});
AllOptions::each([&]<class T>() {
if (add_buttons[i++].IsHovered()) {
nodes.push_back(std::make_unique<T>());
selected_node = nodes.back().get();
current_state = State::EDITING;
}
});
return;
}
auto GetPort = [&] -> Port * { auto GetPort = [&] -> Port * {
for (auto &node : nodes) { for (auto &node : nodes) {
for (auto *port : node->ports) { for (auto *port : node->ports) {
@ -116,15 +125,13 @@ void Application::OnLeftClick() {
selected_port = nullptr; selected_port = nullptr;
current_state = State::DEFAULT; current_state = State::DEFAULT;
} else if (run_button.IsHovered()) { } else if (run_button.IsHovered()) {
if (auto res = ExecuteGraph(); not res) {
message_queue.push_front(res.error());
}
if (auto res = ExecuteGraph(); not res) { message_queue.push_front(res.error()); }
} else { } else {
i32 x = GetMouseX(); i32 x = GetMouseX();
i32 y = GetMouseY(); i32 y = GetMouseY();
auto port = GetPort(); auto port = GetPort();
auto oport = dynamic_cast<OutputPort *>(port); auto oport = dynamic_cast<OutputPort *>(port);
if (oport) {
if (oport and oport->type != PortTypeE::GENERIC) {
if (oport->GetConnected()) { if (oport->GetConnected()) {
oport->Disconnect(); oport->Disconnect();
} else { } else {
@ -154,13 +161,20 @@ Result<> Application::ExecuteGraph() {
for (auto [i, node] : vws::enumerate(nodes)) { for (auto [i, node] : vws::enumerate(nodes)) {
Node *raw_node = node.get(); Node *raw_node = node.get();
if (auto n = dynamic_cast<InputNode *>(raw_node)) { if (auto n = dynamic_cast<InputNode *>(raw_node)) {
if (auto c = n->output_port.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
} }
if (auto n = dynamic_cast<StringConstantNode *>(raw_node)) { if (auto n = dynamic_cast<StringConstantNode *>(raw_node)) {
if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
} }
if (auto _ = dynamic_cast<OutputNode *>(raw_node)) {} if (auto _ = dynamic_cast<OutputNode *>(raw_node)) {}
// OutputNode doesn’t have output ports. // OutputNode doesn’t have output ports.
if (auto n = dynamic_cast<StreamSpecConstantNode *>(raw_node)) {
if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
}
if (auto n = dynamic_cast<SplitterNode *>(raw_node)) {
if (auto c = n->out1.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
if (auto c = n->out2.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); }
}
} }
// TODO add cases for all new types of nodes // TODO add cases for all new types of nodes
@ -177,26 +191,20 @@ Result<> Application::ExecuteGraph() {
break; break;
} }
} }
if (not changed) {
return Error("Graph has cycle");
}
if (not changed) { return Error("Graph has cycle"); }
} }
for (auto node : sorted_nodes) { Try(node->Run()); } for (auto node : sorted_nodes) { Try(node->Run()); }
return {}; return {};
} }
void Application::OnKeyPressed(i32 key) { void Application::OnKeyPressed(i32 key) {
if ((key == KEY_EQUAL or key == KEY_KP_ADD) and current_state == State::DEFAULT) {
current_state = State::ADDING;
}
if ((key == KEY_EQUAL or key == KEY_KP_ADD) and current_state == State::DEFAULT) { current_state = State::ADDING; }
if (current_state != State::EDITING) return; if (current_state != State::EDITING) return;
if (key == KEY_DELETE) { if (key == KEY_DELETE) {
for (auto &node : nodes) { for (auto &node : nodes) {
for (auto raw_port : node->ports) { for (auto raw_port : node->ports) {
if (auto port = dynamic_cast<OutputPort *>(raw_port)) { if (auto port = dynamic_cast<OutputPort *>(raw_port)) {
if (auto a = port->GetConnected(); a and a->owner == selected_node) {
port->Disconnect();
}
if (auto a = port->GetConnected(); a and a->owner == selected_node) { port->Disconnect(); }
} }
} }
} }
@ -257,8 +265,18 @@ void Application::Render() {
offset += 20; offset += 20;
} }
if (current_state == State::ADDING) { if (current_state == State::ADDING) {
auto maxx = GetScreenWidth();
auto currentx = 10;
auto currenty = 10;
for (auto b : add_buttons) { for (auto b : add_buttons) {
b.pos_x = currentx;
b.pos_y = currenty;
b.Render(); b.Render();
currentx += 210;
if (currentx + 200 > maxx) {
currentx = 10;
currenty += 25;
}
} }
} else { } else {
if (selected_port) { DrawLine(selected_port->pos_x, selected_port->pos_y, GetMouseX(), GetMouseY(), BLACK); } if (selected_port) { DrawLine(selected_port->pos_x, selected_port->pos_y, GetMouseX(), GetMouseY(), BLACK); }

115
src/Node.cppm

@ -1,5 +1,5 @@
module; module;
#include <print>
#include <clopts.hh>
#include <raylib.h> #include <raylib.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -7,6 +7,8 @@ export module Node;
export import :Port; export import :Port;
import Base; import Base;
using command_line_options::detail::list;
using command_line_options::detail::static_string;
export namespace ffmpegraph { export namespace ffmpegraph {
struct Node { struct Node {
@ -27,14 +29,18 @@ struct Node {
std::vector<Port*> ports; std::vector<Port*> ports;
virtual Result<> Run() = 0; virtual Result<> Run() = 0;
virtual void OnDisconnect() {} virtual void OnDisconnect() {}
virtual void OnConnect() {}
protected: protected:
i32 width = min_port_width; i32 width = min_port_width;
}; };
struct InputNode : Node { struct InputNode : Node {
InputNode(); InputNode();
Label label; Label label;
InputPort filename_port;
OutputPort output_port;
InputPort prev;
InputPort opts;
InputPort filename;
OutputPort out;
Result<> Run() override; Result<> Run() override;
}; };
@ -42,8 +48,9 @@ struct OutputNode : Node {
OutputNode(); OutputNode();
Result<> Run() override; Result<> Run() override;
Label label; Label label;
InputPort in_data;
InputPort in_filename;
InputPort prev;
InputPort opts;
InputPort filename;
}; };
struct StringConstantNode : Node { struct StringConstantNode : Node {
@ -63,7 +70,105 @@ struct StreamSpecConstantNode : Node {
}; };
struct SplitterNode : Node { struct SplitterNode : Node {
SplitterNode();
Result<> Run() override;
void OnDisconnect() override;
void OnConnect() override;
Label label;
InputPort in;
OutputPort out1;
OutputPort out2;
}; };
template <static_string name, static_string ffmpegopt, PortTypeE arg_type, static_string arg_name = "Arg">
struct OptionNode : Node {
OptionNode()
: label(std::string(name.sv()), this)
, prev("Chain", this, PortTypeE::OPTIONS)
, arg(std::string(arg_name.sv()), this, arg_type)
, out("Out", this, PortTypeE::OPTIONS) {
ports.push_back(&label);
ports.push_back(&prev);
ports.push_back(&arg);
ports.push_back(&out);
}
Result<> Run() override {
out.SetValue(std::format("{} {} {}", prev.GetValue(), ffmpegopt.sv(), arg.GetValue()));
return {};
} }
Label label;
InputPort prev;
InputPort arg;
OutputPort out;
static constexpr std::string_view label_view = name.sv();
};
template <static_string name, static_string ffmpegopt, PortTypeE arg_type, static_string arg_name = "Arg">
struct SpecOptionNode : Node {
SpecOptionNode()
: label(std::string(name.sv()), this)
, prev("Chain", this, PortTypeE::OPTIONS)
, spec("spec", this, PortTypeE::STREAM)
, arg(std::string(arg_name.sv()), this, arg_type)
, out("Out", this, PortTypeE::OPTIONS) {
ports.push_back(&label);
ports.push_back(&prev);
ports.push_back(&spec);
ports.push_back(&arg);
ports.push_back(&out);
}
Result<> Run() override {
out.SetValue(
std::format(
"{} {}{}{} {}", prev.GetValue(), ffmpegopt.sv(), std::get_if<Unit>(&spec.GetValue()) ? "" : ":",
spec.GetValue(), arg.GetValue()
)
);
return {};
}
Label label;
InputPort prev;
InputPort spec;
InputPort arg;
OutputPort out;
static constexpr std::string_view label_view = name.sv();
};
// General options
using ForceFormatOptionNode = OptionNode<"Force Format", "-f", PortTypeE::STRING>;
using StreamLoopOptionNode = OptionNode<"Loop Stream", "-stream_loop", PortTypeE::INT, "Count">;
using DurationOptionNode = OptionNode<"Duration", "-t", PortTypeE::DURATION>;
using PositionOptionNode = OptionNode<"Position", "-to", PortTypeE::DURATION>;
using SizeLimitOptionNode = OptionNode<"Size Limit", "-fs", PortTypeE::INT, "Bytes">;
using SeekStartOptionNode = OptionNode<"Seek from Start", "-ss", PortTypeE::DURATION>;
using SeekEndOptionNode = OptionNode<"Seek from End", "-sseof", PortTypeE::DURATION>;
using SyncToOptionNode = OptionNode<"Sync to Input", "-isync", PortTypeE::INT, "Input index">;
using InputTimeOffsetOptionNode = OptionNode<"Input Time Offset", "-itsoffset", PortTypeE::DURATION>;
using InputTimeScaleOptionNode = OptionNode<"Input Time Scale", "-itsscale", PortTypeE::DURATION>;
using TimestampOptionNode = OptionNode<"Output Timestamp", "-timestamp", PortTypeE::STRING>;
using TargetOptionNode = OptionNode<"Target", "-target", PortTypeE::STRING>;
using DiscardAllOptionNode = OptionNode<"Discard All", "-dn", PortTypeE::STRING, "IGNORED">;
using AttachOptionNode = OptionNode<"Attach", "-attach", PortTypeE::STRING, "Filename">;
using CodecOptionNode = SpecOptionNode<"Codec", "-c", PortTypeE::STRING>;
using DispositionOptionNode = SpecOptionNode<"Disposition", "-disposition", PortTypeE::STRING>;
using FrameLimitOptionNode = SpecOptionNode<"Frame Limit", "-frames", PortTypeE::INT, "Count">;
using QualityScaleOptionNode = SpecOptionNode<"Quality Scale", "-qscale", PortTypeE::STRING>;
using PresetOptionNode = SpecOptionNode<"Preset", "-pre", PortTypeE::STRING>;
using ExtractAttachment = SpecOptionNode<"Extract Attachment", "-dump_attachment", PortTypeE::STRING, "Filename">;
using AllOptions = list<
ForceFormatOptionNode, StreamLoopOptionNode, DurationOptionNode, PositionOptionNode, SizeLimitOptionNode,
SeekStartOptionNode, SeekEndOptionNode, SyncToOptionNode, InputTimeOffsetOptionNode, InputTimeScaleOptionNode,
TimestampOptionNode, TargetOptionNode, DiscardAllOptionNode, AttachOptionNode, CodecOptionNode,
DispositionOptionNode, FrameLimitOptionNode, QualityScaleOptionNode, PresetOptionNode, ExtractAttachment>;
// -program [title=title:][program_num=program_num:]st=stream[:st=stream...]
// -stream_group
// [map=input_file_id=stream_group][type=type:]st=stream[:st=stream][:stg=stream_group][:id=stream_group_id...]
// -filter[:stream_specifier] filtergraph
// -reinit_filter[:stream_specifier] integer
// -metadata[:metadata_specifier] key=value
} // namespace ffmpegraph

18
src/Nodes/InputNode.cpp

@ -5,17 +5,21 @@ module Node;
using namespace ffmpegraph; using namespace ffmpegraph;
InputNode::InputNode() InputNode::InputNode()
: label("Input File", this)
, filename_port("Filename", this, PortTypeE::STRING)
, output_port("Out", this, PortTypeE::STRING) {
: label("File Input", this)
, prev("Chain", this, PortTypeE::INPUTS)
, opts("Options", this, PortTypeE::OPTIONS)
, filename("Filename", this, PortTypeE::STRING)
, out("Out", this, PortTypeE::INPUTS) {
ports.push_back(&label); ports.push_back(&label);
ports.push_back(&filename_port);
ports.push_back(&output_port);
ports.push_back(&prev);
ports.push_back(&opts);
ports.push_back(&filename);
ports.push_back(&out);
} }
Result<> InputNode::Run() { Result<> InputNode::Run() {
auto data = std::get_if<std::string>(&filename_port.GetValue());
auto data = std::get_if<std::string>(&filename.GetValue());
if (not data or data->empty()) return Error("File Input needs a filename "); if (not data or data->empty()) return Error("File Input needs a filename ");
output_port.SetValue(std::format("-i {}", *data));
out.SetValue(std::format("{} {} -i '{}'", prev.GetValue(), opts.GetValue(), *data));
return {}; return {};
} }

18
src/Nodes/OutputNode.cpp

@ -1,20 +1,24 @@
module; module;
#include <string>
#include <variant> #include <variant>
module Node; module Node;
using namespace ffmpegraph; using namespace ffmpegraph;
OutputNode::OutputNode() OutputNode::OutputNode()
: label("File Output", this) : label("File Output", this)
, in_data("Data", this, PortTypeE::STRING)
, in_filename("File", this, PortTypeE::STRING) {
, prev("Chain", this, PortTypeE::INPUTS)
, opts("Opts", this, PortTypeE::OPTIONS)
, filename("File", this, PortTypeE::STRING) {
ports.push_back(&label); ports.push_back(&label);
ports.push_back(&in_data);
ports.push_back(&in_filename);
ports.push_back(&prev);
ports.push_back(&opts);
ports.push_back(&filename);
} }
Result<> OutputNode::Run() { Result<> OutputNode::Run() {
auto data = std::get_if<std::string>(&in_data.GetValue());
auto data = std::get_if<std::string>(&prev.GetValue());
if (not data) return {}; if (not data) return {};
auto fname = std::get_if<std::string>(&in_filename.GetValue());
auto fname = std::get_if<std::string>(&filename.GetValue());
auto path = fname and not fname->empty() ? std::string_view{*fname} : "/tmp/ffmpegraph_out"; auto path = fname and not fname->empty() ? std::string_view{*fname} : "/tmp/ffmpegraph_out";
return Error("ffmpeg {} {}", *data, path);
return Error("ffmpeg -nostdin {} {} '{}'", *data, opts.GetValue(), path);
} }

34
src/Nodes/SplitterNode.cpp

@ -0,0 +1,34 @@
module Node;
import Base;
using namespace ffmpegraph;
SplitterNode::SplitterNode()
: label("Splitter", this)
, in("Input", this, PortTypeE::GENERIC)
, out1("Output", this, PortTypeE::GENERIC)
, out2("Output", this, PortTypeE::GENERIC) {
ports.push_back(&label);
ports.push_back(&in);
ports.push_back(&out1);
ports.push_back(&out2);
}
Result<> SplitterNode::Run() {
out1.SetValue(in.GetValue());
out2.SetValue(in.GetValue());
return {};
}
void SplitterNode::OnConnect() {
out1.type = out2.type = in.type;
}
void SplitterNode::OnDisconnect() {
in.type = out1.type = out2.type = PortTypeE::GENERIC;
out1.Disconnect();
out2.Disconnect();
}

2
src/Nodes/StreamSpecConstantNode.cpp

@ -2,7 +2,7 @@ module Node;
using namespace ffmpegraph; using namespace ffmpegraph;
StreamSpecConstantNode::StreamSpecConstantNode() StreamSpecConstantNode::StreamSpecConstantNode()
: label("Stream Specifier Constant", this), in("Stream Specifier", this), out("Out", this, PortTypeE::STREAM_SPEC) {
: label("Stream Specifier Constant", this), in("Stream Specifier", this), out("Out", this, PortTypeE::STREAM) {
ports.push_back(&label); ports.push_back(&label);
ports.push_back(&in); ports.push_back(&in);
ports.push_back(&out); ports.push_back(&out);

18
src/Port.cppm

@ -12,7 +12,10 @@ enum struct PortTypeE {
GENERIC, GENERIC,
INT, INT,
STRING, STRING,
STREAM_SPEC
STREAM,
OPTIONS,
INPUTS,
DURATION,
}; };
struct PortType { struct PortType {
@ -29,9 +32,12 @@ template <> struct std::formatter<ffmpegraph::PortType> : std::formatter<std::st
auto s = [data] -> string_view { auto s = [data] -> string_view {
switch (data.t) { switch (data.t) {
case ffmpegraph::PortTypeE::INT: return "integer"; case ffmpegraph::PortTypeE::INT: return "integer";
case ffmpegraph::PortTypeE::STREAM_SPEC: return "stream spec";
case ffmpegraph::PortTypeE::STREAM: return "stream";
case ffmpegraph::PortTypeE::STRING: return "string"; case ffmpegraph::PortTypeE::STRING: return "string";
case ffmpegraph::PortTypeE::GENERIC: return "any"; case ffmpegraph::PortTypeE::GENERIC: return "any";
case ffmpegraph::PortTypeE::OPTIONS: return "options";
case ffmpegraph::PortTypeE::INPUTS: return "inputs";
case ffmpegraph::PortTypeE::DURATION: return "duration";
default: return "unknown_type"; default: return "unknown_type";
} }
}(); }();
@ -40,7 +46,7 @@ template <> struct std::formatter<ffmpegraph::PortType> : std::formatter<std::st
}; };
export namespace ffmpegraph { export namespace ffmpegraph {
constexpr i32 min_port_width = 100;
constexpr i32 min_port_width = 20;
using PortData = std::variant<i32, std::string, std::monostate>; using PortData = std::variant<i32, std::string, std::monostate>;
} }
@ -48,7 +54,7 @@ template <> struct std::formatter<ffmpegraph::PortData> : std::formatter<std::st
template <class FormatContext> auto format(ffmpegraph::PortData const& data, FormatContext& ctx) const { template <class FormatContext> auto format(ffmpegraph::PortData const& data, FormatContext& ctx) const {
auto repr = std::visit( auto repr = std::visit(
utils::Overloaded{ utils::Overloaded{
[](std::monostate) { return "()"s; },
[](std::monostate) { return ""s; },
[](std::string const& x) { return x; }, [](std::string const& x) { return x; },
[](i32 x) { return std::to_string(x); }, [](i32 x) { return std::to_string(x); },
}, },
@ -75,18 +81,17 @@ struct OutputPort;
struct InputPort : Port { struct InputPort : Port {
protected: protected:
PortType type;
PortData value = std::monostate{}; PortData value = std::monostate{};
public: public:
InputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {} InputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {}
PortData const& GetValue() const; PortData const& GetValue() const;
PortType type;
i32 Render(i32 x, i32 y, i32 width) override; i32 Render(i32 x, i32 y, i32 width) override;
friend OutputPort; friend OutputPort;
}; };
struct OutputPort : Port { struct OutputPort : Port {
protected: protected:
PortType type;
InputPort* connected = nullptr; InputPort* connected = nullptr;
public: public:
OutputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {} OutputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {}
@ -94,6 +99,7 @@ public:
bool TryConnect(InputPort& ip); bool TryConnect(InputPort& ip);
InputPort* GetConnected() const { return connected; } InputPort* GetConnected() const { return connected; }
void Disconnect(); void Disconnect();
PortType type;
i32 Render(i32 x, i32 y, i32 width) override; i32 Render(i32 x, i32 y, i32 width) override;
}; };

5
src/Ports/InputPort.cpp

@ -14,8 +14,3 @@ i32 InputPort::Render(i32 x, i32 y, i32 width) {
DrawCircle(x, y + 10, 2.5f, BLACK); DrawCircle(x, y + 10, 2.5f, BLACK);
return 10 + MeasureText(formatted.c_str(), 10); return 10 + MeasureText(formatted.c_str(), 10);
} }
i32 Label::Render(i32 x, i32 y, i32 width) {
DrawRectangleLines(x, y, width, 20, BLACK);
DrawText(name.c_str(), x + 5, y + 5, 10, BLACK);
return 10 + MeasureText(name.c_str(), 10);
}

10
src/Ports/Label.cpp

@ -0,0 +1,10 @@
module;
#include <raylib.h>
module Node;
using namespace ffmpegraph;
i32 Label::Render(i32 x, i32 y, i32 width) {
DrawRectangleLines(x, y, width, 20, BLACK);
DrawText(name.c_str(), x + 5, y + 5, 10, BLACK);
return 10 + MeasureText(name.c_str(), 10);
}

11
src/Ports/OutputPort.cpp

@ -1,6 +1,6 @@
module; module;
#include <raylib.h>
#include <format> #include <format>
#include <raylib.h>
module Node; module Node;
using namespace ffmpegraph; using namespace ffmpegraph;
@ -8,16 +8,19 @@ void OutputPort::SetValue(PortData value) {
if (connected) { connected->value = std::move(value); } if (connected) { connected->value = std::move(value); }
} }
bool OutputPort::TryConnect(InputPort& ip) { bool OutputPort::TryConnect(InputPort& ip) {
if (ip.type == PortTypeE::GENERIC) {
ip.type = type;
ip.owner->OnConnect();
}
if (ip.type == type) { if (ip.type == type) {
connected = &ip; connected = &ip;
return true; return true;
} }
return false; return false;
} }
void OutputPort::Disconnect() { void OutputPort::Disconnect() {
if (connected) {
connected->owner->OnDisconnect();
}
if (connected) { connected->owner->OnDisconnect(); }
connected = nullptr; connected = nullptr;
} }
i32 OutputPort::Render(i32 x, i32 y, i32 width) { i32 OutputPort::Render(i32 x, i32 y, i32 width) {

Loading…
Cancel
Save