Updates to libraries
This commit is contained in:
parent
593760dd92
commit
8a514da303
6
External/open-cpp-utils/CMakeLists.txt
vendored
6
External/open-cpp-utils/CMakeLists.txt
vendored
@ -10,6 +10,12 @@ set(OPENCPPUTILS_HEADERS
|
|||||||
startup.h
|
startup.h
|
||||||
template_utils.h
|
template_utils.h
|
||||||
unique_id.h
|
unique_id.h
|
||||||
|
dynarray.h
|
||||||
|
redec.h
|
||||||
|
hash_table.h
|
||||||
|
math.h
|
||||||
|
set.h
|
||||||
|
map.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(open-cpp-utils INTERFACE
|
add_library(open-cpp-utils INTERFACE
|
||||||
|
7
External/open-cpp-utils/any.h
vendored
7
External/open-cpp-utils/any.h
vendored
@ -65,10 +65,17 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// Assignment operators ------------------------------------------------------------------------------------------------
|
// Assignment operators ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
any& operator=(const any&) = default;
|
any& operator=(const any&) = default;
|
||||||
any& operator=(any&&) = default;
|
any& operator=(any&&) = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Access --------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename V>
|
||||||
|
V& get() { static_assert(std::disjunction<std::is_same<V, T>, std::is_same<V, Rest>...>{}); return static_cast<V&>(*this); }
|
||||||
|
|
||||||
|
|
||||||
// Cast operators ------------------------------------------------------------------------------------------------------
|
// Cast operators ------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
operator reference() { return Value; }
|
operator reference() { return Value; }
|
||||||
|
104
External/open-cpp-utils/directed_tree.h
vendored
104
External/open-cpp-utils/directed_tree.h
vendored
@ -42,7 +42,7 @@ public:
|
|||||||
class unordered;
|
class unordered;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct director;
|
struct Node_;
|
||||||
|
|
||||||
|
|
||||||
// Typedefs ============================================================================================================
|
// Typedefs ============================================================================================================
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
using node_queue = std::deque<node>;
|
using node_queue = std::deque<node>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using hierarchy = std::vector<director>;
|
using hierarchy = std::vector<Node_>;
|
||||||
using storage = std::vector<data_type>;
|
using storage = std::vector<data_type>;
|
||||||
|
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
// Data Structures =====================================================================================================
|
// Data Structures =====================================================================================================
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct director
|
struct Node_
|
||||||
{
|
{
|
||||||
enum flags
|
enum flags
|
||||||
{
|
{
|
||||||
@ -76,7 +76,7 @@ private:
|
|||||||
node parent, child, prev_sibling, next_sibling;
|
node parent, child, prev_sibling, next_sibling;
|
||||||
uint32_t flags, depth;
|
uint32_t flags, depth;
|
||||||
|
|
||||||
director() : parent(0), child(0), prev_sibling(0), next_sibling(0), flags(VALID), depth(0) { }
|
Node_() : parent(0), child(0), prev_sibling(0), next_sibling(0), flags(VALID), depth(0) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* \brief Default constructor, creates tree with empty root
|
* \brief Default constructor, creates tree with empty root
|
||||||
*/
|
*/
|
||||||
directed_tree() : graph_{ director() }, data_{ data_type() }, freed_{ } { }
|
directed_tree() : graph_{ Node_() }, data_{ data_type() }, freed_{ } { }
|
||||||
|
|
||||||
|
|
||||||
// Tree Navigation -----------------------------------------------------------------------------------------------------
|
// Tree Navigation -----------------------------------------------------------------------------------------------------
|
||||||
@ -99,7 +99,7 @@ public:
|
|||||||
* \param id Node id to reference
|
* \param id Node id to reference
|
||||||
* \return Whether the valid flag is true in the node
|
* \return Whether the valid flag is true in the node
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool valid(node id) const { return graph_[id].flags & director::VALID; }
|
[[nodiscard]] bool valid(node id) const { return graph_[id].flags & Node_::VALID; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the parent of a node. O(1)
|
* \brief Get the parent of a node. O(1)
|
||||||
@ -115,6 +115,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] node first_child(node id) const { return graph_[id].child; }
|
[[nodiscard]] node first_child(node id) const { return graph_[id].child; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the first child of a node. O(1)
|
||||||
|
* \param id Node id to reference
|
||||||
|
* \return Node id of the first child
|
||||||
|
*/
|
||||||
|
[[nodiscard]] node last_child(node id) const
|
||||||
|
{
|
||||||
|
node c = first_child(id);
|
||||||
|
|
||||||
|
while(c != 0) { if(graph_[c].next_sibling == 0) break; c = graph_[c].next_sibling; }
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the previous sibling of a node. O(1)
|
* \brief Get the previous sibling of a node. O(1)
|
||||||
* \param id Node id to reference
|
* \param id Node id to reference
|
||||||
@ -164,47 +178,63 @@ public:
|
|||||||
* \brief Insert a node into the tree as a child of the provided node
|
* \brief Insert a node into the tree as a child of the provided node
|
||||||
* \param data Value to insert
|
* \param data Value to insert
|
||||||
* \param p_id Id of the parent node
|
* \param p_id Id of the parent node
|
||||||
|
* \param last Whether to insert at the back of the array
|
||||||
* \return Id of the inserted node
|
* \return Id of the inserted node
|
||||||
*/
|
*/
|
||||||
node insert(const data_type& data, node p_id)
|
node insert(const data_type& data, node p_id, bool last = true)
|
||||||
{
|
{
|
||||||
// If there are no freed nodes, create a new node and mark it as freed
|
// If there are no freed nodes, create a new node and mark it as freed
|
||||||
if(freed_.empty())
|
if(freed_.empty())
|
||||||
{
|
{
|
||||||
freed_.push_back(static_cast<node>(graph_.size()));
|
freed_.push_back(static_cast<node>(graph_.size()));
|
||||||
graph_.push_back(director()); data_.push_back(data);
|
graph_.push_back(Node_()); data_.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop a freed node from the stack
|
// Pop a freed node from the stack
|
||||||
node id = freed_.front(); freed_.pop_front();
|
node id = freed_.front(); freed_.pop_front();
|
||||||
director& node = graph_[id];
|
Node_& node = graph_[id];
|
||||||
director& parent = graph_[p_id];
|
Node_& parent = graph_[p_id];
|
||||||
|
|
||||||
// If the parent has a child, update the child's references
|
// If the parent has a child, update the child's references
|
||||||
if(parent.child)
|
if(parent.child && !last)
|
||||||
{
|
{
|
||||||
// Update the next child
|
// Update the next child
|
||||||
director& nchild = graph_[parent.child];
|
Node_& nchild = graph_[parent.child];
|
||||||
node.prev_sibling = nchild.prev_sibling;
|
node.prev_sibling = nchild.prev_sibling;
|
||||||
nchild.prev_sibling = id;
|
nchild.prev_sibling = id;
|
||||||
|
|
||||||
// If present, update the previous child
|
// If present, update the previous child
|
||||||
if(nchild.prev_sibling)
|
if(nchild.prev_sibling)
|
||||||
{
|
{
|
||||||
director& pchild = graph_[nchild.prev_sibling];
|
Node_& pchild = graph_[nchild.prev_sibling];
|
||||||
pchild.next_sibling = id;
|
pchild.next_sibling = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup node
|
// Setup node
|
||||||
node.parent = p_id;
|
node.parent = p_id;
|
||||||
node.next_sibling = parent.child;
|
node.next_sibling = last ? 0 : parent.child;
|
||||||
node.child = 0;
|
node.child = 0;
|
||||||
node.flags = director::VALID;
|
node.flags = Node_::VALID;
|
||||||
node.depth = parent.depth + 1;
|
node.depth = parent.depth + 1;
|
||||||
|
|
||||||
// Set parent's child
|
// Set parent's child
|
||||||
parent.child = id;
|
if(last)
|
||||||
|
{
|
||||||
|
directed_tree::node idx = last_child(p_id);
|
||||||
|
|
||||||
|
if(idx)
|
||||||
|
{
|
||||||
|
Node_& lchild = graph_[idx];
|
||||||
|
lchild.next_sibling = id;
|
||||||
|
node.prev_sibling = idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.child = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else parent.child = id;
|
||||||
|
|
||||||
// Set the data
|
// Set the data
|
||||||
data_[id] = data;
|
data_[id] = data;
|
||||||
@ -221,8 +251,8 @@ public:
|
|||||||
if(id == 0) return;
|
if(id == 0) return;
|
||||||
|
|
||||||
// Mark node as invalid and push it to the freed list
|
// Mark node as invalid and push it to the freed list
|
||||||
director& erased = graph_[id];
|
Node_& erased = graph_[id];
|
||||||
erased.Flags &= ~director::VALID;
|
erased.Flags &= ~Node_::VALID;
|
||||||
freed_.push_back(id);
|
freed_.push_back(id);
|
||||||
|
|
||||||
// Update the parent's child
|
// Update the parent's child
|
||||||
@ -237,8 +267,8 @@ public:
|
|||||||
while(stack.empty() == false)
|
while(stack.empty() == false)
|
||||||
{
|
{
|
||||||
node next = stack.front(); stack.pop_front();
|
node next = stack.front(); stack.pop_front();
|
||||||
director& child = graph_[next];
|
Node_& child = graph_[next];
|
||||||
child.Flags &= ~director::VALID;
|
child.Flags &= ~Node_::VALID;
|
||||||
freed_.push_back(next);
|
freed_.push_back(next);
|
||||||
|
|
||||||
if(child.Sibling) stack.push_front(child.Sibling);
|
if(child.Sibling) stack.push_front(child.Sibling);
|
||||||
@ -326,7 +356,7 @@ public:
|
|||||||
node operator()(node id)
|
node operator()(node id)
|
||||||
{
|
{
|
||||||
id = visit_queue_.back(); visit_queue_.pop_back();
|
id = visit_queue_.back(); visit_queue_.pop_back();
|
||||||
director& current = graph_.graph_[id];
|
Node_& current = graph_.graph_[id];
|
||||||
|
|
||||||
if(current.next_sibling) visit_queue_.push_back(current.next_sibling);
|
if(current.next_sibling) visit_queue_.push_back(current.next_sibling);
|
||||||
if(current.child) visit_queue_.push_front(current.child);
|
if(current.child) visit_queue_.push_front(current.child);
|
||||||
@ -351,7 +381,7 @@ public:
|
|||||||
|
|
||||||
node operator()(node id)
|
node operator()(node id)
|
||||||
{
|
{
|
||||||
director& current = graph_.graph_[id];
|
Node_& current = graph_.graph_[id];
|
||||||
|
|
||||||
if(current.next_sibling) visit_queue_.push_front(current.next_sibling);
|
if(current.next_sibling) visit_queue_.push_front(current.next_sibling);
|
||||||
if(current.child) visit_queue_.push_front(current.child);
|
if(current.child) visit_queue_.push_front(current.child);
|
||||||
@ -375,12 +405,12 @@ public:
|
|||||||
public:
|
public:
|
||||||
in_order(directed_tree& graph) : graph_(graph) { }
|
in_order(directed_tree& graph) : graph_(graph) { }
|
||||||
|
|
||||||
node operator()(node node)
|
node operator()(node id)
|
||||||
{
|
{
|
||||||
if(node == 0) visit_queue_.push_back(graph_.left_most(node));
|
if(id == 0) visit_queue_.push_back(graph_.left_most(id));
|
||||||
|
|
||||||
node = visit_queue_.front(); visit_queue_.pop_front();
|
id = visit_queue_.front(); visit_queue_.pop_front();
|
||||||
director& current = graph_.graph_[node];
|
Node_& current = graph_.graph_[id];
|
||||||
|
|
||||||
if(current.Sibling)
|
if(current.Sibling)
|
||||||
{
|
{
|
||||||
@ -388,7 +418,7 @@ public:
|
|||||||
visit_queue_.push_back(graph_.left_most(current.Sibling));
|
visit_queue_.push_back(graph_.left_most(current.Sibling));
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -405,17 +435,17 @@ public:
|
|||||||
public:
|
public:
|
||||||
post_order(directed_tree& graph) : graph_(graph) { }
|
post_order(directed_tree& graph) : graph_(graph) { }
|
||||||
|
|
||||||
node operator()(node node)
|
node operator()(node id)
|
||||||
{
|
{
|
||||||
if(visit_queue_.empty()) visit_queue_.push_back(graph_.left_most(node));
|
if(visit_queue_.empty()) visit_queue_.push_back(graph_.left_most(id));
|
||||||
|
|
||||||
node = visit_queue_.front(); visit_queue_.pop_front();
|
id = visit_queue_.front(); visit_queue_.pop_front();
|
||||||
if(node == 0) return node;
|
if(id == 0) return id;
|
||||||
director& current = graph_.graph_[node];
|
Node_& current = graph_.graph_[id];
|
||||||
|
|
||||||
visit_queue_.push_back(current.Sibling ? graph_.left_most(current.Sibling) : graph_.parent(node));
|
visit_queue_.push_back(current.Sibling ? graph_.left_most(current.Sibling) : graph_.parent(id));
|
||||||
|
|
||||||
return node;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -438,10 +468,10 @@ public:
|
|||||||
|
|
||||||
void operator()()
|
void operator()()
|
||||||
{
|
{
|
||||||
node node = 0;
|
node id = 0;
|
||||||
while(node = order_(node))
|
while(id = order_(id))
|
||||||
{
|
{
|
||||||
if(visitor_(graph_[node], node)) break;
|
if(visitor_(graph_[id], id)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
External/open-cpp-utils/dynarray.h
vendored
Normal file
30
External/open-cpp-utils/dynarray.h
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef DYNARRAY_H
|
||||||
|
#define DYNARRAY_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace open_cpp_utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, class Alloc = std::allocator<T>>
|
||||||
|
using dynarray = std::vector<T, Alloc>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //DYNARRAY_H
|
300
External/open-cpp-utils/hash_table.h
vendored
Normal file
300
External/open-cpp-utils/hash_table.h
vendored
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef HASH_TABLE_H
|
||||||
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "optional.h"
|
||||||
|
|
||||||
|
namespace open_cpp_utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, class Hash = std::hash<T>, class Alloc = std::allocator<T>>
|
||||||
|
class hash_table
|
||||||
|
{
|
||||||
|
// Typedefs ============================================================================================================
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend class iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct _Node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
|
||||||
|
using hash_type = Hash;
|
||||||
|
using allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<_Node>;
|
||||||
|
|
||||||
|
using size_type = size_t;
|
||||||
|
using iterator_type = iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using table_type = _Node*;
|
||||||
|
using node = int64_t;
|
||||||
|
static constexpr node nullnode = std::integral_constant<node, -1>{};
|
||||||
|
|
||||||
|
|
||||||
|
// Structs =============================================================================================================
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct _Node
|
||||||
|
{
|
||||||
|
optional<T> value;
|
||||||
|
int psl;
|
||||||
|
|
||||||
|
_Node() : value(), psl(0) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Functions ===========================================================================================================
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors & Destructor -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
hash_table() : table_(nullptr), capacity_(0), size_(0), load_factor_(0.8), hash_(), alloc_() { }
|
||||||
|
hash_table(const hash_table&);
|
||||||
|
hash_table(hash_table&&) = default; // Default Move Constructor should suffice
|
||||||
|
~hash_table() { clear(); }
|
||||||
|
|
||||||
|
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void insert(const_reference x);
|
||||||
|
void erase(const_reference x);
|
||||||
|
bool contains(const_reference x);
|
||||||
|
iterator find(const_reference x) const { node res = _find(x); return iterator(this, res == nullnode ? capacity_ : res); }
|
||||||
|
|
||||||
|
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] size_type capacity() const { return capacity_; }
|
||||||
|
[[nodiscard]] size_type size() const { return size_; }
|
||||||
|
[[nodiscard]] bool empty() const { return size_ == 0; }
|
||||||
|
[[nodiscard]] double occupancy() const { return size_ / static_cast<double>(capacity_); }
|
||||||
|
|
||||||
|
// Helpers -------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _increase_capacity();
|
||||||
|
|
||||||
|
[[nodiscard]] node _hash(const_reference v) const;
|
||||||
|
[[nodiscard]] node _find(const_reference x) const;
|
||||||
|
[[nodiscard]] node _next(node n) const { return (n + 1) % capacity_; }
|
||||||
|
[[nodiscard]] node _prev(node n) const { return (n - 1 + capacity_) % capacity_; }
|
||||||
|
|
||||||
|
static size_type _next_prime(size_type x);
|
||||||
|
static size_type _prev_prime(size_type x);
|
||||||
|
|
||||||
|
|
||||||
|
// Iterators ===========================================================================================================
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
iterator(hash_table* table, int idx) : table_(table), idx_(idx) { _next_index(); }
|
||||||
|
iterator(const iterator&) = default;
|
||||||
|
iterator(iterator&&) = default;
|
||||||
|
~iterator() = default;
|
||||||
|
|
||||||
|
iterator& operator++() { ++idx_; _next_index(); return *this; }
|
||||||
|
iterator operator++(int) { iterator ret = *this; ++idx_; _next_index(); return ret; }
|
||||||
|
|
||||||
|
bool operator==(const iterator& o) const = default;
|
||||||
|
bool operator!=(const iterator& o) const = default;
|
||||||
|
|
||||||
|
reference operator*() const { return table_->table_[idx_].value; }
|
||||||
|
pointer operator->() const { return &table_->table_[idx_].value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _next_index() { while(idx_ < table_->capacity_ && table_[idx_].value()) ++idx_; }
|
||||||
|
|
||||||
|
hash_table* table_;
|
||||||
|
int idx_;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return iterator(this, 0); }
|
||||||
|
iterator end() { return iterator(this, capacity_); }
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===========================================================================================================
|
||||||
|
|
||||||
|
private:
|
||||||
|
table_type table_;
|
||||||
|
size_type capacity_, size_;
|
||||||
|
double load_factor_;
|
||||||
|
hash_type hash_;
|
||||||
|
allocator_type alloc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
hash_table<T, Hash, Alloc>::hash_table(const hash_table& other)
|
||||||
|
: table_(nullptr)
|
||||||
|
, capacity_(other.capacity_)
|
||||||
|
, size_(other.size_)
|
||||||
|
, load_factor_(0.8)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
void hash_table<T, Hash, Alloc>::clear()
|
||||||
|
{
|
||||||
|
alloc_.deallocate(table_, capacity_);
|
||||||
|
capacity_ = size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
void hash_table<T, Hash, Alloc>::insert(const_reference x)
|
||||||
|
{
|
||||||
|
if(occupancy() > load_factor_ || capacity_ == 0) _increase_capacity();
|
||||||
|
|
||||||
|
node idx = _hash(x);
|
||||||
|
int psl = 0;
|
||||||
|
T value = x;
|
||||||
|
|
||||||
|
while(table_[idx].value())
|
||||||
|
{
|
||||||
|
_Node& node = table_[idx];
|
||||||
|
|
||||||
|
if(node.value == x) return;
|
||||||
|
if(psl > node.psl) { std::swap(psl, node.psl); std::swap(value, node.value); }
|
||||||
|
|
||||||
|
idx = _next(idx);
|
||||||
|
++psl;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_[idx].value = value;
|
||||||
|
table_[idx].psl = psl;
|
||||||
|
++size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
void hash_table<T, Hash, Alloc>::erase(const_reference x)
|
||||||
|
{
|
||||||
|
node idx = _find(x);
|
||||||
|
if(idx == nullnode) return;
|
||||||
|
|
||||||
|
table_[idx].value.reset();
|
||||||
|
--size_;
|
||||||
|
|
||||||
|
node prev = idx; idx = _next(idx);
|
||||||
|
while(table_[idx].value() && table_[idx].psl > 0)
|
||||||
|
{
|
||||||
|
_Node &a = table_[prev], &b = table_[idx];
|
||||||
|
std::swap(a, b);
|
||||||
|
--a.psl; prev = idx; idx = _next(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
bool hash_table<T, Hash, Alloc>::contains(const_reference x)
|
||||||
|
{
|
||||||
|
return _find(x) != nullnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
void hash_table<T, Hash, Alloc>::_increase_capacity()
|
||||||
|
{
|
||||||
|
table_type old = table_;
|
||||||
|
size_type old_capacity = capacity_;
|
||||||
|
capacity_ = _next_prime(capacity_);
|
||||||
|
table_ = alloc_.allocate(capacity_);
|
||||||
|
memset(table_, 0, capacity_ * sizeof(_Node));
|
||||||
|
size_ = 0;
|
||||||
|
|
||||||
|
for(node i = 0; i < old_capacity; ++i)
|
||||||
|
{
|
||||||
|
if(old[i].value()) insert(old[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc_.deallocate(old, old_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
typename hash_table<T, Hash, Alloc>::node hash_table<T, Hash, Alloc>::_hash(const_reference v) const
|
||||||
|
{
|
||||||
|
node x = hash_(v);
|
||||||
|
|
||||||
|
x ^= x >> 33U;
|
||||||
|
x *= UINT64_C(0xff51afd7ed558ccd);
|
||||||
|
x ^= x >> 33U;
|
||||||
|
x *= UINT64_C(0xc4ceb9fe1a85ec53);
|
||||||
|
x ^= x >> 33U;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
typename hash_table<T, Hash, Alloc>::node hash_table<T, Hash, Alloc>::_find(const_reference x) const
|
||||||
|
{
|
||||||
|
if(capacity_ == 0) return nullnode;
|
||||||
|
node idx = _hash(x);
|
||||||
|
int psl = 0;
|
||||||
|
|
||||||
|
while(table_[idx].value())
|
||||||
|
{
|
||||||
|
_Node& node = table_[idx];
|
||||||
|
|
||||||
|
if(node.psl > psl) return nullnode;
|
||||||
|
if(node.value == x) return idx;
|
||||||
|
|
||||||
|
idx = _next(idx); ++psl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
typename hash_table<T, Hash, Alloc>::size_type hash_table<T, Hash, Alloc>::_next_prime(size_type x)
|
||||||
|
{
|
||||||
|
size_type n = (x + 1) / 6;
|
||||||
|
n *= 2;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
x = (n * 6) - 1;
|
||||||
|
if(!is_prime(x)) x = (n * 6) + 1;
|
||||||
|
if(!is_prime(x)) { ++n; continue; }
|
||||||
|
return std::max(x, 7ull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, class Hash, class Alloc>
|
||||||
|
typename hash_table<T, Hash, Alloc>::size_type hash_table<T, Hash, Alloc>::_prev_prime(size_type x)
|
||||||
|
{
|
||||||
|
size_type n = (x + 1) / 6;
|
||||||
|
n *= 2;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
x = (n * 6) - 1;
|
||||||
|
if(!is_prime(x)) x = (n * 6) + 1;
|
||||||
|
if(!is_prime(x)) { --n; continue; }
|
||||||
|
return std::max(x, 7ull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //HASH_TABLE_H
|
100
External/open-cpp-utils/map.h
vendored
Normal file
100
External/open-cpp-utils/map.h
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef MAP_H
|
||||||
|
#define MAP_H
|
||||||
|
#include "set.h"
|
||||||
|
|
||||||
|
namespace open_cpp_utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename Key, typename Value, class Alloc = std::allocator<std::pair<Key, Value>>>
|
||||||
|
class map
|
||||||
|
{
|
||||||
|
// Typedefs ============================================================================================================
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct hash { size_t operator()(const pair_type& pair) const { return std::hash<key_type>{}(pair.first); } };
|
||||||
|
|
||||||
|
using key_type = Key;
|
||||||
|
using value_type = Value;
|
||||||
|
using pair_type = std::pair<key_type, value_type>;
|
||||||
|
using table_type = set<pair_type, hash, Alloc>;
|
||||||
|
|
||||||
|
using key_pointer = key_type*;
|
||||||
|
using const_key_pointer = const key_type*;
|
||||||
|
using key_reference = key_type&;
|
||||||
|
using const_key_reference = const key_type&;
|
||||||
|
|
||||||
|
using value_pointer = value_type*;
|
||||||
|
using const_value_pointer = const value_type*;
|
||||||
|
using value_reference = value_type&;
|
||||||
|
using const_value_reference = const value_type&;
|
||||||
|
|
||||||
|
using iterator = typename table_type::iterator;
|
||||||
|
|
||||||
|
|
||||||
|
// Functions ===========================================================================================================
|
||||||
|
|
||||||
|
// Constructors & Destructor -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public:
|
||||||
|
map() = default;
|
||||||
|
map(const map&) = default;
|
||||||
|
map(map&&) = default;
|
||||||
|
~map() = default;
|
||||||
|
|
||||||
|
void insert(const_key_reference key, const_value_reference value);
|
||||||
|
void erase(const_key_reference key);
|
||||||
|
value_reference& operator[](const_key_reference key);
|
||||||
|
iterator find() { return table_->find(); }
|
||||||
|
bool contains(const_key_reference key) { return table_.contains({ key, value_type() }); }
|
||||||
|
|
||||||
|
iterator begin() { return table_.begin(); }
|
||||||
|
iterator end() { return table_.end(); }
|
||||||
|
|
||||||
|
// Variables ===========================================================================================================
|
||||||
|
|
||||||
|
private:
|
||||||
|
set<pair_type, hash, Alloc> table_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Key, typename Value, class Alloc>
|
||||||
|
void map<Key, Value, Alloc>::insert(const_key_reference key, const_value_reference value)
|
||||||
|
{
|
||||||
|
iterator it = find({ key, value });
|
||||||
|
if(it != end()) table_.insert({ key, value });
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Key, typename Value, class Alloc>
|
||||||
|
void map<Key, Value, Alloc>::erase(const_key_reference key)
|
||||||
|
{
|
||||||
|
table_.erase({ key, value_type() });
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Key, typename Value, class Alloc>
|
||||||
|
typename map<Key, Value, Alloc>::value_reference map<Key, Value, Alloc>::operator[](const_key_reference key)
|
||||||
|
{
|
||||||
|
iterator it = table_.find({ key, value_type() });
|
||||||
|
if(it == table_.end())
|
||||||
|
{
|
||||||
|
table_.insert({ key, value_type() });
|
||||||
|
it = table_.find({ key, value_type() });
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MAP_H
|
42
External/open-cpp-utils/math.h
vendored
Normal file
42
External/open-cpp-utils/math.h
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef MATH_H
|
||||||
|
#define MATH_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace open_cpp_utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool is_prime(T x)
|
||||||
|
{
|
||||||
|
if(x <= 1) return false;
|
||||||
|
if(x == 2 || x == 3) return true;
|
||||||
|
if(x % 2 == 0 || x % 3 == 0) return false;
|
||||||
|
|
||||||
|
T limit = sqrt(x);
|
||||||
|
for(T i = 5; i <= limit; i += 6)
|
||||||
|
{
|
||||||
|
if(x % i == 0 || x % (i + 2) == 0) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MATH_H
|
82
External/open-cpp-utils/object_pool.h
vendored
82
External/open-cpp-utils/object_pool.h
vendored
@ -16,18 +16,18 @@
|
|||||||
#ifndef OBJECT_POOL_H
|
#ifndef OBJECT_POOL_H
|
||||||
#define OBJECT_POOL_H
|
#define OBJECT_POOL_H
|
||||||
|
|
||||||
#include <stack>
|
#include "dynarray.h"
|
||||||
#include <vector>
|
#include "optional.h"
|
||||||
#include <tuple>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "template_utils.h"
|
|
||||||
|
|
||||||
namespace open_cpp_utils
|
namespace open_cpp_utils
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T, typename _Hash = std::unordered_map<uint64_t, int64_t>>
|
/**
|
||||||
class object_pool
|
* \brief
|
||||||
|
* \tparam T
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class object_list
|
||||||
{
|
{
|
||||||
// Typedefs ============================================================================================================
|
// Typedefs ============================================================================================================
|
||||||
|
|
||||||
@ -38,17 +38,10 @@ public:
|
|||||||
using reference = T&;
|
using reference = T&;
|
||||||
using const_reference = const T&;
|
using const_reference = const T&;
|
||||||
|
|
||||||
using index_type = int64_t;
|
|
||||||
using uuid_type = uint64_t;
|
using uuid_type = uint64_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using node = std::tuple<value_type, bool>;
|
using node = optional<value_type>;
|
||||||
|
|
||||||
|
|
||||||
// Constants ===========================================================================================================
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr std::integral_constant<index_type, -1> nullidx{};
|
|
||||||
|
|
||||||
|
|
||||||
// Functions ===========================================================================================================
|
// Functions ===========================================================================================================
|
||||||
@ -57,33 +50,62 @@ public:
|
|||||||
|
|
||||||
// Constructors & Destructor -------------------------------------------------------------------------------------------
|
// Constructors & Destructor -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
object_pool();
|
object_list() = default;
|
||||||
|
object_list(const object_list& other) = default;
|
||||||
|
object_list(object_list&& other) = default;
|
||||||
|
~object_list() = default;
|
||||||
|
|
||||||
void clear();
|
|
||||||
void reset();
|
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||||
void cleanup();
|
|
||||||
|
size_t size() { return data_.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void clear() { data_.clear(); freed_.clear(); }
|
||||||
|
|
||||||
uuid_type insert(const_reference& value);
|
uuid_type insert(const_reference& value);
|
||||||
void erase(uuid_type id);
|
void erase(uuid_type id);
|
||||||
void erase(index_type idx);
|
|
||||||
|
object_list& operator=(const object_list&) = default;
|
||||||
|
object_list& operator=(object_list&&) = default;
|
||||||
|
|
||||||
|
|
||||||
// Accessors -----------------------------------------------------------------------------------------------------------
|
// Accessors -----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
reference operator[](uuid_type id);
|
reference operator[](uuid_type id) { assert(data_[id]()); return data_[id]; }
|
||||||
const_reference operator[](uuid_type id) const;
|
const_reference operator[](uuid_type id) const { assert(data_[id]()); return data_[id]; }
|
||||||
bool operator()(uuid_type id) const;
|
bool operator()(uuid_type id) const { return data_[id](); }
|
||||||
|
|
||||||
reference operator[](index_type idx);
|
typename dynarray<node>::iterator begin() { return data_.begin(); }
|
||||||
const_reference operator[](index_type idx) const;
|
typename dynarray<node>::iterator end() { return data_.end(); }
|
||||||
bool operator()(index_type idx) const;
|
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===========================================================================================================
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<node> data_;
|
dynarray<node> data_;
|
||||||
_Hash map_;
|
dynarray<uuid_type> freed_;
|
||||||
std::stack<index_type> freed_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
typename object_list<T>::uuid_type object_list<T>::insert(const_reference value)
|
||||||
|
{
|
||||||
|
if(freed_.empty()) { data_.push_back(value); return data_.size() - 1; }
|
||||||
|
|
||||||
|
uuid_type id = freed_.back(); freed_.pop_back();
|
||||||
|
data_[id] = value;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void object_list<T>::erase(uuid_type id)
|
||||||
|
{
|
||||||
|
data_[id].reset();
|
||||||
|
freed_.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
} // open_cpp_utils
|
} // open_cpp_utils
|
||||||
|
|
||||||
#endif //OBJECT_POOL_H
|
#endif //OBJECT_POOL_H
|
||||||
|
2
External/open-cpp-utils/optional.h
vendored
2
External/open-cpp-utils/optional.h
vendored
@ -26,7 +26,7 @@ namespace open_cpp_utils
|
|||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
optional() : data_(), valid_(false) { }
|
optional() : valid_(false) { }
|
||||||
optional(const value_type& data) : data_(data), valid_(true) { }
|
optional(const value_type& data) : data_(data), valid_(true) { }
|
||||||
optional(value_type&& data) : data_(data), valid_(true) { }
|
optional(value_type&& data) : data_(data), valid_(true) { }
|
||||||
optional(const optional& other) = default;
|
optional(const optional& other) = default;
|
||||||
|
21
External/open-cpp-utils/redec.h
vendored
Normal file
21
External/open-cpp-utils/redec.h
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef REDEC_H
|
||||||
|
#define REDEC_H
|
||||||
|
|
||||||
|
#include "dynarray.h"
|
||||||
|
|
||||||
|
#endif //REDEC_H
|
28
External/open-cpp-utils/set.h
vendored
Normal file
28
External/open-cpp-utils/set.h
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// Copyright 2024 Medusa Slockbower
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#ifndef SET_H
|
||||||
|
#define SET_H
|
||||||
|
|
||||||
|
#include "hash_table.h"
|
||||||
|
|
||||||
|
namespace open_cpp_utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, class Hash = std::hash<T>, class Alloc = std::allocator<T>> using set = hash_table<T, Hash, Alloc>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SET_H
|
@ -24,33 +24,111 @@ namespace ocu = open_cpp_utils;
|
|||||||
|
|
||||||
namespace OpenShaderDesigner::Nodes::Math
|
namespace OpenShaderDesigner::Nodes::Math
|
||||||
{
|
{
|
||||||
inline static constexpr ImColor HeaderColor = ImColor(0x92, 0x16, 0x16);
|
// Header Colors =======================================================================================================
|
||||||
|
|
||||||
struct Constant : public Node
|
inline static constexpr ImColor HeaderColor = ImColor(0xA7, 0x62, 0x53);
|
||||||
{
|
inline static constexpr ImColor HeaderHoveredColor = ImColor(0xC5, 0x79, 0x67);
|
||||||
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
|
inline static constexpr ImColor HeaderActiveColor = ImColor(0x82, 0x4C, 0x40);
|
||||||
|
|
||||||
Constant(ShaderGraph& graph, ImVec2 pos);
|
inline static const std::string HeaderMarker = "\uF3B9 ";
|
||||||
virtual ~Constant() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
|
||||||
void Inspect() override;
|
|
||||||
|
|
||||||
ValueType Value;
|
// =====================================================================================================================
|
||||||
};
|
// Integral
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
RegisterNode("Math/Constant", Constant);
|
struct Integral : public Node
|
||||||
|
{
|
||||||
|
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
|
||||||
|
|
||||||
struct Add : public Node
|
Integral(ShaderGraph& graph, ImVec2 pos);
|
||||||
{
|
virtual ~Integral() = default;
|
||||||
Add(ShaderGraph& graph, ImVec2 pos);
|
|
||||||
virtual ~Add() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
||||||
void Inspect() override;
|
void Inspect() override;
|
||||||
};
|
|
||||||
|
ValueType Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterNode("Math/Constants/Integral", Integral);
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Unsigned Integral
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
struct UnsignedIntegral : public Node
|
||||||
|
{
|
||||||
|
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
|
||||||
|
|
||||||
|
UnsignedIntegral(ShaderGraph& graph, ImVec2 pos);
|
||||||
|
virtual ~UnsignedIntegral() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
||||||
|
void Inspect() override;
|
||||||
|
|
||||||
|
ValueType Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterNode("Math/Constants/Unsigned Integral", UnsignedIntegral);
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Scalar
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
struct Scalar : public Node
|
||||||
|
{
|
||||||
|
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
|
||||||
|
|
||||||
|
Scalar(ShaderGraph& graph, ImVec2 pos);
|
||||||
|
virtual ~Scalar() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
||||||
|
void Inspect() override;
|
||||||
|
|
||||||
|
ValueType Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterNode("Math/Constants/Scalar", Scalar);
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Vector
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
struct Vector : public Node
|
||||||
|
{
|
||||||
|
using ValueType = ocu::any<int, unsigned int, float, glm::vec4>;
|
||||||
|
|
||||||
|
Vector(ShaderGraph& graph, ImVec2 pos);
|
||||||
|
virtual ~Vector() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
||||||
|
void Inspect() override;
|
||||||
|
|
||||||
|
ValueType Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterNode("Math/Constants/Vector", Vector);
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Add
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
struct Add : public Node
|
||||||
|
{
|
||||||
|
Add(ShaderGraph& graph, ImVec2 pos);
|
||||||
|
virtual ~Add() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
|
||||||
|
void Inspect() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterNode("Math/Operators/Add", Add);
|
||||||
|
|
||||||
RegisterNode("Math/Add", Add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MATH_H
|
#endif //MATH_H
|
||||||
|
@ -29,6 +29,11 @@
|
|||||||
#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>
|
||||||
|
|
||||||
|
#include <imnode-graph/imnode_graph.h>
|
||||||
|
|
||||||
|
#include "open-cpp-utils/any.h"
|
||||||
|
#include "open-cpp-utils/object_pool.h"
|
||||||
|
|
||||||
namespace ocu = open_cpp_utils;
|
namespace ocu = open_cpp_utils;
|
||||||
|
|
||||||
#define RegisterNode(Name, Type) \
|
#define RegisterNode(Name, Type) \
|
||||||
@ -38,68 +43,58 @@ namespace ocu = open_cpp_utils;
|
|||||||
namespace OpenShaderDesigner
|
namespace OpenShaderDesigner
|
||||||
{
|
{
|
||||||
class ShaderGraph;
|
class ShaderGraph;
|
||||||
using PinId = uint16_t;
|
|
||||||
using NodeId = uint32_t;
|
|
||||||
|
|
||||||
struct PinPtr
|
using PinType = int;
|
||||||
{
|
enum PinType_
|
||||||
struct Hash
|
{
|
||||||
{
|
PinType_Int = 0
|
||||||
size_t operator()(const PinPtr& p) const
|
, PinType_UInt
|
||||||
{
|
, PinType_Float
|
||||||
return p.hash();
|
, PinType_Vector
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
NodeId Node;
|
, PinType_Any
|
||||||
PinId Pin;
|
, PinType_COUNT
|
||||||
bool Input;
|
};
|
||||||
|
|
||||||
size_t hash() const { return (Input ? 0 : 0x8000000) | static_cast<size_t>(Node) << 32 | static_cast<size_t>(Pin & 0x7FFFFFFF); }
|
using PinFlags = unsigned int;
|
||||||
|
enum PinFlags_
|
||||||
bool operator<(const PinPtr& o) const { return hash() < o.hash(); }
|
{
|
||||||
bool operator==(const PinPtr& o) const { return hash() == o.hash(); }
|
PinFlags_None = 0
|
||||||
};
|
, PinFlags_NoCollapse = 1 << 0
|
||||||
|
, PinFlags_NoPadding = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
struct Pin
|
struct Pin
|
||||||
{
|
{
|
||||||
enum PinType
|
inline const static ImColor Colors[PinType_COUNT] = {
|
||||||
{
|
ImColor(0x64, 0x94, 0xAA) // Int
|
||||||
INT = 0
|
, ImColor(0x7A, 0x9F, 0x82) // Unsigned Int
|
||||||
, UINT
|
, ImColor(0xA6, 0x3D, 0x40) // Float
|
||||||
, FLOAT
|
, ImColor(0xE9, 0xB8, 0x72) // Vector
|
||||||
, VECTOR
|
, ImColor(0xD2, 0xD5, 0xD3) // Any
|
||||||
|
|
||||||
, ANY
|
|
||||||
, COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PinDirection
|
inline const static std::string TypeNames[PinType_COUNT] = {
|
||||||
{
|
|
||||||
INPUT
|
|
||||||
, OUTPUT
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const static ImColor Colors[COUNT] = {
|
|
||||||
ImColor(0xB9, 0xF5, 0x94)
|
|
||||||
, ImColor(0x8C, 0xC0, 0x8C)
|
|
||||||
, ImColor(0x37, 0x95, 0x85)
|
|
||||||
, ImColor(0xE3, 0x7D, 0xDC)
|
|
||||||
// , ImColor(0xD2, 0x6E, 0x46)
|
|
||||||
, ImColor(0xD2, 0xD5, 0xD3)
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const static std::string TypeNames[COUNT] = {
|
|
||||||
"Int"
|
"Int"
|
||||||
, "Unsigned Int"
|
, "Unsigned Int"
|
||||||
, "Float"
|
, "Float"
|
||||||
, "Vector"
|
, "Vector"
|
||||||
|
, "Any"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string Name;
|
using Ambiguous = ocu::any<int, unsigned int, float, ImVec4>;
|
||||||
PinType Type;
|
|
||||||
PinDirection Direction;
|
std::string Name;
|
||||||
};
|
PinType Type;
|
||||||
|
PinFlags Flags;
|
||||||
|
Ambiguous Value;
|
||||||
|
|
||||||
|
Pin(const std::string& name, PinType type, PinFlags flags = PinFlags_None)
|
||||||
|
: Name(name)
|
||||||
|
, Type(type)
|
||||||
|
, Flags(flags)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
@ -108,31 +103,28 @@ namespace OpenShaderDesigner
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
std::string Title = "Node";
|
std::string Title;
|
||||||
ImColor Color = Pin::Colors[Pin::VECTOR];
|
ImColor Color, HoveredColor, ActiveColor;
|
||||||
bool Enabled = true;
|
bool Enabled;
|
||||||
} Header;
|
} Header;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
std::vector<Pin> Inputs, Outputs;
|
std::vector<Pin> Inputs, Outputs;
|
||||||
bool DynamicInputs = false;
|
bool DynamicInputs;
|
||||||
} IO;
|
} IO;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
ImVec2 Size;
|
|
||||||
bool Const;
|
bool Const;
|
||||||
} Info;
|
} Info;
|
||||||
|
|
||||||
Node(
|
Node(ShaderGraph& graph, ImVec2 pos);
|
||||||
ShaderGraph& graph, ImVec2 pos
|
|
||||||
, const std::string& title, ImColor color
|
|
||||||
, const std::vector<Pin>& inputs, bool dyn_inputs
|
|
||||||
, const std::vector<Pin>& outputs
|
|
||||||
, bool constant = false);
|
|
||||||
~Node() = default;
|
~Node() = default;
|
||||||
|
|
||||||
|
void DrawPin(ImGuiID id, Pin& pin, ImPinDirection direction);
|
||||||
|
void Draw(ImGuiID id);
|
||||||
|
|
||||||
virtual Node* Copy(ShaderGraph& graph) const = 0;
|
virtual Node* Copy(ShaderGraph& graph) const = 0;
|
||||||
virtual void Inspect() = 0;
|
virtual void Inspect() = 0;
|
||||||
};
|
};
|
||||||
@ -143,15 +135,6 @@ namespace OpenShaderDesigner
|
|||||||
private:
|
private:
|
||||||
friend Node;
|
friend Node;
|
||||||
|
|
||||||
using Connection = std::pair<const PinPtr, PinPtr>;
|
|
||||||
using ConnectionMap = std::unordered_multimap<PinPtr, PinPtr, PinPtr::Hash>;
|
|
||||||
|
|
||||||
struct Line
|
|
||||||
{
|
|
||||||
ImColor Color;
|
|
||||||
float Thickness;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ConstructorPtr = Node*(*)(ShaderGraph&, ImVec2);
|
using ConstructorPtr = Node*(*)(ShaderGraph&, ImVec2);
|
||||||
struct ContextMenuItem
|
struct ContextMenuItem
|
||||||
{
|
{
|
||||||
@ -161,10 +144,8 @@ namespace OpenShaderDesigner
|
|||||||
|
|
||||||
struct GraphState
|
struct GraphState
|
||||||
{
|
{
|
||||||
ShaderGraph& Parent;
|
ShaderGraph& Parent;
|
||||||
std::vector<Node*> Nodes;
|
ocu::object_list<Node*> Nodes;
|
||||||
std::set<PinId> Erased;
|
|
||||||
ConnectionMap Connections;
|
|
||||||
|
|
||||||
GraphState(ShaderGraph& parent);
|
GraphState(ShaderGraph& parent);
|
||||||
GraphState(const GraphState& other);
|
GraphState(const GraphState& other);
|
||||||
@ -177,55 +158,22 @@ namespace OpenShaderDesigner
|
|||||||
using ContextID = ContextMenuHierarchy::node;
|
using ContextID = ContextMenuHierarchy::node;
|
||||||
inline static ContextMenuHierarchy ContextMenu;
|
inline static ContextMenuHierarchy ContextMenu;
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
float CalculateWidth(Node& node);
|
|
||||||
float CalculateHeight(Node& node);
|
|
||||||
|
|
||||||
// Base Draw and Input functions
|
|
||||||
void HandleInput();
|
|
||||||
void DrawGrid();
|
|
||||||
void DrawNode(Node& node, NodeId id);
|
|
||||||
void DrawPin(NodeId node_id, Pin& pin, PinId pin_id, ImVec2 location, bool input);
|
|
||||||
void DrawContextMenu();
|
|
||||||
|
|
||||||
// Connection functions
|
|
||||||
void DrawConnections();
|
|
||||||
void DrawConnection(const PinPtr& a, const PinPtr& b);
|
|
||||||
auto StartConnection(const PinPtr& ptr) -> void;
|
|
||||||
void StopConnection();
|
|
||||||
void CreateConnection(const PinPtr& a, const PinPtr& b);
|
|
||||||
void EraseConnection(const PinPtr& a, const PinPtr& b);
|
|
||||||
void EraseConnections(const PinPtr& a);
|
|
||||||
|
|
||||||
NodeId AddNode(Node* node);
|
|
||||||
void RemoveNode(NodeId id);
|
|
||||||
|
|
||||||
// Clipboard functionality
|
|
||||||
void ClearClipboard();
|
|
||||||
void Copy();
|
|
||||||
void Paste(const ImVec2& location);
|
|
||||||
void EraseSelection();
|
|
||||||
|
|
||||||
// History Functionality
|
// History Functionality
|
||||||
void PushState();
|
void PushState();
|
||||||
void PopState();
|
void PopState();
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
float BezierOffset(const ImVec2& out, const ImVec2& in);
|
|
||||||
bool AABB(const ImVec2& a0, const ImVec2& a1, const ImVec2& b0, const ImVec2& b1);
|
|
||||||
|
|
||||||
ImVec2 GridToScreen(const ImVec2& position);
|
|
||||||
ImVec2 ScreenToGrid(const ImVec2& position);
|
|
||||||
ImVec2 SnapToGrid(const ImVec2& position);
|
|
||||||
|
|
||||||
Pin& GetPin(const PinPtr& ptr);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShaderGraph();
|
ShaderGraph();
|
||||||
~ShaderGraph();
|
~ShaderGraph();
|
||||||
|
|
||||||
void OnOpen() override;
|
void OnOpen() override;
|
||||||
void DrawWindow() override;
|
void DrawWindow() override;
|
||||||
|
|
||||||
|
void DrawContextMenu();
|
||||||
|
|
||||||
|
void Copy();
|
||||||
|
void Erase();
|
||||||
|
void Paste(ImVec2 pos);
|
||||||
|
|
||||||
static void Register(const std::filesystem::path& path, ConstructorPtr constructor);
|
static void Register(const std::filesystem::path& path, ConstructorPtr constructor);
|
||||||
|
|
||||||
@ -233,86 +181,9 @@ namespace OpenShaderDesigner
|
|||||||
bool GrabFocus;
|
bool GrabFocus;
|
||||||
|
|
||||||
GraphState State;
|
GraphState State;
|
||||||
std::stack<GraphState> History;
|
std::stack<GraphState> History;
|
||||||
|
|
||||||
struct
|
ImVec2 ContextMenuPosition;
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
ImColor BackgroundColor;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
Line Thin, Thick;
|
|
||||||
float Padding;
|
|
||||||
} Lines;
|
|
||||||
} Grid;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float Rounding;
|
|
||||||
Line Border, SelectedBorder;
|
|
||||||
ImColor Content;
|
|
||||||
ImColor Title;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float Padding;
|
|
||||||
float BorderThickness;
|
|
||||||
ImColor Background;
|
|
||||||
ImColor Text;
|
|
||||||
Line Connections;
|
|
||||||
} Pins;
|
|
||||||
} Nodes;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
ImColor Background;
|
|
||||||
Line Border;
|
|
||||||
} Selection;
|
|
||||||
|
|
||||||
float FontSize;
|
|
||||||
} Style;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float Rate, Smoothing;
|
|
||||||
} Scroll;
|
|
||||||
} Input;
|
|
||||||
} Settings;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
ImVec2 Location, ScreenLocation, Delta;
|
|
||||||
float Scroll;
|
|
||||||
bool ClickedSomething;
|
|
||||||
|
|
||||||
ocu::optional<NodeId> FocusedNode;
|
|
||||||
std::unordered_map<NodeId, ImVec2> Locks;
|
|
||||||
std::unordered_set<NodeId> DragSelect;
|
|
||||||
bool LocksDragged, NodeHovered;
|
|
||||||
ocu::optional<PinPtr> NewConnection;
|
|
||||||
std::unordered_set<NodeId> Selected;
|
|
||||||
} Mouse;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
ImVec2 Location;
|
|
||||||
float Zoom, Scroll;
|
|
||||||
} Camera;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
std::vector<Node*> Nodes;
|
|
||||||
ConnectionMap Connections;
|
|
||||||
} Clipboard;
|
|
||||||
|
|
||||||
bool Focused;
|
|
||||||
ImVec2 ContextMenuPosition;
|
|
||||||
|
|
||||||
friend class Inspector;
|
friend class Inspector;
|
||||||
};
|
};
|
||||||
|
@ -19,73 +19,131 @@
|
|||||||
using namespace OpenShaderDesigner;
|
using namespace OpenShaderDesigner;
|
||||||
using namespace OpenShaderDesigner::Nodes::Math;
|
using namespace OpenShaderDesigner::Nodes::Math;
|
||||||
|
|
||||||
Constant::Constant(ShaderGraph& graph, ImVec2 pos)
|
|
||||||
: Node(
|
// =====================================================================================================================
|
||||||
graph, pos
|
// Integral
|
||||||
, "Constant", HeaderColor
|
// =====================================================================================================================
|
||||||
, { }, false
|
|
||||||
, { { "Out", Pin::FLOAT, Pin::OUTPUT } }
|
Integral::Integral(ShaderGraph& graph, ImVec2 pos)
|
||||||
)
|
: Node(graph, pos)
|
||||||
{
|
{
|
||||||
|
Header.Title = HeaderMarker + "Integral";
|
||||||
|
Header.Color = HeaderColor;
|
||||||
|
Header.HoveredColor = HeaderHoveredColor;
|
||||||
|
Header.ActiveColor = HeaderActiveColor;
|
||||||
|
|
||||||
|
IO.Outputs.emplace_back("Out", PinType_Float, PinFlags_NoCollapse | PinFlags_NoPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* Constant::Copy(ShaderGraph& graph) const
|
Node* Integral::Copy(ShaderGraph& graph) const
|
||||||
{
|
{
|
||||||
return new Constant(graph, Position);
|
return new Integral(graph, Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Constant::Inspect()
|
void Integral::Inspect()
|
||||||
{
|
{
|
||||||
Pin::PinType& Type = IO.Outputs[0].Type;
|
|
||||||
|
|
||||||
if(ImGui::BeginCombo("Type", Pin::TypeNames[Type].c_str()))
|
|
||||||
{
|
|
||||||
for(int i = 0; i < Pin::ANY; ++i)
|
|
||||||
{
|
|
||||||
Pin::PinType t = static_cast<Pin::PinType>(i);
|
|
||||||
|
|
||||||
if(ImGui::Selectable(Pin::TypeNames[t].c_str(), t == Type))
|
|
||||||
{
|
|
||||||
Type = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec4& v = Value;
|
|
||||||
|
|
||||||
switch(Type)
|
|
||||||
{
|
|
||||||
case Pin::INT:
|
|
||||||
ImGui::InputInt("Value", Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Pin::UINT:
|
|
||||||
ImGui::InputUInt("Value", Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Pin::FLOAT:
|
|
||||||
ImGui::InputFloat("Value", Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Pin::VECTOR:
|
|
||||||
ImGui::ColorEdit4("Value", &v.x);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Scalar
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
UnsignedIntegral::UnsignedIntegral(ShaderGraph& graph, ImVec2 pos)
|
||||||
|
: Node(graph, pos)
|
||||||
|
{
|
||||||
|
Header.Title = HeaderMarker + "Unsigned Integral";
|
||||||
|
Header.Color = HeaderColor;
|
||||||
|
Header.HoveredColor = HeaderHoveredColor;
|
||||||
|
Header.ActiveColor = HeaderActiveColor;
|
||||||
|
|
||||||
|
IO.Outputs.emplace_back("Out", PinType_Float, PinFlags_NoCollapse | PinFlags_NoPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* UnsignedIntegral::Copy(ShaderGraph& graph) const
|
||||||
|
{
|
||||||
|
return new UnsignedIntegral(graph, Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnsignedIntegral::Inspect()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Scalar
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
Scalar::Scalar(ShaderGraph& graph, ImVec2 pos)
|
||||||
|
: Node(graph, pos)
|
||||||
|
{
|
||||||
|
Header.Title = HeaderMarker + "Scalar";
|
||||||
|
Header.Color = HeaderColor;
|
||||||
|
Header.HoveredColor = HeaderHoveredColor;
|
||||||
|
Header.ActiveColor = HeaderActiveColor;
|
||||||
|
|
||||||
|
IO.Outputs.emplace_back("Out", PinType_Float, PinFlags_NoCollapse | PinFlags_NoPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* Scalar::Copy(ShaderGraph& graph) const
|
||||||
|
{
|
||||||
|
return new Scalar(graph, Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scalar::Inspect()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Vector
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
Vector::Vector(ShaderGraph &graph, ImVec2 pos)
|
||||||
|
: Node(graph, pos)
|
||||||
|
{
|
||||||
|
Header.Title = HeaderMarker + "Vector";
|
||||||
|
Header.Color = HeaderColor;
|
||||||
|
Header.HoveredColor = HeaderHoveredColor;
|
||||||
|
Header.ActiveColor = HeaderActiveColor;
|
||||||
|
|
||||||
|
IO.Outputs.emplace_back("Out", PinType_Vector, PinFlags_NoCollapse | PinFlags_NoPadding);
|
||||||
|
|
||||||
|
IO.Outputs[0].Value.get<ImVec4>() = ImVec4(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* Vector::Copy(ShaderGraph &graph) const
|
||||||
|
{
|
||||||
|
return new Vector(graph, Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vector::Inspect()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
// Add
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
Add::Add(ShaderGraph& graph, ImVec2 pos)
|
Add::Add(ShaderGraph& graph, ImVec2 pos)
|
||||||
: Node(
|
: Node(graph, pos)
|
||||||
graph, pos
|
{
|
||||||
, "Add", HeaderColor
|
Header.Title = HeaderMarker + "Add";
|
||||||
, { { "A", Pin::ANY, Pin::INPUT }, { "B", Pin::ANY, Pin::INPUT } }, true
|
Header.Color = HeaderColor;
|
||||||
, { { "Out", Pin::ANY, Pin::OUTPUT } }
|
Header.HoveredColor = HeaderHoveredColor;
|
||||||
)
|
Header.ActiveColor = HeaderActiveColor;
|
||||||
{ }
|
|
||||||
|
IO.Inputs.emplace_back("A", PinType_Any);
|
||||||
|
IO.Inputs.emplace_back("B", PinType_Any);
|
||||||
|
IO.DynamicInputs = true;
|
||||||
|
|
||||||
|
IO.Outputs.emplace_back("B", PinType_Any);
|
||||||
|
}
|
||||||
|
|
||||||
Node* Add::Copy(ShaderGraph& graph) const
|
Node* Add::Copy(ShaderGraph& graph) const
|
||||||
{
|
{
|
||||||
|
@ -17,15 +17,15 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#include <Core/Engine.h>
|
|
||||||
#include <Core/Console.h>
|
#include <Core/Console.h>
|
||||||
#include <Editor/EditorSystem.h>
|
#include <Editor/EditorSystem.h>
|
||||||
|
|
||||||
#include <glm/common.hpp>
|
|
||||||
#include <Graph/ShaderGraph.h>
|
#include <Graph/ShaderGraph.h>
|
||||||
|
|
||||||
#include <imgui-docking/imgui_internal.h>
|
#include <imgui-docking/imgui_internal.h>
|
||||||
|
|
||||||
#include <imnode-graph/imnode_graph.h>
|
#include "imgui-extras/imgui_extras.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace OpenShaderDesigner;
|
using namespace OpenShaderDesigner;
|
||||||
|
|
||||||
@ -41,16 +41,12 @@ ShaderGraph::GraphState::GraphState(ShaderGraph& parent)
|
|||||||
|
|
||||||
ShaderGraph::GraphState::GraphState(const GraphState& other)
|
ShaderGraph::GraphState::GraphState(const GraphState& other)
|
||||||
: Parent(other.Parent)
|
: Parent(other.Parent)
|
||||||
, Nodes(other.Nodes.size(), nullptr)
|
, Nodes(other.Nodes)
|
||||||
, Connections(other.Connections)
|
|
||||||
, Erased(other.Erased)
|
|
||||||
{
|
{
|
||||||
NodeId id = 0;
|
for(Node*& node : Nodes)
|
||||||
for(const Node* node : other.Nodes)
|
{
|
||||||
{
|
node = node->Copy(Parent);
|
||||||
if(node) Nodes[id] = node->Copy(Parent);
|
}
|
||||||
++id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderGraph::GraphState::~GraphState()
|
ShaderGraph::GraphState::~GraphState()
|
||||||
@ -63,153 +59,107 @@ ShaderGraph::GraphState::~GraphState()
|
|||||||
|
|
||||||
ShaderGraph::GraphState& ShaderGraph::GraphState::operator=(const GraphState& other)
|
ShaderGraph::GraphState& ShaderGraph::GraphState::operator=(const GraphState& other)
|
||||||
{
|
{
|
||||||
for(Node* node : Nodes)
|
Nodes = other.Nodes;
|
||||||
{
|
|
||||||
if(node) delete node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nodes.clear();
|
for(Node*& node : Nodes) if(node) node = node->Copy(Parent);
|
||||||
Nodes.resize(other.Nodes.size(), nullptr);
|
|
||||||
|
|
||||||
NodeId id = 0;
|
return *this;
|
||||||
for(const Node* node : other.Nodes)
|
|
||||||
{
|
|
||||||
if(node) Nodes[id] = node->Copy(Parent);
|
|
||||||
++id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections = other.Connections;
|
|
||||||
Erased = other.Erased;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
float ShaderGraph::CalculateWidth(Node& node)
|
|
||||||
{
|
|
||||||
const float GridSize = Style.FontSize + Style.Grid.Lines.Padding;
|
|
||||||
const float HeaderHeight = Style.FontSize;
|
|
||||||
const float HeaderWidth = ImGui::CalcTextSize(node.Header.Title.c_str()).x;
|
|
||||||
float InputWidth = 0.0f, OutputWidth = 0.0f;
|
|
||||||
|
|
||||||
// Longest Input Pin
|
|
||||||
for(const Pin& pin : node.IO.Inputs)
|
|
||||||
{
|
|
||||||
InputWidth = glm::max(InputWidth, HeaderHeight + ImGui::CalcTextSize(pin.Name.c_str()).x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Longest Output Pin
|
|
||||||
for(const Pin& pin : node.IO.Outputs)
|
|
||||||
{
|
|
||||||
OutputWidth = glm::max(OutputWidth, HeaderHeight + ImGui::CalcTextSize(pin.Name.c_str()).x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Width = glm::max(InputWidth + OutputWidth, HeaderWidth) + HeaderHeight;
|
|
||||||
Width += GridSize - std::fmod(1.0f + Style.Grid.Lines.Padding + Width, GridSize);
|
|
||||||
|
|
||||||
return Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
float ShaderGraph::CalculateHeight(Node& node)
|
|
||||||
{
|
|
||||||
const float HeaderHeight = Style.FontSize;
|
|
||||||
const float PinHeight = HeaderHeight * static_cast<float>(1 + glm::max(node.IO.Inputs.size(), node.IO.Outputs.size()));
|
|
||||||
return glm::max(HeaderHeight + PinHeight, 2 * HeaderHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Node(
|
Node::Node(
|
||||||
ShaderGraph& graph, ImVec2 pos
|
ShaderGraph& graph, ImVec2 pos)
|
||||||
, const std::string& title, ImColor color
|
|
||||||
, const std::vector<Pin>& inputs, bool dyn_inputs
|
|
||||||
, const std::vector<Pin>& outputs, bool constant)
|
|
||||||
: Position(pos)
|
: Position(pos)
|
||||||
, Header
|
, Header
|
||||||
{
|
{
|
||||||
.Title = title
|
.Title = "Node"
|
||||||
, .Color = color
|
, .Color = ImColor(0xA7, 0x62, 0x53)
|
||||||
, .Enabled = true
|
, .HoveredColor = ImColor(0xC5, 0x79, 0x67)
|
||||||
|
, .ActiveColor = ImColor(0x82, 0x4C, 0x40)
|
||||||
|
, .Enabled = true
|
||||||
}
|
}
|
||||||
, IO
|
, IO
|
||||||
{
|
{
|
||||||
.Inputs = inputs
|
.DynamicInputs = false
|
||||||
, .Outputs = outputs
|
|
||||||
, .DynamicInputs = dyn_inputs
|
|
||||||
}
|
}
|
||||||
, Info
|
, Info
|
||||||
{
|
{
|
||||||
.Size = ImVec2(graph.CalculateWidth(*this), graph.CalculateHeight(*this))
|
.Const = false
|
||||||
, .Const = constant
|
|
||||||
}
|
}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
void Node::DrawPin(ImGuiID id, Pin& pin, ImPinDirection direction)
|
||||||
|
{
|
||||||
|
ImPinFlags flags = 0;
|
||||||
|
if(pin.Flags & PinFlags_NoPadding) flags |= ImPinFlags_NoPadding;
|
||||||
|
|
||||||
|
ImNodeGraph::BeginPin(std::format("{}##{}", pin.Name, id).c_str(), pin.Type, direction, flags);
|
||||||
|
|
||||||
|
bool connected = ImNodeGraph::IsPinConnected();
|
||||||
|
|
||||||
|
if((connected || pin.Type == PinType_Any) && !(pin.Flags & PinFlags_NoCollapse))
|
||||||
|
{
|
||||||
|
ImGui::Text(pin.Name.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (pin.Type)
|
||||||
|
{
|
||||||
|
case PinType_Int:
|
||||||
|
ImNodeGraph::PushItemWidth(200.0f);
|
||||||
|
ImGui::InputInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
|
||||||
|
case PinType_UInt:
|
||||||
|
ImNodeGraph::PushItemWidth(200.0f);
|
||||||
|
ImGui::InputUInt(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
|
||||||
|
case PinType_Float:
|
||||||
|
ImNodeGraph::PushItemWidth(100.0f);
|
||||||
|
ImGui::InputFloat(std::format("##in{}{}", pin.Name, id).c_str(), pin.Value); break;
|
||||||
|
case PinType_Vector:
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
// Color Picker
|
||||||
|
ImNodeGraph::PushItemWidth(150.0f);
|
||||||
|
ImGui::ColorPicker4(
|
||||||
|
std::format("##in{}{}", pin.Name, id).c_str(), &pin.Value.get<ImVec4>().x
|
||||||
|
, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float
|
||||||
|
);
|
||||||
|
|
||||||
|
ImNodeGraph::PushItemWidth(150.0f);
|
||||||
|
ImGui::ColorPreview(
|
||||||
|
std::format("##invec{}{}", pin.Name, id).c_str(), &pin.Value.get<ImVec4>().x
|
||||||
|
, ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float
|
||||||
|
);
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImNodeGraph::EndPin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::Draw(ImGuiID id)
|
||||||
|
{
|
||||||
|
ImNodeGraph::BeginNode(id, Position);
|
||||||
|
|
||||||
|
if(Header.Enabled)
|
||||||
|
{
|
||||||
|
ImNodeGraph::BeginNodeHeader(id, Header.Color, Header.HoveredColor, Header.ActiveColor);
|
||||||
|
|
||||||
|
ImGui::Text(Header.Title.c_str());
|
||||||
|
|
||||||
|
ImNodeGraph::EndNodeHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Pin& pin : IO.Inputs) DrawPin(id, pin, ImPinDirection_Input);
|
||||||
|
for(Pin& pin : IO.Outputs) DrawPin(id, pin, ImPinDirection_Output);
|
||||||
|
|
||||||
|
ImNodeGraph::EndNode();
|
||||||
|
}
|
||||||
|
|
||||||
ShaderGraph::ShaderGraph()
|
ShaderGraph::ShaderGraph()
|
||||||
: EditorWindow("\uED46 Shader Graph", 0)
|
: EditorWindow("\uED46 Shader Graph", 0)
|
||||||
, GrabFocus(false)
|
, GrabFocus(false)
|
||||||
, State(*this)
|
, State(*this)
|
||||||
, Style
|
|
||||||
{
|
|
||||||
.Grid
|
|
||||||
{
|
|
||||||
.BackgroundColor = ImColor(0x11, 0x11, 0x11)
|
|
||||||
, .Lines
|
|
||||||
{
|
|
||||||
.Thin
|
|
||||||
{
|
|
||||||
.Color = ImColor(0x44, 0x44, 0x44)
|
|
||||||
, .Thickness = 1.0
|
|
||||||
}
|
|
||||||
, .Thick
|
|
||||||
{
|
|
||||||
.Color = ImColor(0x88, 0x88, 0x88)
|
|
||||||
, .Thickness = 2.0
|
|
||||||
}
|
|
||||||
, .Padding = 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, .Nodes
|
|
||||||
{
|
|
||||||
.Rounding = 5.0f
|
|
||||||
, .Border = { ImColor(0x33, 0x33, 0x33), 2.0f }
|
|
||||||
, .SelectedBorder = { ImColor(0xEF, 0xAE, 0x4B), 4.0f }
|
|
||||||
, .Content = ImColor(0x88, 0x88, 0x88)
|
|
||||||
, .Title = ImColor(0xCC, 0xCC, 0xCC)
|
|
||||||
, .Pins
|
|
||||||
{
|
|
||||||
.Padding = 2.0f
|
|
||||||
, .BorderThickness = 3.0f
|
|
||||||
, .Background = ImColor(0x22, 0x22, 0x22)
|
|
||||||
, .Text = ImColor(0x22, 0x22, 0x22)
|
|
||||||
, .Connections
|
|
||||||
{
|
|
||||||
.Color = ImColor(0x00, 0x00, 0x00)
|
|
||||||
, .Thickness = 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, .Selection
|
|
||||||
{
|
|
||||||
.Background = ImColor(0xC9, 0x8E, 0x36, 0x44)
|
|
||||||
, .Border
|
|
||||||
{
|
|
||||||
.Color = ImColor(0xEF, 0xAE, 0x4B, 0xBB)
|
|
||||||
, .Thickness = 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, .FontSize = 20.0f
|
|
||||||
}
|
|
||||||
, Settings
|
|
||||||
{
|
|
||||||
.Input
|
|
||||||
{
|
|
||||||
.Scroll
|
|
||||||
{
|
|
||||||
.Rate = 0.2f
|
|
||||||
, .Smoothing = 8.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, Mouse({ 0, 0 }, { 0, 0 })
|
|
||||||
, Camera({ 0, 0 }, 1)
|
|
||||||
, Focused(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,9 +169,6 @@ ShaderGraph::~ShaderGraph()
|
|||||||
|
|
||||||
void ShaderGraph::OnOpen()
|
void ShaderGraph::OnOpen()
|
||||||
{
|
{
|
||||||
Mouse.Location = ImGui::GetMousePos();
|
|
||||||
Camera.Scroll = Camera.Zoom = 1.0f;
|
|
||||||
|
|
||||||
EditorSystem::Open<Inspector>()->Graph = this;
|
EditorSystem::Open<Inspector>()->Graph = this;
|
||||||
|
|
||||||
GrabFocus = true;
|
GrabFocus = true;
|
||||||
@ -230,7 +177,6 @@ void ShaderGraph::OnOpen()
|
|||||||
|
|
||||||
void ShaderGraph::DrawWindow()
|
void ShaderGraph::DrawWindow()
|
||||||
{
|
{
|
||||||
static int test_in, test_out;
|
|
||||||
ImNodeGraph::BeginGraph("ShaderGraph");
|
ImNodeGraph::BeginGraph("ShaderGraph");
|
||||||
ImNodeGraph::SetPinColors(Pin::Colors);
|
ImNodeGraph::SetPinColors(Pin::Colors);
|
||||||
|
|
||||||
@ -241,56 +187,173 @@ void ShaderGraph::DrawWindow()
|
|||||||
ImGui::SetNavWindow(ImGui::GetCurrentWindow());
|
ImGui::SetNavWindow(ImGui::GetCurrentWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
// First Test Node
|
for(ImGuiID id = 0; id < State.Nodes.size(); ++id)
|
||||||
{
|
{
|
||||||
ImVec2 pos = { 0, 0 };
|
if(State.Nodes(id) == false) continue;
|
||||||
|
|
||||||
ImNodeGraph::BeginNode(0, pos);
|
State.Nodes[id]->Draw(id);
|
||||||
|
|
||||||
ImNodeGraph::BeginNodeHeader(-1, ImColor(0xA7, 0x62, 0x53), ImColor(0xC5, 0x79, 0x67), ImColor(0x82, 0x4C, 0x40));
|
|
||||||
ImGui::Text("\uf1f5 Hello");
|
|
||||||
ImNodeGraph::EndNodeHeader();
|
|
||||||
|
|
||||||
ImNodeGraph::BeginPin(1, Pin::INT, ImPinDirection_Input);
|
|
||||||
ImGui::PushItemWidth(100 * ImNodeGraph::GetCameraScale());
|
|
||||||
ImGui::InputInt("##In", &test_in, 0);
|
|
||||||
//ImGui::Text("In");
|
|
||||||
ImNodeGraph::EndPin();
|
|
||||||
|
|
||||||
ImNodeGraph::BeginPin(2, Pin::ANY, ImPinDirection_Output);
|
|
||||||
ImGui::Text("Out");
|
|
||||||
ImNodeGraph::EndPin();
|
|
||||||
|
|
||||||
ImNodeGraph::EndNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second Test Node
|
DrawContextMenu();
|
||||||
{
|
|
||||||
ImVec2 pos = { 300, 0 };
|
|
||||||
|
|
||||||
ImNodeGraph::BeginNode(3, pos);
|
|
||||||
|
|
||||||
ImNodeGraph::BeginNodeHeader(-1, ImColor(0xA7, 0x62, 0x53), ImColor(0xC5, 0x79, 0x67), ImColor(0x82, 0x4C, 0x40));
|
|
||||||
ImGui::Text("\uf1f5 Hello");
|
|
||||||
ImNodeGraph::EndNodeHeader();
|
|
||||||
|
|
||||||
ImNodeGraph::BeginPin(4, Pin::INT, ImPinDirection_Input);
|
|
||||||
ImGui::PushItemWidth(100 * ImNodeGraph::GetCameraScale());
|
|
||||||
ImGui::InputInt("##In", &test_in, 0);
|
|
||||||
//ImGui::Text("In");
|
|
||||||
ImNodeGraph::EndPin();
|
|
||||||
|
|
||||||
ImNodeGraph::BeginPin(5, Pin::ANY, ImPinDirection_Output);
|
|
||||||
ImGui::Text("Out");
|
|
||||||
ImNodeGraph::EndPin();
|
|
||||||
|
|
||||||
ImNodeGraph::EndNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImNodeGraph::EndGraph();
|
ImNodeGraph::EndGraph();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
void ShaderGraph::DrawContextMenu()
|
||||||
|
{
|
||||||
|
if(ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||||
|
{
|
||||||
|
ContextMenuPosition = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginPopupContextWindow())
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Copy", "Ctrl+C", false, false)) Copy();
|
||||||
|
if(ImGui::MenuItem("Cut", "Ctrl+X", false, false))
|
||||||
|
{
|
||||||
|
Copy();
|
||||||
|
Erase();
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Paste", "Ctrl+V", false, false)) Paste(ContextMenuPosition);
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::Text("Create");
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Create Nodes
|
||||||
|
ImVec2 position = ContextMenuPosition;
|
||||||
|
|
||||||
|
std::stack<ContextID> context; context.push(0);
|
||||||
|
|
||||||
|
struct Visitor
|
||||||
|
{
|
||||||
|
bool operator()(ContextMenuItem& item, ContextID id)
|
||||||
|
{
|
||||||
|
const auto depth = Graph.ContextMenu.depth(id);
|
||||||
|
if(depth > Context.size()) return false;
|
||||||
|
|
||||||
|
while(depth < Context.size())
|
||||||
|
{
|
||||||
|
Context.pop();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Context.top() != Graph.ContextMenu.parent(id)) return false;
|
||||||
|
std::string name = std::format("{}##{}", item.Name, id);
|
||||||
|
|
||||||
|
if(item.Constructor)
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem(item.Name.c_str()))
|
||||||
|
{
|
||||||
|
Graph.State.Nodes.insert(item.Constructor(Graph, Location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenu(item.Name.c_str()))
|
||||||
|
{
|
||||||
|
Context.push(id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderGraph& Graph;
|
||||||
|
const ImVec2 Location;
|
||||||
|
std::stack<ContextID>& Context;
|
||||||
|
} MenuVisitor
|
||||||
|
{
|
||||||
|
.Graph = *this
|
||||||
|
, .Location = position
|
||||||
|
, .Context = context
|
||||||
|
};
|
||||||
|
|
||||||
|
ContextMenu.traverse<ContextMenuHierarchy::pre_order>(MenuVisitor);
|
||||||
|
|
||||||
|
context.pop();
|
||||||
|
while(context.empty() == false)
|
||||||
|
{
|
||||||
|
ImGui::EndMenu();
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGraph::Copy() {}
|
||||||
|
void ShaderGraph::Erase() {}
|
||||||
|
void ShaderGraph::Paste(ImVec2) {}
|
||||||
|
|
||||||
|
void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr constructor)
|
||||||
|
{
|
||||||
|
const std::string name = path.filename().string();
|
||||||
|
|
||||||
|
std::stack<std::string> decomp;
|
||||||
|
std::filesystem::path current = path.parent_path();
|
||||||
|
while(current.empty() == false)
|
||||||
|
{
|
||||||
|
decomp.push(current.filename().string());
|
||||||
|
current = current.parent_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextID node = 0;
|
||||||
|
while(decomp.empty() == false)
|
||||||
|
{
|
||||||
|
ContextID child = ContextMenu.first_child(node);
|
||||||
|
|
||||||
|
while(child)
|
||||||
|
{
|
||||||
|
if(ContextMenu[child].Name == decomp.top())
|
||||||
|
{
|
||||||
|
node = child;
|
||||||
|
decomp.pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = ContextMenu.next_sibling(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node == 0 || node != child)
|
||||||
|
{
|
||||||
|
node = ContextMenu.insert({ decomp.top(), nullptr }, node);
|
||||||
|
decomp.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextMenu.insert({ name, constructor }, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
Inspector::Inspector()
|
||||||
|
: EditorWindow("Inspector", 0)
|
||||||
|
, Graph(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inspector::DrawWindow()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if(Graph->Mouse.Selected.size() != 1)
|
||||||
|
{
|
||||||
|
ImGui::Text("Selected %d nodes.", Graph->Mouse.Selected.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph->State.Nodes[*Graph->Mouse.Selected.begin()]->Inspect();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** DEPRECATED
|
||||||
void ShaderGraph::DrawWindow()
|
void ShaderGraph::DrawWindow()
|
||||||
{
|
{
|
||||||
HandleInput();
|
HandleInput();
|
||||||
@ -340,7 +403,6 @@ void ShaderGraph::DrawWindow()
|
|||||||
Mouse.LocksDragged = false;
|
Mouse.LocksDragged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void ShaderGraph::HandleInput()
|
void ShaderGraph::HandleInput()
|
||||||
@ -732,98 +794,6 @@ void ShaderGraph::DrawPin(NodeId node_id, Pin& pin, PinId pin_id, ImVec2 locatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderGraph::DrawContextMenu()
|
|
||||||
{
|
|
||||||
const float GridSize = (Style.FontSize + Style.Grid.Lines.Padding);
|
|
||||||
|
|
||||||
if(ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
|
||||||
{
|
|
||||||
ContextMenuPosition = Mouse.Location;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::BeginPopupContextWindow())
|
|
||||||
{
|
|
||||||
if(ImGui::MenuItem("Copy", "Ctrl+C", false, !Mouse.Selected.empty())) Copy();
|
|
||||||
if(ImGui::MenuItem("Cut", "Ctrl+X", false, !Mouse.Selected.empty()))
|
|
||||||
{
|
|
||||||
Copy();
|
|
||||||
EraseSelection();
|
|
||||||
}
|
|
||||||
if(ImGui::MenuItem("Paste", "Ctrl+V", false, !Clipboard.Nodes.empty())) Paste(ContextMenuPosition);
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
ImGui::Text("Create");
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
// Create Nodes
|
|
||||||
ImVec2 position = ContextMenuPosition;
|
|
||||||
position = SnapToGrid(position);
|
|
||||||
|
|
||||||
std::stack<ContextID> context; context.push(0);
|
|
||||||
|
|
||||||
struct Visitor
|
|
||||||
{
|
|
||||||
bool operator()(ContextMenuItem& item, ContextID id)
|
|
||||||
{
|
|
||||||
const auto depth = Graph.ContextMenu.depth(id);
|
|
||||||
if(depth > Context.size()) return false;
|
|
||||||
|
|
||||||
while(depth < Context.size())
|
|
||||||
{
|
|
||||||
Context.pop();
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Context.top() != Graph.ContextMenu.parent(id)) return false;
|
|
||||||
std::string name = std::format("{}##{}", item.Name, id);
|
|
||||||
|
|
||||||
if(item.Constructor)
|
|
||||||
{
|
|
||||||
if(ImGui::MenuItem(item.Name.c_str()))
|
|
||||||
{
|
|
||||||
Graph.AddNode(item.Constructor(Graph, Location));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(ImGui::BeginMenu(item.Name.c_str()))
|
|
||||||
{
|
|
||||||
Context.push(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderGraph& Graph;
|
|
||||||
const ImVec2 Location;
|
|
||||||
std::stack<ContextID>& Context;
|
|
||||||
} MenuVisitor
|
|
||||||
{
|
|
||||||
.Graph = *this
|
|
||||||
, .Location = position
|
|
||||||
, .Context = context
|
|
||||||
};
|
|
||||||
|
|
||||||
ContextMenu.traverse<ContextMenuHierarchy::pre_order>(MenuVisitor);
|
|
||||||
|
|
||||||
context.pop();
|
|
||||||
while(context.empty() == false)
|
|
||||||
{
|
|
||||||
ImGui::EndMenu();
|
|
||||||
context.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderGraph::DrawConnections()
|
void ShaderGraph::DrawConnections()
|
||||||
{
|
{
|
||||||
// Vars ============================================================================================================
|
// Vars ============================================================================================================
|
||||||
@ -1177,59 +1147,4 @@ Pin& ShaderGraph::GetPin(const PinPtr &ptr)
|
|||||||
Node* node = State.Nodes[ptr.Node];
|
Node* node = State.Nodes[ptr.Node];
|
||||||
return (ptr.Input ? node->IO.Inputs : node->IO.Outputs)[ptr.Pin];
|
return (ptr.Input ? node->IO.Inputs : node->IO.Outputs)[ptr.Pin];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr constructor)
|
|
||||||
{
|
|
||||||
const std::string name = path.filename().string();
|
|
||||||
|
|
||||||
std::stack<std::string> decomp;
|
|
||||||
std::filesystem::path current = path.parent_path();
|
|
||||||
while(current.empty() == false)
|
|
||||||
{
|
|
||||||
decomp.push(current.filename().string());
|
|
||||||
current = current.parent_path();
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextID node = 0;
|
|
||||||
while(decomp.empty() == false)
|
|
||||||
{
|
|
||||||
ContextID child = ContextMenu.first_child(node);
|
|
||||||
|
|
||||||
while(child)
|
|
||||||
{
|
|
||||||
if(ContextMenu[child].Name == decomp.top())
|
|
||||||
{
|
|
||||||
node = child;
|
|
||||||
decomp.pop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
child = ContextMenu.next_sibling(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node == 0 || node != child)
|
|
||||||
{
|
|
||||||
node = ContextMenu.insert({ decomp.top(), nullptr }, node);
|
|
||||||
decomp.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextMenu.insert({ name, constructor }, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
Inspector::Inspector()
|
|
||||||
: EditorWindow("Inspector", 0)
|
|
||||||
, Graph(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Inspector::DrawWindow()
|
|
||||||
{
|
|
||||||
if(Graph->Mouse.Selected.size() != 1)
|
|
||||||
{
|
|
||||||
ImGui::Text("Selected %d nodes.", Graph->Mouse.Selected.size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Graph->State.Nodes[*Graph->Mouse.Selected.begin()]->Inspect();
|
|
||||||
}
|
|
14
imgui.ini
14
imgui.ini
@ -8,31 +8,31 @@ Size=400,400
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Dear ImGui Demo]
|
[Window][Dear ImGui Demo]
|
||||||
Pos=359,275
|
Pos=171,229
|
||||||
Size=375,341
|
Size=375,341
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][ Console]
|
[Window][ Console]
|
||||||
Pos=303,905
|
Pos=303,953
|
||||||
Size=3137,464
|
Size=3137,464
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][ Profiler]
|
[Window][ Profiler]
|
||||||
Pos=0,905
|
Pos=0,953
|
||||||
Size=301,464
|
Size=301,464
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][ Shader Graph]
|
[Window][ Shader Graph]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=3068,903
|
Size=3068,951
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][WindowOverViewport_11111111]
|
[Window][WindowOverViewport_11111111]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=3440,1369
|
Size=3440,1417
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Example: Custom rendering]
|
[Window][Example: Custom rendering]
|
||||||
@ -65,12 +65,12 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=3070,0
|
Pos=3070,0
|
||||||
Size=370,903
|
Size=370,951
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3440,1369 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,974 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 Selected=0xE7039252
|
||||||
|
Loading…
x
Reference in New Issue
Block a user