Bugfixes & Small Refactor

This commit is contained in:
Maddie Slockbower 2024-09-09 21:30:50 -04:00
parent 8a514da303
commit 2fbdfd14b9
12 changed files with 540 additions and 116 deletions

View File

@ -34,6 +34,7 @@ include_directories(External)
# Add External Libraries # Add External Libraries
add_subdirectory(External/open-cpp-utils) add_subdirectory(External/open-cpp-utils)
add_subdirectory(External/glw)
# Configure ImGui # Configure ImGui
set(IMGUI_BACKEND_SDL2 ON) set(IMGUI_BACKEND_SDL2 ON)
@ -77,6 +78,7 @@ target_link_libraries(OpenShaderDesigner PRIVATE
imgui-docking imgui-docking
imgui-extras imgui-extras
imnode-graph imnode-graph
glw
) )
# DOXYGEN ============================================================================================================== # DOXYGEN ==============================================================================================================

View File

@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(imgui-docking) set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
set(PROJECT_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
project(imgui-docking VERSION ${PROJECT_VERSION})
# Required Source Files # Required Source Files

View File

@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(open-cpp-utils) set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
set(PROJECT_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
project(open-cpp-utils VERSION ${PROJECT_VERSION})
set(OPENCPPUTILS_HEADERS set(OPENCPPUTILS_HEADERS
any.h any.h
@ -32,12 +37,11 @@ find_package(GTest)
add_executable(open-cpp-utils-test add_executable(open-cpp-utils-test
Test/Test.cpp Test/Test.cpp
${OPENCPPUTILS_HEADERS}
) )
target_link_libraries(open-cpp-utils-test PRIVATE target_link_libraries(open-cpp-utils-test PRIVATE
GTest::gtest GTest::gtest
open-cpp-utils
) )
endif () endif ()

View File

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2024 Medusa Slockbower
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -13,8 +13,6 @@
// limitations under the License. // limitations under the License.
// ===================================================================================================================== // =====================================================================================================================
#include <gtest/gtest.h>
#include "../object_pool.h" #include "../object_pool.h"

View File

@ -16,6 +16,8 @@
#ifndef SET_H #ifndef SET_H
#define SET_H #define SET_H
#include <set>
#include "hash_table.h" #include "hash_table.h"
namespace open_cpp_utils namespace open_cpp_utils
@ -23,6 +25,8 @@ namespace open_cpp_utils
template<typename T, class Hash = std::hash<T>, class Alloc = std::allocator<T>> using set = hash_table<T, Hash, Alloc>; template<typename T, class Hash = std::hash<T>, class Alloc = std::allocator<T>> using set = hash_table<T, Hash, Alloc>;
template<typename T, class Compare = std::less<T>, class Alloc = std::allocator<T>> using ordered_set = std::set<T, Compare, Alloc>;
} }
#endif //SET_H #endif //SET_H

View File

@ -33,16 +33,20 @@ inline static constexpr ImColor HeaderActiveColor = ImColor(0x82, 0x4C, 0x40);
inline static const std::string HeaderMarker = "\uF3B9 "; inline static const std::string HeaderMarker = "\uF3B9 ";
// ===================================================================================================================== // =====================================================================================================================
// Integral // Constants
// ===================================================================================================================== // =====================================================================================================================
struct Integral : public Node
// Integer -------------------------------------------------------------------------------------------------------------
struct Integer : public Node
{ {
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>; using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
Integral(ShaderGraph& graph, ImVec2 pos); Integer(ShaderGraph& graph, ImVec2 pos);
virtual ~Integral() = default; virtual ~Integer() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
@ -50,19 +54,17 @@ struct Integral : public Node
ValueType Value; ValueType Value;
}; };
RegisterNode("Math/Constants/Integral", Integral); RegisterNode("Math/Constants/Integer", Integer);
// ===================================================================================================================== // Unsigned Integer ----------------------------------------------------------------------------------------------------
// Unsigned Integral
// =====================================================================================================================
struct UnsignedIntegral : public Node struct UnsignedInteger : public Node
{ {
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>; using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
UnsignedIntegral(ShaderGraph& graph, ImVec2 pos); UnsignedInteger(ShaderGraph& graph, ImVec2 pos);
virtual ~UnsignedIntegral() = default; virtual ~UnsignedInteger() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
@ -70,12 +72,10 @@ struct UnsignedIntegral : public Node
ValueType Value; ValueType Value;
}; };
RegisterNode("Math/Constants/Unsigned Integral", UnsignedIntegral); RegisterNode("Math/Constants/Unsigned Integer", UnsignedInteger);
// ===================================================================================================================== // Scalar --------------------------------------------------------------------------------------------------------------
// Scalar
// =====================================================================================================================
struct Scalar : public Node struct Scalar : public Node
{ {
@ -93,9 +93,7 @@ struct Scalar : public Node
RegisterNode("Math/Constants/Scalar", Scalar); RegisterNode("Math/Constants/Scalar", Scalar);
// ===================================================================================================================== // Vector --------------------------------------------------------------------------------------------------------------
// Vector
// =====================================================================================================================
struct Vector : public Node struct Vector : public Node
{ {
@ -113,12 +111,29 @@ struct Vector : public Node
RegisterNode("Math/Constants/Vector", Vector); RegisterNode("Math/Constants/Vector", Vector);
// ===================================================================================================================== // =====================================================================================================================
// Add // Operations
// ===================================================================================================================== // =====================================================================================================================
struct Add : public Node // Math Op Prototype ---------------------------------------------------------------------------------------------------
struct MathOp : public Node
{
MathOp(ShaderGraph& graph, ImVec2 pos);
virtual ~MathOp() = default;
virtual bool CheckConnection(Pin *, Pin *) override;
virtual void ValidateConnections() override;
bool AllowMultiWidthInputs;
};
// Add -----------------------------------------------------------------------------------------------------------------
struct Add : public MathOp
{ {
Add(ShaderGraph& graph, ImVec2 pos); Add(ShaderGraph& graph, ImVec2 pos);
virtual ~Add() = default; virtual ~Add() = default;
@ -129,6 +144,82 @@ struct Add : public Node
RegisterNode("Math/Operators/Add", Add); RegisterNode("Math/Operators/Add", Add);
// Subtract ------------------------------------------------------------------------------------------------------------
struct Subtract : public MathOp
{
Subtract(ShaderGraph& graph, ImVec2 pos);
virtual ~Subtract() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override;
};
RegisterNode("Math/Operators/Subtract", Subtract);
// Multiply ------------------------------------------------------------------------------------------------------------
struct Multiply : public MathOp
{
Multiply(ShaderGraph& graph, ImVec2 pos);
virtual ~Multiply() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override;
};
RegisterNode("Math/Operators/Multiply", Multiply);
// Divide --------------------------------------------------------------------------------------------------------------
struct Divide : public MathOp
{
Divide(ShaderGraph& graph, ImVec2 pos);
virtual ~Divide() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override;
};
RegisterNode("Math/Operators/Divide", Divide);
// =====================================================================================================================
// Utilities
// =====================================================================================================================
// Make Vector ---------------------------------------------------------------------------------------------------------
struct MakeVector : public Node
{
MakeVector(ShaderGraph& graph, ImVec2 pos);
virtual ~MakeVector() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override;
};
RegisterNode("Math/Utilities/Make Vector", MakeVector);
// Break Vector ---------------------------------------------------------------------------------------------------------
struct BreakVector : public Node
{
BreakVector(ShaderGraph& graph, ImVec2 pos);
virtual ~BreakVector() = default;
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override;
};
RegisterNode("Math/Utilities/Break Vector", BreakVector);
} }
#endif //MATH_H #endif //MATH_H

View File

@ -25,6 +25,8 @@
#include <set> #include <set>
#include <stack> #include <stack>
#include <glm/glm.hpp>
#include <open-cpp-utils/startup.h> #include <open-cpp-utils/startup.h>
#include <open-cpp-utils/directed_tree.h> #include <open-cpp-utils/directed_tree.h>
#include <open-cpp-utils/optional.h> #include <open-cpp-utils/optional.h>
@ -47,8 +49,8 @@ namespace OpenShaderDesigner
using PinType = int; using PinType = int;
enum PinType_ enum PinType_
{ {
PinType_Int = 0 PinType_UInt = 0
, PinType_UInt , PinType_Int
, PinType_Float , PinType_Float
, PinType_Vector , PinType_Vector
@ -59,35 +61,46 @@ namespace OpenShaderDesigner
using PinFlags = unsigned int; using PinFlags = unsigned int;
enum PinFlags_ enum PinFlags_
{ {
PinFlags_None = 0 PinFlags_None = 0
, PinFlags_NoCollapse = 1 << 0 , PinFlags_NoCollapse = 1 << 0
, PinFlags_NoPadding = 1 << 1 , PinFlags_AlwaysCollapse = 1 << 1
, PinFlags_NoPadding = 1 << 2
, PinFlags_Ambiguous = 1 << 3
}; };
struct Pin struct Pin
{ {
inline const static ImColor Colors[PinType_COUNT] = { inline const static ImColor Colors[PinType_COUNT] = {
ImColor(0x64, 0x94, 0xAA) // Int ImColor(0x7A, 0x9F, 0x82) // Unsigned Int
, ImColor(0x7A, 0x9F, 0x82) // Unsigned Int , ImColor(0x64, 0x94, 0xAA) // Int
, ImColor(0xA6, 0x3D, 0x40) // Float , ImColor(0xA6, 0x3D, 0x40) // Float
, ImColor(0xE9, 0xB8, 0x72) // Vector , ImColor(0xE9, 0xB8, 0x72) // Vector
, ImColor(0xD2, 0xD5, 0xD3) // Any , ImColor(0xFF, 0xFF, 0xFF) // Any
}; };
inline const static std::string TypeNames[PinType_COUNT] = { inline const static std::string TypeNames[PinType_COUNT] = {
"Int" "Unsigned Int"
, "Unsigned Int" , "Int"
, "Float" , "Float"
, "Vector" , "Vector"
, "Any" , "Any"
}; };
using Ambiguous = ocu::any<int, unsigned int, float, ImVec4>; inline const static int TypeWidths[PinType_COUNT] = {
1 // Unsigned Int
, 1 // Int
, 1 // Float
, 3 // Vector
, -1 // Any
};
using Ambiguous = ocu::any<int, unsigned int, float, glm::vec3>;
std::string Name; std::string Name;
PinType Type; PinType Type;
PinFlags Flags; PinFlags Flags;
Ambiguous Value; Ambiguous Value;
ImPinPtr Ptr;
Pin(const std::string& name, PinType type, PinFlags flags = PinFlags_None) Pin(const std::string& name, PinType type, PinFlags flags = PinFlags_None)
: Name(name) : Name(name)
@ -99,7 +112,8 @@ namespace OpenShaderDesigner
struct Node struct Node
{ {
public: public:
ImVec2 Position = { 0, 0 }; ShaderGraph& Graph;
ImVec2 Position = { 0, 0 };
struct struct
{ {
@ -122,9 +136,11 @@ namespace OpenShaderDesigner
Node(ShaderGraph& graph, ImVec2 pos); Node(ShaderGraph& graph, ImVec2 pos);
~Node() = default; ~Node() = default;
void DrawPin(ImGuiID id, Pin& pin, ImPinDirection direction); void DrawPin(int id, Pin& pin, ImPinDirection direction);
void Draw(ImGuiID id); void Draw(ImGuiID id);
virtual bool CheckConnection(Pin*, Pin*) { return false; }
virtual void ValidateConnections() { }
virtual Node* Copy(ShaderGraph& graph) const = 0; virtual Node* Copy(ShaderGraph& graph) const = 0;
virtual void Inspect() = 0; virtual void Inspect() = 0;
}; };
@ -132,6 +148,19 @@ namespace OpenShaderDesigner
class ShaderGraph class ShaderGraph
: public EditorWindow : public EditorWindow
{ {
public:
struct GraphState
{
ShaderGraph& Parent;
ocu::object_list<Node*> Nodes;
GraphState(ShaderGraph& parent);
GraphState(const GraphState& other);
~GraphState();
GraphState& operator=(const GraphState& other);
};
private: private:
friend Node; friend Node;
@ -142,25 +171,10 @@ namespace OpenShaderDesigner
ConstructorPtr Constructor; ConstructorPtr Constructor;
}; };
struct GraphState
{
ShaderGraph& Parent;
ocu::object_list<Node*> Nodes;
GraphState(ShaderGraph& parent);
GraphState(const GraphState& other);
~GraphState();
GraphState& operator=(const GraphState& other);
};
using ContextMenuHierarchy = ocu::directed_tree<ContextMenuItem>; using ContextMenuHierarchy = ocu::directed_tree<ContextMenuItem>;
using ContextID = ContextMenuHierarchy::node; using ContextID = ContextMenuHierarchy::node;
inline static ContextMenuHierarchy ContextMenu; inline static ContextMenuHierarchy ContextMenu;
// History Functionality
void PushState();
void PopState();
public: public:
ShaderGraph(); ShaderGraph();
@ -175,7 +189,15 @@ namespace OpenShaderDesigner
void Erase(); void Erase();
void Paste(ImVec2 pos); void Paste(ImVec2 pos);
static void Register(const std::filesystem::path& path, ConstructorPtr constructor); Node* FindNode(ImPinPtr ptr);
Pin& FindPin(ImPinPtr ptr);
static void Register(const std::filesystem::path& path, ConstructorPtr constructor);
// History Functionality
void PushState();
void PopState();
GraphState& GetState() { return State; }
private: private:
bool GrabFocus; bool GrabFocus;

View File

@ -22,7 +22,7 @@ int main(int, char**)
Window::Configuration config; Window::Configuration config;
config.Application.Title = "OpenShaderDesigner"; config.Application.Title = "OpenShaderDesigner";
config.Video.Multisamples = 4; config.Video.Multisamples = 16;
config.Video.Fullscreen = Window::FullscreenMode::WINDOWED; config.Video.Fullscreen = Window::FullscreenMode::WINDOWED;
config.Video.Resolution = { 1280, 720 }; config.Video.Resolution = { 1280, 720 };
config.Video.HDR = false; config.Video.HDR = false;

View File

@ -16,65 +16,65 @@
#include <Graph/Nodes/Math.h> #include <Graph/Nodes/Math.h>
#include <imgui-extras/imgui_extras.h> #include <imgui-extras/imgui_extras.h>
#include <queue>
using namespace OpenShaderDesigner; using namespace OpenShaderDesigner;
using namespace OpenShaderDesigner::Nodes::Math; using namespace OpenShaderDesigner::Nodes::Math;
// ===================================================================================================================== // =====================================================================================================================
// Integral // Constants
// ===================================================================================================================== // =====================================================================================================================
Integral::Integral(ShaderGraph& graph, ImVec2 pos)
// Integer -------------------------------------------------------------------------------------------------------------
Integer::Integer(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos) : Node(graph, pos)
{ {
Header.Title = HeaderMarker + "Integral"; Header.Title = HeaderMarker + "Integer";
Header.Color = HeaderColor; Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor; Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor; Header.ActiveColor = HeaderActiveColor;
IO.Outputs.emplace_back("Out", PinType_Float, PinFlags_NoCollapse | PinFlags_NoPadding); IO.Outputs.emplace_back("Out", PinType_Int, PinFlags_NoCollapse | PinFlags_NoPadding);
} }
Node* Integral::Copy(ShaderGraph& graph) const Node* Integer::Copy(ShaderGraph& graph) const
{ {
return new Integral(graph, Position); return new Integer(graph, Position);
} }
void Integral::Inspect() void Integer::Inspect()
{ {
} }
// ===================================================================================================================== // Unsigned Integer ----------------------------------------------------------------------------------------------------
// Scalar
// =====================================================================================================================
UnsignedIntegral::UnsignedIntegral(ShaderGraph& graph, ImVec2 pos) UnsignedInteger::UnsignedInteger(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos) : Node(graph, pos)
{ {
Header.Title = HeaderMarker + "Unsigned Integral"; Header.Title = HeaderMarker + "Unsigned Integer";
Header.Color = HeaderColor; Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor; Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor; Header.ActiveColor = HeaderActiveColor;
IO.Outputs.emplace_back("Out", PinType_Float, PinFlags_NoCollapse | PinFlags_NoPadding); IO.Outputs.emplace_back("Out", PinType_UInt, PinFlags_NoCollapse | PinFlags_NoPadding);
} }
Node* UnsignedIntegral::Copy(ShaderGraph& graph) const Node* UnsignedInteger::Copy(ShaderGraph& graph) const
{ {
return new UnsignedIntegral(graph, Position); return new UnsignedInteger(graph, Position);
} }
void UnsignedIntegral::Inspect() void UnsignedInteger::Inspect()
{ {
} }
// ===================================================================================================================== // Scalar --------------------------------------------------------------------------------------------------------------
// Scalar
// =====================================================================================================================
Scalar::Scalar(ShaderGraph& graph, ImVec2 pos) Scalar::Scalar(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos) : Node(graph, pos)
@ -98,9 +98,7 @@ void Scalar::Inspect()
} }
// ===================================================================================================================== // Vector --------------------------------------------------------------------------------------------------------------
// Vector
// =====================================================================================================================
Vector::Vector(ShaderGraph &graph, ImVec2 pos) Vector::Vector(ShaderGraph &graph, ImVec2 pos)
: Node(graph, pos) : Node(graph, pos)
@ -112,7 +110,7 @@ Vector::Vector(ShaderGraph &graph, ImVec2 pos)
IO.Outputs.emplace_back("Out", PinType_Vector, PinFlags_NoCollapse | PinFlags_NoPadding); IO.Outputs.emplace_back("Out", PinType_Vector, PinFlags_NoCollapse | PinFlags_NoPadding);
IO.Outputs[0].Value.get<ImVec4>() = ImVec4(0, 0, 0, 1); IO.Outputs[0].Value.get<glm::vec3>() = glm::vec3(0);
} }
Node* Vector::Copy(ShaderGraph &graph) const Node* Vector::Copy(ShaderGraph &graph) const
@ -127,22 +125,84 @@ void Vector::Inspect()
// ===================================================================================================================== // =====================================================================================================================
// Add // Math Operations
// ===================================================================================================================== // =====================================================================================================================
// Math Operation Interface --------------------------------------------------------------------------------------------
MathOp::MathOp(ShaderGraph &graph, ImVec2 pos)
: Node(graph, pos)
, AllowMultiWidthInputs(false)
{
}
bool MathOp::CheckConnection(Pin* a, Pin* b)
{
if(AllowMultiWidthInputs) return false;
for(Pin& pin : IO.Inputs)
{
if(&pin == a) continue;
if((pin.Flags & PinFlags_Ambiguous) == false) continue;
if(ImNodeGraph::IsPinConnected(pin.Ptr) == false) continue;
if(pin.Type == PinType_Any) continue;
if(Pin::TypeWidths[pin.Type] != Pin::TypeWidths[b->Type]) return true;
}
return false;
}
void MathOp::ValidateConnections()
{
std::set<PinType> present;
for(Pin& pin : IO.Inputs)
{
if((pin.Flags & PinFlags_Ambiguous) == false) continue;
if(ImNodeGraph::IsPinConnected(pin.Ptr) == false) continue;
if(pin.Type == PinType_Any) continue;
present.insert(pin.Type);
}
PinType type = present.empty() ? PinType_Any : *present.rbegin();
for(Pin& pin : IO.Inputs)
{
if((pin.Flags & PinFlags_Ambiguous) == false) continue;
if(ImNodeGraph::IsPinConnected(pin.Ptr)) continue;
pin.Type = type;
}
for(Pin& pin : IO.Outputs)
{
if((pin.Flags & PinFlags_Ambiguous) == false) continue;
if(ImNodeGraph::IsPinConnected(pin.Ptr)) continue;
pin.Type = type;
}
}
// Add -----------------------------------------------------------------------------------------------------------------
Add::Add(ShaderGraph& graph, ImVec2 pos) Add::Add(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos) : MathOp(graph, pos)
{ {
Header.Title = HeaderMarker + "Add"; Header.Title = HeaderMarker + "Add";
Header.Color = HeaderColor; Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor; Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor; Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("A", PinType_Any); IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous);
IO.Inputs.emplace_back("B", PinType_Any); IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous);
IO.DynamicInputs = true; IO.DynamicInputs = true;
IO.Outputs.emplace_back("B", PinType_Any); IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous);
} }
Node* Add::Copy(ShaderGraph& graph) const Node* Add::Copy(ShaderGraph& graph) const
@ -154,3 +214,153 @@ void Add::Inspect()
{ {
} }
// Subtract ------------------------------------------------------------------------------------------------------------
Subtract::Subtract(ShaderGraph& graph, ImVec2 pos)
: MathOp(graph, pos)
{
Header.Title = HeaderMarker + "Subtract";
Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous);
IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous);
IO.DynamicInputs = true;
IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous);
}
Node* Subtract::Copy(ShaderGraph& graph) const
{
return new Subtract(graph, Position);
}
void Subtract::Inspect()
{
}
// Multiply ------------------------------------------------------------------------------------------------------------
Multiply::Multiply(ShaderGraph& graph, ImVec2 pos)
: MathOp(graph, pos)
{
Header.Title = HeaderMarker + "Multiply";
Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous);
IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous);
IO.DynamicInputs = true;
IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous);
AllowMultiWidthInputs = true;
}
Node* Multiply::Copy(ShaderGraph& graph) const
{
return new Multiply(graph, Position);
}
void Multiply::Inspect()
{
}
// Divide --------------------------------------------------------------------------------------------------------------
Divide::Divide(ShaderGraph& graph, ImVec2 pos)
: MathOp(graph, pos)
{
Header.Title = HeaderMarker + "Divide";
Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous);
IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous);
IO.DynamicInputs = true;
IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous);
AllowMultiWidthInputs = true;
}
Node* Divide::Copy(ShaderGraph& graph) const
{
return new Divide(graph, Position);
}
void Divide::Inspect()
{
}
// =====================================================================================================================
// Utilities
// =====================================================================================================================
// Make Vector ---------------------------------------------------------------------------------------------------------
MakeVector::MakeVector(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos)
{
Header.Title = HeaderMarker + "Make Vector";
Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("X", PinType_Float, PinFlags_AlwaysCollapse);
IO.Inputs.emplace_back("Y", PinType_Float, PinFlags_AlwaysCollapse);
IO.Inputs.emplace_back("Z", PinType_Float, PinFlags_AlwaysCollapse);
IO.Outputs.emplace_back("Out", PinType_Vector);
}
Node* MakeVector::Copy(ShaderGraph& graph) const
{
return new MakeVector(graph, Position);
}
void MakeVector::Inspect()
{
}
// Break Vector ---------------------------------------------------------------------------------------------------------
BreakVector::BreakVector(ShaderGraph& graph, ImVec2 pos)
: Node(graph, pos)
{
Header.Title = HeaderMarker + "Make Vector";
Header.Color = HeaderColor;
Header.HoveredColor = HeaderHoveredColor;
Header.ActiveColor = HeaderActiveColor;
IO.Inputs.emplace_back("In", PinType_Vector, PinFlags_AlwaysCollapse);
IO.Outputs.emplace_back("X", PinType_Float);
IO.Outputs.emplace_back("Y", PinType_Float);
IO.Outputs.emplace_back("Z", PinType_Float);
}
Node* BreakVector::Copy(ShaderGraph& graph) const
{
return new MakeVector(graph, Position);
}
void BreakVector::Inspect()
{
}

View File

@ -29,6 +29,21 @@
using namespace OpenShaderDesigner; using namespace OpenShaderDesigner;
static ShaderGraph* GCurrentGraph = nullptr;
static bool ValidateConnection(ImPinPtr a, ImPinPtr b)
{
ShaderGraph& Graph = *GCurrentGraph;
bool result = false;
result |= Graph.FindNode(a)->CheckConnection(&Graph.FindPin(a), &Graph.FindPin(b));
result |= Graph.FindNode(b)->CheckConnection(&Graph.FindPin(b), &Graph.FindPin(a));
return result;
}
ImColor operator*(const ImColor& c, float f) ImColor operator*(const ImColor& c, float f)
{ {
return ImVec4(c.Value.x * f, c.Value.y * f, c.Value.z * f, c.Value.w); return ImVec4(c.Value.x * f, c.Value.y * f, c.Value.z * f, c.Value.w);
@ -66,9 +81,9 @@ ShaderGraph::GraphState& ShaderGraph::GraphState::operator=(const GraphState& ot
return *this; return *this;
} }
Node::Node( Node::Node(ShaderGraph& graph, ImVec2 pos)
ShaderGraph& graph, ImVec2 pos) : Graph(graph)
: Position(pos) , Position(pos)
, Header , Header
{ {
.Title = "Node" .Title = "Node"
@ -87,16 +102,38 @@ Node::Node(
} }
{ } { }
void Node::DrawPin(ImGuiID id, Pin& pin, ImPinDirection direction) void Node::DrawPin(int id, Pin& pin, ImPinDirection direction)
{ {
ImPinFlags flags = 0; ImPinFlags flags = 0;
if(pin.Flags & PinFlags_NoPadding) flags |= ImPinFlags_NoPadding; if(pin.Flags & PinFlags_NoPadding) flags |= ImPinFlags_NoPadding;
ImNodeGraph::BeginPin(std::format("{}##{}", pin.Name, id).c_str(), pin.Type, direction, flags); bool res = ImNodeGraph::BeginPin(id, pin.Type, direction, flags);
pin.Ptr = ImNodeGraph::GetPinPtr();
if(res)
{
const ImVector<ImGuiID>& connections = ImNodeGraph::GetConnections();
const ImVector<ImPinPtr>& new_conns = ImNodeGraph::GetNewConnections();
bool connected = ImNodeGraph::IsPinConnected(); if(pin.Flags & PinFlags_Ambiguous)
{
if(connections.size() == new_conns.size() && new_conns.size() > 0)
{
Pin& first = Graph.FindPin(new_conns.front());
if(first.Type != PinType_Any) pin.Type = first.Type;
}
if((connected || pin.Type == PinType_Any) && !(pin.Flags & PinFlags_NoCollapse)) if(connections.size() == 0) pin.Type = PinType_Any;
}
ValidateConnections();
}
const bool connected = ImNodeGraph::IsPinConnected();
const bool any = pin.Type == PinType_Any;
const bool force_collapse = pin.Flags & PinFlags_AlwaysCollapse;
const bool no_collapse = pin.Flags & PinFlags_NoCollapse;
if((connected || any || direction || force_collapse) && !no_collapse)
{ {
ImGui::Text(pin.Name.c_str()); ImGui::Text(pin.Name.c_str());
} }
@ -107,25 +144,28 @@ void Node::DrawPin(ImGuiID id, Pin& pin, ImPinDirection direction)
case PinType_Int: case PinType_Int:
ImNodeGraph::PushItemWidth(200.0f); ImNodeGraph::PushItemWidth(200.0f);
ImGui::InputInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break; ImGui::InputInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
case PinType_UInt: case PinType_UInt:
ImNodeGraph::PushItemWidth(200.0f); ImNodeGraph::PushItemWidth(200.0f);
ImGui::InputUInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break; ImGui::InputUInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
case PinType_Float: case PinType_Float:
ImNodeGraph::PushItemWidth(100.0f); ImNodeGraph::PushItemWidth(100.0f);
ImGui::InputFloat(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break; ImGui::InputFloat(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
case PinType_Vector: case PinType_Vector:
ImGui::BeginGroup(); ImGui::BeginGroup();
// Color Picker // Color Picker
ImNodeGraph::PushItemWidth(150.0f); ImNodeGraph::PushItemWidth(150.0f);
ImGui::ColorPicker4( ImGui::ColorPicker3(
std::format("##in{}{}", pin.Name, id).c_str(), &pin.Value.get<ImVec4>().x std::format("##in{}{}", pin.Name, id).c_str(), &pin.Value.get<glm::vec3>().x
, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float , ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float
); );
ImNodeGraph::PushItemWidth(150.0f); ImNodeGraph::PushItemWidth(150.0f);
ImGui::ColorPreview( ImGui::ColorPreview3(
std::format("##invec{}{}", pin.Name, id).c_str(), &pin.Value.get<ImVec4>().x std::format("##invec{}{}", pin.Name, id).c_str(), &pin.Value.get<glm::vec3>().x
, ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float , ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float
); );
@ -150,8 +190,20 @@ void Node::Draw(ImGuiID id)
ImNodeGraph::EndNodeHeader(); ImNodeGraph::EndNodeHeader();
} }
for(Pin& pin : IO.Inputs) DrawPin(id, pin, ImPinDirection_Input); ImGuiID pid = 0;
for(Pin& pin : IO.Outputs) DrawPin(id, pin, ImPinDirection_Output); for(Pin& pin : IO.Inputs) DrawPin(++pid, pin, ImPinDirection_Input);
ImVec2 cursor = ImGui::GetCursorPos();
pid = 0;
for(Pin& pin : IO.Outputs) DrawPin(--pid, pin, ImPinDirection_Output);
ImGui::SetCursorPos(cursor);
//if(IO.DynamicInputs)
//{
// ImGui::Text("\uEA11");
//}
ImNodeGraph::EndNode(); ImNodeGraph::EndNode();
} }
@ -177,9 +229,13 @@ void ShaderGraph::OnOpen()
void ShaderGraph::DrawWindow() void ShaderGraph::DrawWindow()
{ {
GCurrentGraph = this;
ImNodeGraph::BeginGraph("ShaderGraph"); ImNodeGraph::BeginGraph("ShaderGraph");
ImNodeGraph::SetPinColors(Pin::Colors); ImNodeGraph::SetPinColors(Pin::Colors);
ImNodeGraph::SetGraphValidation(ValidateConnection);
if(GrabFocus) if(GrabFocus)
{ {
GrabFocus = false; GrabFocus = false;
@ -198,6 +254,20 @@ void ShaderGraph::DrawWindow()
ImNodeGraph::EndGraph(); ImNodeGraph::EndGraph();
ImNodeGraph::BeginGraphPostOp("ShaderGraph");
if(ImGui::IsKeyPressed(ImGuiKey_Delete))
{
auto& selected = ImNodeGraph::GetSelected();
for(ImGuiID node : selected)
{
State.Nodes.erase(ImNodeGraph::GetUserID(node).Int);
}
selected.Clear();
}
ImNodeGraph::EndGraphPostOp();
} }
@ -208,7 +278,7 @@ void ShaderGraph::DrawContextMenu()
ContextMenuPosition = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos()); ContextMenuPosition = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos());
} }
if(ImGui::BeginPopupContextWindow()) if(ImGui::BeginPopupContextWindow("graph_context"))
{ {
if(ImGui::MenuItem("Copy", "Ctrl+C", false, false)) Copy(); if(ImGui::MenuItem("Copy", "Ctrl+C", false, false)) Copy();
if(ImGui::MenuItem("Cut", "Ctrl+X", false, false)) if(ImGui::MenuItem("Cut", "Ctrl+X", false, false))
@ -294,6 +364,21 @@ void ShaderGraph::Copy() {}
void ShaderGraph::Erase() {} void ShaderGraph::Erase() {}
void ShaderGraph::Paste(ImVec2) {} void ShaderGraph::Paste(ImVec2) {}
Node* ShaderGraph::FindNode(ImPinPtr ptr)
{
return State.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int];
}
Pin& ShaderGraph::FindPin(ImPinPtr ptr)
{
Node* node = State.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int];
auto& pins = ptr.Direction ? node->IO.Outputs : node->IO.Inputs;
int idx = ImNodeGraph::GetUserID(ptr).Int;
if(ptr.Direction) idx *= -1;
idx -= 1;
return pins[idx];
}
void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr constructor) void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr constructor)
{ {
const std::string name = path.filename().string(); const std::string name = path.filename().string();

View File

@ -8,25 +8,26 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Dear ImGui Demo] [Window][Dear ImGui Demo]
Pos=171,229 Pos=3070,364
Size=375,341 Size=370,711
Collapsed=0 Collapsed=0
DockId=0x00000008,0
[Window][ Console] [Window][ Console]
Pos=303,953 Pos=303,1077
Size=3137,464 Size=3137,340
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
[Window][ Profiler] [Window][ Profiler]
Pos=0,953 Pos=0,1077
Size=301,464 Size=301,340
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][ Shader Graph] [Window][ Shader Graph]
Pos=0,0 Pos=0,0
Size=3068,951 Size=3068,1075
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
@ -65,16 +66,18 @@ Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=3070,0 Pos=3070,0
Size=370,951 Size=370,362
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000007,0
[Docking][Data] [Docking][Data]
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3440,1417 Split=Y DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3440,1417 Split=Y
DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,974 Split=X DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,378 Split=X
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=3068,1417 CentralNode=1 Selected=0xD4C89E35 DockNode ID=0x00000005 Parent=0x00000001 SizeRef=3068,1417 CentralNode=1 Selected=0xD4C89E35
DockNode ID=0x00000006 Parent=0x00000001 SizeRef=370,1417 Selected=0xE7039252 DockNode ID=0x00000006 Parent=0x00000001 SizeRef=370,1417 Split=Y Selected=0xE7039252
DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,464 Split=X Selected=0xE9F1AFD1 DockNode ID=0x00000007 Parent=0x00000006 SizeRef=370,127 Selected=0xE7039252
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=301,448 Selected=0xAC4B19AE DockNode ID=0x00000008 Parent=0x00000006 SizeRef=370,249 Selected=0xE87781F4
DockNode ID=0x00000004 Parent=0x00000002 SizeRef=3137,448 Selected=0xE9F1AFD1 DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,340 Split=X Selected=0xE9F1AFD1
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=301,448 Selected=0xAC4B19AE
DockNode ID=0x00000004 Parent=0x00000002 SizeRef=3137,448 Selected=0xE9F1AFD1