Annwan
3 months ago
9 changed files with 411 additions and 129 deletions
-
2.clang-format
-
4.gitignore
-
33CMakeLists.txt
-
163src/Application.cppm
-
52src/Base.cppm
-
32src/Button.cppm
-
46src/Node.cppm
-
136src/Port.cppm
-
14src/main.cpp
@ -1,5 +1,5 @@ |
|||||
build/* |
build/* |
||||
/ffmpegraph |
/ffmpegraph |
||||
/.idea |
/.idea |
||||
/cmake-build-debug |
|
||||
/cmake-build-release |
|
||||
|
/out |
||||
|
/release |
@ -0,0 +1,32 @@ |
|||||
|
module; |
||||
|
#include <string> |
||||
|
#include <raylib.h> |
||||
|
export module Button; |
||||
|
import Base; |
||||
|
|
||||
|
export namespace ffmpegraph { |
||||
|
struct Button { |
||||
|
i32 pos_x, pos_y; |
||||
|
i32 width, height; |
||||
|
std::string label; |
||||
|
void Render() const; |
||||
|
bool IsHovered() const; |
||||
|
Button(i32 x, i32 y, i32 w, i32 h, std::string label): pos_x(x), pos_y(y), width(w), height(h), label(std::move(label)) {} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
module: private; |
||||
|
namespace ffmpegraph { |
||||
|
void Button::Render() const { |
||||
|
auto color = IsHovered()? LIGHTGRAY : WHITE; |
||||
|
DrawRectangle(pos_x, pos_y, width, height, color); |
||||
|
DrawRectangleLines(pos_x, pos_y, width, height, BLACK); |
||||
|
DrawText(label.c_str(), pos_x + 5, pos_y + 5, 10, BLACK); |
||||
|
} |
||||
|
|
||||
|
bool Button::IsHovered() const { |
||||
|
return pos_x <= GetMouseX() and GetMouseX() <= pos_x + width |
||||
|
and pos_y <= GetMouseY() and GetMouseY() <= pos_y + height; |
||||
|
} |
||||
|
|
||||
|
} |
@ -1,87 +1,141 @@ |
|||||
module; |
module; |
||||
#include <optional> |
|
||||
#include <string> |
|
||||
|
#include <format> |
||||
|
#include <limits> |
||||
#include <raylib.h> |
#include <raylib.h> |
||||
export module Port; |
|
||||
|
#include <string> |
||||
|
#include <variant> |
||||
|
export module Node:Port; |
||||
import Base; |
import Base; |
||||
|
|
||||
|
using namespace std::literals; |
||||
export namespace ffmpegraph { |
export namespace ffmpegraph { |
||||
|
|
||||
|
struct Node; |
||||
|
|
||||
|
enum struct PortType { |
||||
|
INT, |
||||
|
STRING, |
||||
|
}; |
||||
|
|
||||
|
constexpr i32 min_port_width = 100; |
||||
|
using PortData = std::variant<i32, std::string, std::monostate>; |
||||
|
} |
||||
|
|
||||
|
template <> struct std::formatter<ffmpegraph::PortData> : std::formatter<std::string> { |
||||
|
template <class FormatContext> auto format(ffmpegraph::PortData const& data, FormatContext& ctx) const { |
||||
|
auto repr = std::visit( |
||||
|
utils::Overloaded{ |
||||
|
[](std::monostate) { return "()"s; }, |
||||
|
[](std::string const& x) { return x; }, |
||||
|
[](i32 x) { return std::to_string(x); }, |
||||
|
}, |
||||
|
data |
||||
|
); |
||||
|
return formatter<std::string>::format(repr, ctx); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
export namespace ffmpegraph { |
||||
struct Port { |
struct Port { |
||||
protected: |
protected: |
||||
std::string name; |
std::string name; |
||||
explicit Port(std::string name): name(std::move(name)) {} |
|
||||
|
explicit Port(std::string name, Node* owner) : name(std::move(name)), owner(owner) {} |
||||
virtual ~Port() = default; |
virtual ~Port() = default; |
||||
public: |
public: |
||||
i32 pos_x{}, pos_y{}; |
i32 pos_x{}, pos_y{}; |
||||
virtual void Render(i32 x, i32 y) = 0; |
|
||||
|
Node* owner; |
||||
|
// Returns the desired width for the port. |
||||
|
virtual i32 Render(i32 x, i32 y, i32 width) = 0; |
||||
}; |
}; |
||||
|
|
||||
struct OutputPort; |
struct OutputPort; |
||||
|
|
||||
struct InputPort : Port { |
struct InputPort : Port { |
||||
protected: |
protected: |
||||
std::optional<int> value = std::nullopt; |
|
||||
|
PortType type; |
||||
|
PortData value = std::monostate{}; |
||||
public: |
public: |
||||
explicit InputPort(std::string name): Port(std::move(name)) {} |
|
||||
std::optional<int> GetValue(); |
|
||||
void Render(i32 x, i32 y) override; |
|
||||
|
InputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {} |
||||
|
PortData const& GetValue() const; |
||||
|
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: |
||||
explicit OutputPort(std::string name): Port(std::move(name)) {} |
|
||||
void SetValue(std::optional<int>); |
|
||||
void Connect(InputPort& ip); |
|
||||
|
OutputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {} |
||||
|
void SetValue(PortData value); |
||||
|
bool TryConnect(InputPort& ip); |
||||
|
InputPort* GetConnected() const { return connected; } |
||||
void Disconnect(); |
void Disconnect(); |
||||
void Render(i32 x, i32 y) override; |
|
||||
|
i32 Render(i32 x, i32 y, i32 width) override; |
||||
}; |
}; |
||||
|
|
||||
struct Label : Port { |
struct Label : Port { |
||||
void Render(i32 x, i32 y) override; |
|
||||
explicit Label(std::string name): Port(std::move(name)) { |
|
||||
pos_x = -1; |
|
||||
pos_y = -1; |
|
||||
|
i32 Render(i32 x, i32 y, i32 width) override; |
||||
|
explicit Label(std::string name, Node* owner) : Port(std::move(name), owner) { |
||||
|
pos_x = pos_y = std::numeric_limits<i32>::min(); |
||||
} |
} |
||||
}; |
}; |
||||
|
|
||||
std::optional<int> InputPort::GetValue(){ |
|
||||
return value; |
|
||||
} |
|
||||
void OutputPort::SetValue(std::optional<int> val){ |
|
||||
if (connected) { |
|
||||
connected->value = val; |
|
||||
|
struct StringUserInput : Port { |
||||
|
explicit StringUserInput(std::string name, Node* owner) : Port(std::move(name), owner), data("") { |
||||
|
pos_x = pos_y = std::numeric_limits<i32>::min(); |
||||
} |
} |
||||
|
i32 Render(i32 x, i32 y, i32 width) override; |
||||
|
std::string data; |
||||
|
}; |
||||
|
|
||||
|
PortData const& InputPort::GetValue() const { return value; } |
||||
|
|
||||
|
void OutputPort::SetValue(PortData value) { |
||||
|
if (connected) { connected->value = std::move(value); } |
||||
} |
} |
||||
void OutputPort::Connect(InputPort& ip){ |
|
||||
|
bool OutputPort::TryConnect(InputPort& ip) { |
||||
|
if (ip.type == type) { |
||||
connected = &ip; |
connected = &ip; |
||||
|
return true; |
||||
} |
} |
||||
|
|
||||
void OutputPort::Disconnect(){ |
|
||||
connected = nullptr; |
|
||||
|
return false; |
||||
} |
} |
||||
|
|
||||
void OutputPort::Render(i32 x, i32 y) { |
|
||||
pos_x = x+100; pos_y = y+10; |
|
||||
DrawRectangleLines(x, y, 100, 20, BLACK); |
|
||||
|
void OutputPort::Disconnect() { connected = nullptr; } |
||||
|
|
||||
|
i32 OutputPort::Render(i32 x, i32 y, i32 width) { |
||||
|
pos_x = x + width; |
||||
|
pos_y = y + 10; |
||||
|
DrawRectangleLines(x, y, width, 20, BLACK); |
||||
DrawText(name.c_str(), x + 5, y + 5, 10, RED); |
DrawText(name.c_str(), x + 5, y + 5, 10, RED); |
||||
DrawCircle(x+100, y+10, 2.5f, BLACK); |
|
||||
if (connected) { |
|
||||
DrawLine(pos_x, pos_y, connected->pos_x, connected->pos_y, BLUE); |
|
||||
|
DrawCircle(x + width, y + 10, 2.5f, BLACK); |
||||
|
if (connected) { DrawLine(pos_x, pos_y, connected->pos_x, connected->pos_y, BLUE); } |
||||
|
return 10 + MeasureText(name.c_str(), 10); |
||||
} |
} |
||||
} |
|
||||
void InputPort::Render(i32 x, i32 y) { |
|
||||
pos_x = x; pos_y = y+10; |
|
||||
DrawRectangleLines(x, y, 100, 20, BLACK); |
|
||||
DrawText(name.c_str(), x + 5, y + 5, 10, BLUE); |
|
||||
|
i32 InputPort::Render(i32 x, i32 y, i32 width) { |
||||
|
pos_x = x; |
||||
|
pos_y = y + 10; |
||||
|
auto formatted = std::format("{}: {}", name, value); |
||||
|
auto new_width = 10 + MeasureText(formatted.c_str(), 10); |
||||
|
DrawRectangleLines(x, y, width, 20, BLACK); |
||||
|
DrawText(formatted.c_str(), x + 5, y + 5, 10, BLUE); |
||||
DrawCircle(x, y + 10, 2.5f, BLACK); |
DrawCircle(x, y + 10, 2.5f, BLACK); |
||||
|
return new_width; |
||||
} |
} |
||||
void Label::Render(i32 x, i32 y){ |
|
||||
DrawRectangleLines(x, y, 100, 20, BLACK); |
|
||||
|
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); |
DrawText(name.c_str(), x + 5, y + 5, 10, BLACK); |
||||
|
return 10 + MeasureText(name.c_str(), 10); |
||||
} |
} |
||||
|
|
||||
|
i32 StringUserInput::Render(i32 x, i32 y, i32 width) { |
||||
|
DrawRectangleLines(x, y, width, 20, BLACK); |
||||
|
if (data.empty()) { |
||||
|
DrawText(name.c_str(), x + 5, y + 5, 10, GRAY); |
||||
|
return 10 + MeasureText(name.c_str(), 10); |
||||
|
} else { |
||||
|
DrawText(data.c_str(), x + 5, y + 5, 10, BLACK); |
||||
|
return 10 + MeasureText(data.c_str(), 10); |
||||
|
} |
||||
} |
} |
||||
|
} // namespace ffmpegraph |
@ -1,8 +1,20 @@ |
|||||
|
#include <clopts.hh>
|
||||
|
#include <print>
|
||||
import Base; |
import Base; |
||||
import Application; |
import Application; |
||||
using namespace ffmpegraph; |
using namespace ffmpegraph; |
||||
|
|
||||
int main() { |
|
||||
|
namespace detail { |
||||
|
using namespace command_line_options; |
||||
|
using options = clopts< |
||||
|
help<>, |
||||
|
option<"--ffmpeg-path", "Path to ffmpeg, default is `ffmpeg'">, |
||||
|
positional<"savefile", "Savefile to load", file<>, false> |
||||
|
>; |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) { |
||||
|
auto opts = detail::options::parse(argc, argv); |
||||
Application app("FFMpeGraph"); |
Application app("FFMpeGraph"); |
||||
app.Run(); |
app.Run(); |
||||
return 0; |
return 0; |
||||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue