Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions Hesiod/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ set(CMAKE_AUTOMOC_VERBOSE ON)
# Source files
# ------------------------------
file(GLOB_RECURSE HESIOD_GUI_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
file(GLOB_RECURSE HESIOD_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE HESIOD_SOURCES CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

if(HESIOD_MINIMAL_NODE_SET)
# option for a minimal set of nodes for quick compile time when tempering with
Expand Down Expand Up @@ -59,7 +60,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE hesiod_core)
target_include_directories(
hesiod_core
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include
${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})
${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})

# ------------------------------
# Compiler features
Expand All @@ -72,24 +73,24 @@ target_compile_features(hesiod_core PUBLIC cxx_std_20)
target_link_libraries(
hesiod_core
PUBLIC hesiod_options
hesiod_platform
hesiod_qt_logging
args
spdlog::spdlog
nlohmann_json::nlohmann_json
highmap
gnode
gnodegui
meta
meta_qt
Qt6::Core
Qt6::OpenGL
Qt6::Widgets
Qt6::OpenGLWidgets
Qt6::WebEngineWidgets
qterrain-renderer
qtexture_downloader
ZLIB::ZLIB)
hesiod_platform
hesiod_qt_logging
args
spdlog::spdlog
nlohmann_json::nlohmann_json
highmap
gnode
gnodegui
meta
meta_qt
Qt6::Core
Qt6::OpenGL
Qt6::Widgets
Qt6::OpenGLWidgets
Qt6::WebEngineWidgets
qterrain-renderer
qtexture_downloader
ZLIB::ZLIB)

# ------------------------------
# Precompiled Headers (PCH)
Expand Down Expand Up @@ -134,10 +135,20 @@ message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

if(HESIOD_ENABLE_TESTS)
find_package(Qt6 REQUIRED COMPONENTS Test)
add_executable(test_graph_editor ${CMAKE_SOURCE_DIR}/tests/gui/test_graph_editor.cpp)
add_library(test_model_headers OBJECT
${CMAKE_SOURCE_DIR}/tests/model/model_headers.cpp)
set_target_properties(test_model_headers PROPERTIES AUTOMOC OFF)
target_include_directories(test_model_headers
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(test_model_headers PRIVATE gnode highmap meta)
target_compile_features(test_model_headers PRIVATE cxx_std_20)

add_executable(test_graph_editor
${CMAKE_SOURCE_DIR}/tests/gui/test_graph_editor.cpp)
add_dependencies(test_graph_editor test_model_headers)
target_link_libraries(test_graph_editor PRIVATE hesiod_core Qt6::Test)
add_test(NAME graph_editor COMMAND test_graph_editor)
set_tests_properties(graph_editor PROPERTIES
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
set_tests_properties(
graph_editor PROPERTIES WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
endif()
32 changes: 32 additions & 0 deletions Hesiod/include/hesiod/gui/hesiod_node_proxy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright (c) 2026 Otto Link. Distributed under the terms of the GNU General
* Public License. The full license is in the file LICENSE, distributed with
* this software. */
#pragma once
#include "gnodegui/node_proxy.hpp"

namespace hesiod
{
class BaseNode;

// The view owns the proxy; the graph owns the model.
class HesiodNodeProxy : public gngui::NodeProxy
{
public:
HesiodNodeProxy(std::weak_ptr<BaseNode> model, QObject *owner);

std::string get_id() const override;
void set_id(const std::string &id) override;
std::string get_caption() const override;
std::string get_category() const override;
std::string get_comment() const override;
std::string get_tool_tip_text() const override;
int get_nports() const override;
std::string get_port_caption(int index) const override;
gngui::PortType get_port_type(int index) const override;
std::string get_data_type(int index) const override;
void *get_data_ref(int index) const override;

private:
std::weak_ptr<BaseNode> model;
};
} // namespace hesiod
13 changes: 3 additions & 10 deletions Hesiod/include/hesiod/model/nodes/base_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <utility>

#include "gnode/node.hpp"
#include "gnodegui/node_proxy.hpp"

#include "meta/core/container_group.hpp"

Expand Down Expand Up @@ -57,6 +56,7 @@ class BaseNode : public gnode::Node, public std::enable_shared_from_this<BaseNod
std::string get_id() const;
void set_id(const std::string &new_id);
std::string get_category() const;
std::string get_comment() const;
void set_comment(const std::string &new_comment);
std::string get_node_type() const;

Expand All @@ -76,15 +76,8 @@ class BaseNode : public gnode::Node, public std::enable_shared_from_this<BaseNod
std::string get_documentation_short_html() const;
void update_attributes_tool_tip();

// --- Proxy (most of it) ---
std::string get_caption() const;
std::string get_comment() const;
void *get_data_ref(int port_index);
std::string get_data_type(int port_index) const;
int get_nports() const;
std::string get_port_caption(int port_index) const;
gngui::PortType get_port_type(int port_index) const;
std::string get_tool_tip_text();
using gnode::Node::get_port_type;
gnode::PortType get_port_type(int port_index) const;

// --- Meta Accessors & Helpers ---
template <typename T> decltype(auto) val(const std::string &key) const
Expand Down
8 changes: 4 additions & 4 deletions Hesiod/include/hesiod/model/nodes/port_catalog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <string>
#include <vector>

#include "gnodegui/node_proxy.hpp" // gngui::PortType
#include "gnode/port.hpp"

namespace hesiod
{
Expand All @@ -19,7 +19,7 @@ struct PortInfo
{
std::string name;
std::string data_type;
gngui::PortType direction;
gnode::PortType direction;
};

/**
Expand All @@ -45,7 +45,7 @@ class PortCatalog
*/
bool is_offerable(const std::string &node_type,
const std::string &data_type,
gngui::PortType wanted_direction) const;
gnode::PortType wanted_direction) const;

/// Ports of a node type, or nullptr when the type is unknown.
const std::vector<PortInfo> *find(const std::string &node_type) const;
Expand All @@ -65,6 +65,6 @@ class PortCatalog
*/
std::optional<std::string> select_port(const BaseNode &node,
const std::string &data_type,
gngui::PortType wanted_direction);
gnode::PortType wanted_direction);

} // namespace hesiod
2 changes: 1 addition & 1 deletion Hesiod/src/app/hesiod_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ void HesiodApplication::on_export_batch()
BaseNode *p_base = p_graph->get_node_ref_by_id<BaseNode>(nid);
NodeExportStatus st;
st.node_id = nid;
st.node_label = p_base ? p_base->get_caption() : nid;
st.node_label = p_base ? p_base->get_label() : nid;
st.node_type = p_base ? p_base->get_node_type() : "";
st.state = NodeComputeState::Pending;
scheduled_nodes.push_back(st);
Expand Down
38 changes: 19 additions & 19 deletions Hesiod/src/cli/check_port_links.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int conventional_rule_changed_outcome = 0;
void expect_offerable(const PortCatalog &catalog,
const std::string &node_type,
const std::string &data_type,
gngui::PortType wanted,
gnode::PortType wanted,
bool expected)
{
const bool got = catalog.is_offerable(node_type, data_type, wanted);
Expand All @@ -32,7 +32,7 @@ void expect_offerable(const PortCatalog &catalog,
Logger::log()->error("check-port-links: {} [{}, want {}]: offerable={} expected={}",
node_type,
data_type,
wanted == gngui::PortType::IN ? "IN" : "OUT",
wanted == gnode::PortType::IN ? "IN" : "OUT",
got,
expected);
failures++;
Expand All @@ -41,7 +41,7 @@ void expect_offerable(const PortCatalog &catalog,

void expect_selected(const std::string &node_type,
const std::string &data_type,
gngui::PortType wanted,
gnode::PortType wanted,
const std::string &expected_port)
{
auto config = std::make_shared<hesiod::GraphConfig>();
Expand All @@ -64,7 +64,7 @@ void expect_selected(const std::string &node_type,
"check-port-links: {} [{}, want {}]: selected '{}' expected '{}'",
node_type,
data_type,
wanted == gngui::PortType::IN ? "IN" : "OUT",
wanted == gnode::PortType::IN ? "IN" : "OUT",
got_str,
expected_port);
failures++;
Expand Down Expand Up @@ -110,7 +110,7 @@ void sweep_all_node_types(const PortCatalog &catalog)
}

for (const std::string &data_type : data_types)
for (gngui::PortType wanted : {gngui::PortType::IN, gngui::PortType::OUT})
for (gnode::PortType wanted : {gnode::PortType::IN, gnode::PortType::OUT})
{
const bool offered = catalog.is_offerable(node_type, data_type, wanted);
const std::optional<std::string> selected = hesiod::select_port(*p_base,
Expand All @@ -125,7 +125,7 @@ void sweep_all_node_types(const PortCatalog &catalog)
"node selected={} (documentation drift?)",
node_type,
data_type,
wanted == gngui::PortType::IN ? "IN" : "OUT",
wanted == gnode::PortType::IN ? "IN" : "OUT",
offered,
selected.has_value());
failures++;
Expand Down Expand Up @@ -164,7 +164,7 @@ void sweep_all_node_types(const PortCatalog &catalog)
std::string lower;
for (char c : label)
lower += static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
const bool conventional = (wanted == gngui::PortType::IN)
const bool conventional = (wanted == gnode::PortType::IN)
? (lower == "input" || lower == "in")
: (lower == "output" || lower == "out");
if (conventional)
Expand All @@ -182,7 +182,7 @@ void sweep_all_node_types(const PortCatalog &catalog)
"check-port-links: {} [{}, want {}]: oracle expected='{}' got='{}'",
node_type,
data_type,
wanted == gngui::PortType::IN ? "IN" : "OUT",
wanted == gnode::PortType::IN ? "IN" : "OUT",
expected ? *expected : std::string("<none>"),
selected ? *selected : std::string("<none>"));
failures++;
Expand Down Expand Up @@ -216,40 +216,40 @@ int run_check_port_links()
// IslandChain's only VirtualArray port is its OUTPUT, so dragging a
// VirtualArray from an output (wanting an input) must NOT offer it.
// This is the case that aborted the application.
expect_offerable(catalog, "IslandChain", "VirtualArray", gngui::PortType::IN, false);
expect_offerable(catalog, "IslandChain", "VirtualArray", gnode::PortType::IN, false);

// Dragging backwards from an input (wanting an output) must offer it.
expect_offerable(catalog, "IslandChain", "VirtualArray", gngui::PortType::OUT, true);
expect_offerable(catalog, "IslandChain", "VirtualArray", gnode::PortType::OUT, true);

// Its Path input is offerable when a Path is dragged from an output.
expect_offerable(catalog, "IslandChain", "Path", gngui::PortType::IN, true);
expect_offerable(catalog, "IslandChain", "Path", gnode::PortType::IN, true);

// Ordinary filters accept a VirtualArray input.
expect_offerable(catalog, "Laplace", "VirtualArray", gngui::PortType::IN, true);
expect_offerable(catalog, "Bump", "VirtualArray", gngui::PortType::IN, true);
expect_offerable(catalog, "Laplace", "VirtualArray", gnode::PortType::IN, true);
expect_offerable(catalog, "Bump", "VirtualArray", gnode::PortType::IN, true);

// Incompatible type is never offered.
expect_offerable(catalog, "Laplace", "VirtualTexture", gngui::PortType::IN, false);
expect_offerable(catalog, "Laplace", "VirtualTexture", gnode::PortType::IN, false);

// Unknown node type fails OPEN (never hide a real node if docs drift).
expect_offerable(catalog, "NoSuchNodeType", "VirtualArray", gngui::PortType::IN, true);
expect_offerable(catalog, "NoSuchNodeType", "VirtualArray", gnode::PortType::IN, true);

// --- pinned port-selection cases (live node, true declaration order)

// Conventional name wins: Laplace declares an "input" port.
expect_selected("Laplace", "VirtualArray", gngui::PortType::IN, "input");
expect_selected("Laplace", "VirtualArray", gnode::PortType::IN, "input");

// No conventional name: Bump declares dx, dy, control, envelope -> first
// declared wins. NOTE this is "dx" only because selection reads the LIVE
// node; the documentation's alphabetical key order would have given
// "control", which is why the catalog must never be used for selection.
expect_selected("Bump", "VirtualArray", gngui::PortType::IN, "dx");
expect_selected("Bump", "VirtualArray", gnode::PortType::IN, "dx");

// Backwards drag: wanting an OUTPUT of type VirtualArray.
expect_selected("IslandChain", "VirtualArray", gngui::PortType::OUT, "output");
expect_selected("IslandChain", "VirtualArray", gnode::PortType::OUT, "output");

// Forwards drag onto IslandChain has no VirtualArray input at all.
expect_selected("IslandChain", "VirtualArray", gngui::PortType::IN, "<none>");
expect_selected("IslandChain", "VirtualArray", gnode::PortType::IN, "<none>");

sweep_all_node_types(catalog);

Expand Down
Loading
Loading