From 3130d91f399bfb98911eb7437d261a781688408a Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 4 Aug 2025 12:16:19 +0100 Subject: [PATCH 01/14] feat: render split lines --- src/Gui/Viewport/GLMesh.cpp | 38 +++++++++++++++++++++++--------- src/Gui/Viewport/GLMesh.h | 6 +++-- src/OpDefs/GopGeometryImport.cpp | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/Gui/Viewport/GLMesh.cpp b/src/Gui/Viewport/GLMesh.cpp index 46a9d61..b4d147f 100644 --- a/src/Gui/Viewport/GLMesh.cpp +++ b/src/Gui/Viewport/GLMesh.cpp @@ -50,8 +50,9 @@ void GLMesh::initBuffers() glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); - glGenBuffers(1, &indexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glGenBuffers(1, &faceIndexBuffer); + glGenBuffers(1, &lineIndexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceIndexBuffer); } @@ -119,8 +120,8 @@ void GLMesh::setPosBuffer(enzo::geo::Geometry& geometry) void GLMesh::setIndexBuffer(std::vector pointIndices, std::vector primVertexCounts) { bind(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - indexData.clear(); + faceIndexData.clear(); + lineIndexData.clear(); unsigned int startVert = 0; @@ -130,18 +131,31 @@ void GLMesh::setIndexBuffer(std::vector pointIndices, std::vector prim int primVertexCount = primVertexCounts[primNum]; - for(size_t i=1; i=3) { - indexData.push_back(startVert); - indexData.push_back(startVert+i); - indexData.push_back(startVert+i+1); + for(size_t i=1; i vertexPosData; std::vector vertices; - std::vector indexData; + std::vector faceIndexData; + std::vector lineIndexData; void init(); void initBuffers(); diff --git a/src/OpDefs/GopGeometryImport.cpp b/src/OpDefs/GopGeometryImport.cpp index 9e539d2..fadf756 100644 --- a/src/OpDefs/GopGeometryImport.cpp +++ b/src/OpDefs/GopGeometryImport.cpp @@ -78,7 +78,7 @@ void GopGeometryImport::cookOp(enzo::op::Context context) const bt::Vector3 pointPos = {std::stod(result[1]), std::stod(result[2]), std::stod(result[3])}; PAttrHandle.addValue(pointPos); } - else if(firstChar=='f') + else if(firstChar=='f' || firstChar=='l') { std::vector result; boost::split(result, line, isspace); From 065e5f73ac2bc5b4c73b0f1e7b3873a7a29fec7c Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 4 Aug 2025 13:47:08 +0100 Subject: [PATCH 02/14] feat: render open and closed faces/lines --- src/Engine/Operator/Attribute.cpp | 18 +++++++---- src/Engine/Operator/Attribute.h | 5 ++-- src/Engine/Operator/AttributeHandle.h | 15 ++++++---- src/Engine/Operator/Geometry.cpp | 43 +++++++++++++++++++++++++-- src/Engine/Operator/Geometry.h | 16 +++++++--- src/Engine/Types.h | 2 ++ src/Gui/Viewport/GLMesh.cpp | 27 +++++++++-------- src/Gui/Viewport/GLMesh.h | 2 +- src/Gui/Viewport/ViewportGLWidget.cpp | 18 ++--------- src/OpDefs/GopGeometryImport.cpp | 35 ++++++++++++---------- tests/OperatorTests.cpp | 2 +- 11 files changed, 117 insertions(+), 66 deletions(-) diff --git a/src/Engine/Operator/Attribute.cpp b/src/Engine/Operator/Attribute.cpp index 048651f..637aa72 100644 --- a/src/Engine/Operator/Attribute.cpp +++ b/src/Engine/Operator/Attribute.cpp @@ -14,16 +14,19 @@ ga::Attribute::Attribute(std::string name, ga::AttributeType type) switch(type_) { case(AttrType::intT): - intStore_=std::make_shared>(); + intStore_=std::make_shared>(); break; case(AttrType::floatT): - floatStore_=std::make_shared>(); + floatStore_=std::make_shared>(); break; case(AttrType::vectorT): vector3Store_=std::make_shared>(); break; + case(AttrType::boolT): + boolStore_=std::make_shared>(); + break; default: - throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for"); + throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in Attribute constructor"); } @@ -40,16 +43,19 @@ ga::Attribute::Attribute(const Attribute& other) switch(type_) { case(AttrType::intT): - intStore_=std::make_shared>(*other.intStore_); + intStore_=std::make_shared>(*other.intStore_); break; case(AttrType::floatT): - floatStore_=std::make_shared>(*other.floatStore_); + floatStore_=std::make_shared>(*other.floatStore_); break; case(AttrType::vectorT): vector3Store_=std::make_shared>(*other.vector3Store_); break; + case(AttrType::boolT): + boolStore_=std::make_shared>(*other.boolStore_); + break; default: - throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for"); + throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in Attribute copy constructor"); } } diff --git a/src/Engine/Operator/Attribute.h b/src/Engine/Operator/Attribute.h index 365687e..8f4c6ad 100644 --- a/src/Engine/Operator/Attribute.h +++ b/src/Engine/Operator/Attribute.h @@ -46,9 +46,10 @@ namespace enzo{ // void* data_; // data stores - std::shared_ptr> intStore_; - std::shared_ptr> floatStore_; + std::shared_ptr> intStore_; + std::shared_ptr> floatStore_; std::shared_ptr> vector3Store_; + std::shared_ptr> boolStore_; }; diff --git a/src/Engine/Operator/AttributeHandle.h b/src/Engine/Operator/AttributeHandle.h index e3e0a49..0178409 100644 --- a/src/Engine/Operator/AttributeHandle.h +++ b/src/Engine/Operator/AttributeHandle.h @@ -27,13 +27,13 @@ public: // TODO: add the other types // int - if constexpr (std::is_same::value) + if constexpr (std::is_same::value) { data_=attribute->intStore_; } // float - else if constexpr (std::is_same::value) + else if constexpr (std::is_same::value) { data_=attribute->floatStore_; } @@ -43,9 +43,13 @@ public: { data_=attribute->vector3Store_; } + else if constexpr (std::is_same::value) + { + data_=attribute->boolStore_; + } else { - throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for"); + throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in AttributeHandle constructor"); } } @@ -109,8 +113,9 @@ private: }; -using AttributeHandleInt = AttributeHandle; -using AttributeHandleFloat = AttributeHandle; +using AttributeHandleInt = AttributeHandle; +using AttributeHandleFloat = AttributeHandle; using AttributeHandleVector3 = AttributeHandle; +using AttributeHandleBool = AttributeHandle; } diff --git a/src/Engine/Operator/Geometry.cpp b/src/Engine/Operator/Geometry.cpp index 069fb3e..8f2a72d 100644 --- a/src/Engine/Operator/Geometry.cpp +++ b/src/Engine/Operator/Geometry.cpp @@ -12,6 +12,7 @@ using namespace enzo; geo::Geometry::Geometry() : vertexCountHandlePrim_{addIntAttribute(ga::AttrOwner::PRIMITIVE, "vertexCount")}, + closedHandlePrim_{addBoolAttribute(ga::AttrOwner::PRIMITIVE, "closed")}, pointOffsetHandleVert_{addIntAttribute(ga::AttrOwner::VERTEX, "point")}, posHandlePoint_{addVector3Attribute(ga::AttrOwner::POINT, "P")} { @@ -19,27 +20,39 @@ geo::Geometry::Geometry() : } geo::Geometry::Geometry(const Geometry& other): + // attributes pointAttributes_{deepCopyAttributes(other.pointAttributes_)}, vertexAttributes_{deepCopyAttributes(other.vertexAttributes_)}, primitiveAttributes_{deepCopyAttributes(other.primitiveAttributes_)}, globalAttributes_{deepCopyAttributes(other.globalAttributes_)}, + + // handles vertexCountHandlePrim_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"))}, + closedHandlePrim_{enzo::ga::AttributeHandleBool(getAttribByName(ga::AttrOwner::PRIMITIVE, "closed"))}, pointOffsetHandleVert_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point"))}, posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))} { } -void geo::Geometry::addFace(std::initializer_list pointOffsets) +void geo::Geometry::addFace(std::vector pointOffsets, bool closed) { for(ga::Offset pointOffset : pointOffsets) { pointOffsetHandleVert_.addValue(pointOffset); } vertexCountHandlePrim_.addValue(pointOffsets.size()); + closedHandlePrim_.addValue(closed); } +void geo::Geometry::addPoint(const bt::Vector3& pos) +{ + posHandlePoint_.addValue(pos); + +} + + bt::Vector3 geo::Geometry::getPosFromVert(ga::Offset vertexOffset) const { // get point offset @@ -53,6 +66,12 @@ bt::Vector3 geo::Geometry::getPointPos(ga::Offset pointOffset) const return posHandlePoint_.getValue(pointOffset); } +void geo::Geometry::setPointPos(const ga::Offset offset, const bt::Vector3& pos) +{ + posHandlePoint_.setValue(offset, pos); +} + + unsigned int geo::Geometry::getPrimVertCount(ga::Offset primOffset) const { return vertexCountHandlePrim_.getValue(primOffset); @@ -68,6 +87,11 @@ ga::Offset geo::Geometry::getNumVerts() const return pointOffsetHandleVert_.getSize(); } +ga::Offset geo::Geometry::getNumPoints() const +{ + return posHandlePoint_.getSize(); +} + @@ -191,13 +215,26 @@ void geo::Geometry::computePrimStartVertices() -ga::AttributeHandle geo::Geometry::addIntAttribute(ga::AttributeOwner owner, std::string name) +ga::AttributeHandleInt geo::Geometry::addIntAttribute(ga::AttributeOwner owner, std::string name) { auto newAttribute = std::make_shared(name, ga::AttrType::intT); getAttributeStore(owner).push_back(newAttribute); - return ga::AttributeHandle(newAttribute); + return ga::AttributeHandleInt(newAttribute); } +ga::AttributeHandleBool geo::Geometry::addBoolAttribute(ga::AttributeOwner owner, std::string name) +{ + auto newAttribute = std::make_shared(name, ga::AttrType::boolT); + getAttributeStore(owner).push_back(newAttribute); + return ga::AttributeHandleBool(newAttribute); +} + +bt::boolT geo::Geometry::isClosed(ga::Offset primOffset) const +{ + return closedHandlePrim_.getValue(primOffset); +} + + ga::AttributeHandle geo::Geometry::addVector3Attribute(ga::AttributeOwner owner, std::string name) { auto newAttribute = std::make_shared(name, ga::AttrType::vectorT); diff --git a/src/Engine/Operator/Geometry.h b/src/Engine/Operator/Geometry.h index 833c97e..e865149 100644 --- a/src/Engine/Operator/Geometry.h +++ b/src/Engine/Operator/Geometry.h @@ -24,21 +24,28 @@ class Geometry public: Geometry(); Geometry(const Geometry& other); - ga::AttributeHandle addIntAttribute(ga::AttributeOwner owner, std::string name); + ga::AttributeHandle addIntAttribute(ga::AttributeOwner owner, std::string name); + ga::AttributeHandleBool addBoolAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandle addVector3Attribute(ga::AttributeOwner owner, std::string name); // TODO: return weak ptr std::shared_ptr getAttribByName(ga::AttributeOwner owner, std::string name); std::vector derivePointNormals(); HeMesh computeHalfEdgeMesh(); - // returns the first vertex of the primitive - void addFace(std::initializer_list pointOffsets); + void addFace(std::vector pointOffsets, bool closed=true); + void addPoint(const bt::Vector3& pos); - ga::Offset getPrimStartVertex(ga::Offset primOffset) const; + void setPointPos(const ga::Offset offset, const bt::Vector3& pos); + + ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; bt::Vector3 getPointPos(ga::Offset pointOffset) const; unsigned int getPrimVertCount(ga::Offset primOffset) const; ga::Offset getNumPrims() const; ga::Offset getNumVerts() const; + ga::Offset getNumPoints() const; + + bt::boolT isClosed(ga::Offset primOffset) const; + void computePrimStartVertices(); private: using attribVector = std::vector>; @@ -55,6 +62,7 @@ private: // handles enzo::ga::AttributeHandleInt vertexCountHandlePrim_; + enzo::ga::AttributeHandleBool closedHandlePrim_; enzo::ga::AttributeHandleInt pointOffsetHandleVert_; enzo::ga::AttributeHandleVector3 posHandlePoint_; }; diff --git a/src/Engine/Types.h b/src/Engine/Types.h index d1b84dc..4ced7d5 100644 --- a/src/Engine/Types.h +++ b/src/Engine/Types.h @@ -19,6 +19,7 @@ namespace enzo floatT, listT, vectorT, + boolT, }; using AttrType = AttributeType; using AttrOwner = AttributeOwner; @@ -29,6 +30,7 @@ namespace enzo { using floatT = double; using intT = int64_t; + using boolT = bool; using Vector3 = Eigen::Vector3d; using Vector4 = Eigen::Vector4d; using String = std::string; diff --git a/src/Gui/Viewport/GLMesh.cpp b/src/Gui/Viewport/GLMesh.cpp index b4d147f..15d0a98 100644 --- a/src/Gui/Viewport/GLMesh.cpp +++ b/src/Gui/Viewport/GLMesh.cpp @@ -117,21 +117,29 @@ void GLMesh::setPosBuffer(enzo::geo::Geometry& geometry) unbind(); } -void GLMesh::setIndexBuffer(std::vector pointIndices, std::vector primVertexCounts) +void GLMesh::setIndexBuffer(enzo::geo::Geometry& geometry) { bind(); faceIndexData.clear(); lineIndexData.clear(); - unsigned int startVert = 0; // create triangle fan from potentially ngon inputs - for(size_t primNum=0; primNum=3) + if(!closed && primVertexCount>=2) + { + for(size_t i=0; i=3) { for(size_t i=1; i pointIndices, std::vector prim } } - if(primVertexCount==2) - { - IC(startVert, startVert+1); - lineIndexData.push_back(startVert); - lineIndexData.push_back(startVert+1); - } - startVert += primVertexCount; } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceIndexBuffer); diff --git a/src/Gui/Viewport/GLMesh.h b/src/Gui/Viewport/GLMesh.h index ce773b9..6083ca7 100644 --- a/src/Gui/Viewport/GLMesh.h +++ b/src/Gui/Viewport/GLMesh.h @@ -29,7 +29,7 @@ public: void init(); void initBuffers(); void setPosBuffer(enzo::geo::Geometry& geometry); - void setIndexBuffer(std::vector pointIndices, std::vector primVertexCounts); + void setIndexBuffer(enzo::geo::Geometry& geometry); void bind(); void unbind(); void draw(); diff --git a/src/Gui/Viewport/ViewportGLWidget.cpp b/src/Gui/Viewport/ViewportGLWidget.cpp index f2cbe58..14c8ff4 100644 --- a/src/Gui/Viewport/ViewportGLWidget.cpp +++ b/src/Gui/Viewport/ViewportGLWidget.cpp @@ -184,14 +184,7 @@ std::unique_ptr ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geome mesh->setPosBuffer(geometry); - - std::shared_ptr pointAttr = geometry.getAttribByName(ga::AttrOwner::VERTEX, "point"); - ga::AttributeHandleInt pointAttrHandle = ga::AttributeHandleInt(pointAttr); - - std::shared_ptr vertexCountAttr = geometry.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"); - ga::AttributeHandleInt vertexCountHandle = ga::AttributeHandleInt(vertexCountAttr); - - mesh->setIndexBuffer(pointAttrHandle.getAllValues(), vertexCountHandle.getAllValues()); + mesh->setIndexBuffer(geometry); @@ -205,12 +198,5 @@ void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry) ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); triangleMesh_->setPosBuffer(geometry); - - std::shared_ptr pointAttr = geometry.getAttribByName(ga::AttrOwner::VERTEX, "point"); - ga::AttributeHandleInt pointAttrHandle = ga::AttributeHandleInt(pointAttr); - - std::shared_ptr vertexCountAttr = geometry.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"); - ga::AttributeHandleInt vertexCountHandle = ga::AttributeHandleInt(vertexCountAttr); - - triangleMesh_->setIndexBuffer(pointAttrHandle.getAllValues(), vertexCountHandle.getAllValues()); + triangleMesh_->setIndexBuffer(geometry); } diff --git a/src/OpDefs/GopGeometryImport.cpp b/src/OpDefs/GopGeometryImport.cpp index fadf756..29eba6c 100644 --- a/src/OpDefs/GopGeometryImport.cpp +++ b/src/OpDefs/GopGeometryImport.cpp @@ -40,14 +40,14 @@ void GopGeometryImport::cookOp(enzo::op::Context context) } - auto PAttr = geo.getAttribByName(ga::AttrOwner::POINT, "P"); - ga::AttributeHandleVector3 PAttrHandle(PAttr); + // auto PAttr = geo.getAttribByName(ga::AttrOwner::POINT, "P"); + // ga::AttributeHandleVector3 PAttrHandle(PAttr); - auto pointAttr = geo.getAttribByName(ga::AttrOwner::VERTEX, "point"); - ga::AttributeHandleInt pointAttrHandle(pointAttr); + // auto pointAttr = geo.getAttribByName(ga::AttrOwner::VERTEX, "point"); + // ga::AttributeHandleInt pointAttrHandle(pointAttr); - auto vertexCountAttr = geo.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"); - ga::AttributeHandleInt vertexCountHandle(vertexCountAttr); + // auto vertexCountAttr = geo.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"); + // ga::AttributeHandleInt vertexCountHandle(vertexCountAttr); std::ifstream file(filePath); if(!file.is_open()) @@ -76,10 +76,12 @@ void GopGeometryImport::cookOp(enzo::op::Context context) } const bt::Vector3 pointPos = {std::stod(result[1]), std::stod(result[2]), std::stod(result[3])}; - PAttrHandle.addValue(pointPos); + geo.addPoint(pointPos); } else if(firstChar=='f' || firstChar=='l') { + bool closedFace = firstChar=='f'; + std::vector result; boost::split(result, line, isspace); if(result.size()<3) @@ -88,16 +90,18 @@ void GopGeometryImport::cookOp(enzo::op::Context context) } + ga::Offset numVerts = result.size()-1; + + std::vector verts; + verts.reserve(numVerts); // set vertex attributes - for(int i=1; i myHandle = geo.addIntAttribute(ga::AttrOwner::POINT, "index"); + ga::AttributeHandleInt myHandle = geo.addIntAttribute(ga::AttrOwner::POINT, "index"); myHandle.addValue(5); myHandle.addValue(6); REQUIRE(myHandle.getValue(0)==5); From 123f6d30fe82a8d0ac5681022d03fe20873aa9c8 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 4 Aug 2025 22:56:06 +0100 Subject: [PATCH 03/14] feat: opengl point rendering --- CMakeLists.txt | 1 + src/Gui/Viewport/GLCamera.cpp | 4 + src/Gui/Viewport/GLCamera.h | 1 + src/Gui/Viewport/GLPoints.cpp | 211 ++++++++++++++++++++++++++ src/Gui/Viewport/GLPoints.h | 43 ++++++ src/Gui/Viewport/ViewportGLWidget.cpp | 42 +++-- src/Gui/Viewport/ViewportGLWidget.h | 4 +- src/Gui/main.cpp | 2 +- 8 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 src/Gui/Viewport/GLPoints.cpp create mode 100644 src/Gui/Viewport/GLPoints.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c759eb3..ad55f02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(GUI_SOURCES src/Gui/Viewport/GLCamera.cpp src/Gui/Viewport/GLMesh.cpp src/Gui/Viewport/GLGrid.cpp + src/Gui/Viewport/GLPoints.cpp src/Gui/Network/NetworkGraphicsView.cpp src/Gui/Network/NetworkGraphicsScene.cpp src/Gui/Network/Network.cpp diff --git a/src/Gui/Viewport/GLCamera.cpp b/src/Gui/Viewport/GLCamera.cpp index d226a14..ead83e7 100644 --- a/src/Gui/Viewport/GLCamera.cpp +++ b/src/Gui/Viewport/GLCamera.cpp @@ -123,6 +123,10 @@ void GLCamera::changeRadius(float delta) } +glm::vec3 GLCamera::getPos() +{ + return camPos_; +}; glm::vec3 GLCamera::getRight() { diff --git a/src/Gui/Viewport/GLCamera.h b/src/Gui/Viewport/GLCamera.h index f353e9a..b3a940a 100644 --- a/src/Gui/Viewport/GLCamera.h +++ b/src/Gui/Viewport/GLCamera.h @@ -16,6 +16,7 @@ public: void setCenter(float x, float y, float z); void setUniform(uint uniformLocation); + glm::vec3 getPos(); glm::vec3 getForward(); glm::vec3 getRight(); glm::vec3 getUp(); diff --git a/src/Gui/Viewport/GLPoints.cpp b/src/Gui/Viewport/GLPoints.cpp new file mode 100644 index 0000000..c5d7fd1 --- /dev/null +++ b/src/Gui/Viewport/GLPoints.cpp @@ -0,0 +1,211 @@ + +#include "Gui/Viewport/GLPoints.h" +#include +#include +#include +#include +#include +#include +#include "Engine/Types.h" +#include "Gui/Viewport/GLCamera.h" +#include "icecream.hpp" + +#define GLM_ENABLE_EXPERIMENTAL +#include + + +GLPoints::GLPoints() +{ + initializeOpenGLFunctions(); + init(); +} + +void GLPoints::init() +{ + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + initBuffers(); + initShaderProgram(); + + // unbind vertex array + glBindVertexArray(0); +} + +void GLPoints::initBuffers() +{ + const GLfloat billboardVertexPositions[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + }; + + points_ = {}; + pointCount = points_.size(); + + glGenBuffers(1, &billboardVertexBuffer_); + glBindBuffer(GL_ARRAY_BUFFER, billboardVertexBuffer_); + glBufferData(GL_ARRAY_BUFFER, sizeof(billboardVertexPositions), billboardVertexPositions, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glGenBuffers(1, &pointDataBuffer_); + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)0); + glVertexAttribDivisor(1, 1); +} + + +void GLPoints::setPoints(enzo::geo::Geometry& geometry, GLCamera& camera) +{ + const enzo::ga::Offset numPoints = geometry.getNumPoints(); + const glm::vec3 camPosGlm = camera.getPos(); + const enzo::bt::Vector3 camPos(camPosGlm.x, camPosGlm.y, camPosGlm.z); + + points_ = std::vector(numPoints); + + for(enzo::ga::Offset ptOffset=0; ptOffset((pos-camPos).norm())*0.005f}; + } + pointCount = points_.size(); + + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); +} + +void GLPoints::updatePointSize(GLCamera& camera) +{ + const glm::vec3 camPosGlm = camera.getPos(); + + for(Point& point : points_) + { + point = {point.position, glm::distance(point.position,camPosGlm)*0.005f}; + } + + glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); + glBufferData(GL_ARRAY_BUFFER, points_.size() * sizeof(Point), points_.data(), GL_STATIC_DRAW); +} + + + +void GLPoints::initShaderProgram() +{ + // vertex shader + const std::string vertexShaderSource = R"( + #version 330 core + uniform mat4 uView; + uniform mat4 uProj; + layout(location = 0) in vec3 aPos; + layout(location = 1) in vec4 aOffsetScale; + + out vec2 vLocal; + + void main() + { + vec3 right = vec3(uView[0][0], uView[1][0], uView[2][0]); + vec3 up = vec3(uView[0][1], uView[1][1], uView[2][1]); + + vLocal = aPos.xy; + vec3 worldPos = aOffsetScale.xyz + + (right * aPos.x + up * aPos.y) * aOffsetScale.w; + + gl_Position = uProj * uView * vec4(worldPos, 1.0); + } + )"; + // shader type + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + // convert source + const GLchar* vertexShaderSourceC = vertexShaderSource.c_str(); + // create shader object + glShaderSource(vertexShader, 1, &vertexShaderSourceC, NULL); + // compile shader object + glCompileShader(vertexShader); + + + // log shader error + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if(!success) + { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + } + else + { + std::cout << "success\n"; + + } + + + // fragment shader + const std::string fragmentShaderSource = R"( + #version 330 core + in vec2 vLocal; + out vec4 FragColor; + + void main() + { + if (length(vLocal) > 0.5) discard; + FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } + )"; + + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar* fragmentShaderSourceC = fragmentShaderSource.c_str(); + glShaderSource(fragmentShader, 1, &fragmentShaderSourceC, NULL); + glCompileShader(fragmentShader); + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if(!success) + { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; + } + else + { + std::cout << "success\n"; + + } + + // create shader program + shaderProgram = glCreateProgram(); + // attach shaders + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + // link program + glLinkProgram(shaderProgram); + + // delete shaders now that the program is complete + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); +} + + + +void GLPoints::bind() +{ + glBindVertexArray(vao); +} + +void GLPoints::useProgram() +{ + glUseProgram(shaderProgram); +} + + +void GLPoints::unbind() +{ + glBindVertexArray(0); +} + +void GLPoints::draw() +{ + bind(); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, pointCount); +} diff --git a/src/Gui/Viewport/GLPoints.h b/src/Gui/Viewport/GLPoints.h new file mode 100644 index 0000000..57fe0cc --- /dev/null +++ b/src/Gui/Viewport/GLPoints.h @@ -0,0 +1,43 @@ +#pragma once +#include "Engine/Types.h" +#include +#include +#include +#include +#include "Engine/Operator/Geometry.h" +#include "Gui/Viewport/GLCamera.h" + +struct Point +{ + glm::vec3 position; + float scale; +}; + +class GLPoints +: protected QOpenGLFunctions_3_3_Core +{ +public: + GLPoints(); + GLuint vao; + + GLuint billboardVertexBuffer_; + GLuint pointDataBuffer_; + GLuint shaderProgram; + + + + std::vector faceIndexData; + std::vector points_; + + enzo::ga::Offset pointCount; + + void init(); + void initBuffers(); + void initShaderProgram(); + void setPoints(enzo::geo::Geometry& geometry, GLCamera& camera); + void updatePointSize(GLCamera& camera); + void useProgram(); + void bind(); + void unbind(); + void draw(); +}; diff --git a/src/Gui/Viewport/ViewportGLWidget.cpp b/src/Gui/Viewport/ViewportGLWidget.cpp index 14c8ff4..167bec5 100644 --- a/src/Gui/Viewport/ViewportGLWidget.cpp +++ b/src/Gui/Viewport/ViewportGLWidget.cpp @@ -2,6 +2,7 @@ #include "Engine/Operator/AttributeHandle.h" #include "Engine/Types.h" #include "Gui/Viewport/GLMesh.h" +#include "Gui/Viewport/GLPoints.h" #include #include #include @@ -21,9 +22,9 @@ void ViewportGLWidget::initializeGL() glEnable(GL_MULTISAMPLE); enzo::geo::Geometry geo = enzo::geo::Geometry(); - // triangleMesh_ = meshFromGeo(geo); triangleMesh_ = std::make_unique(); gridMesh_ = std::make_unique(); + points_ = std::make_unique(); QSurfaceFormat fmt = context()->format(); std::cout << "format: " << (fmt.renderableType() == QSurfaceFormat::OpenGLES ? "GLES" : "Desktop") << "\n"; @@ -154,9 +155,10 @@ void ViewportGLWidget::paintGL() 1000.0f // far plane ); + gridMesh_->useProgram(); - glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); - curCamera.setUniform(glGetUniformLocation(shaderProgram, "uView")); + glUniformMatrix4fv(glGetUniformLocation(gridMesh_->shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); + curCamera.setUniform(glGetUniformLocation(gridMesh_->shaderProgram, "uView")); gridMesh_->draw(); @@ -170,26 +172,36 @@ void ViewportGLWidget::paintGL() triangleMesh_->draw(); + points_->useProgram(); + points_->bind(); + points_->updatePointSize(curCamera); + glUniformMatrix4fv(glGetUniformLocation(points_->shaderProgram, "uProj"), 1, GL_FALSE, glm::value_ptr(projMatrix)); + curCamera.setUniform(glGetUniformLocation(points_->shaderProgram, "uView")); + + glUniform3fv(glGetUniformLocation(points_->shaderProgram, "uCameraRight"), 1, glm::value_ptr(curCamera.getRight())); + glUniform3fv(glGetUniformLocation(points_->shaderProgram, "uCameraUp"), 1, glm::value_ptr(curCamera.getUp())); + points_->draw(); + } -std::unique_ptr ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geometry) -{ - using namespace enzo; +// std::unique_ptr ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geometry) +// { +// using namespace enzo; - auto mesh = std::make_unique(); - - std::shared_ptr PAttr = geometry.getAttribByName(ga::AttrOwner::POINT, "P"); - ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); +// auto mesh = std::make_unique(); +// +// std::shared_ptr PAttr = geometry.getAttribByName(ga::AttrOwner::POINT, "P"); +// ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); - mesh->setPosBuffer(geometry); - mesh->setIndexBuffer(geometry); +// mesh->setPosBuffer(geometry); +// mesh->setIndexBuffer(geometry); - return mesh; -} +// return mesh; +// } void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry) { @@ -199,4 +211,6 @@ void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry) triangleMesh_->setPosBuffer(geometry); triangleMesh_->setIndexBuffer(geometry); + + points_->setPoints(geometry, curCamera); } diff --git a/src/Gui/Viewport/ViewportGLWidget.h b/src/Gui/Viewport/ViewportGLWidget.h index 2917873..22c3b43 100644 --- a/src/Gui/Viewport/ViewportGLWidget.h +++ b/src/Gui/Viewport/ViewportGLWidget.h @@ -6,6 +6,7 @@ #include "Gui/Viewport/GLCamera.h" #include "Gui/Viewport/GLMesh.h" #include "Gui/Viewport/GLGrid.h" +#include "Gui/Viewport/GLPoints.h" #include "Engine/Operator/Geometry.h" class ViewportGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_2_Core @@ -17,8 +18,9 @@ public: GLCamera curCamera; std::unique_ptr triangleMesh_ ; std::unique_ptr gridMesh_ ; + std::unique_ptr points_ ; - std::unique_ptr meshFromGeo(enzo::geo::Geometry& geometry); + // std::unique_ptr meshFromGeo(enzo::geo::Geometry& geometry); protected: void initializeGL() override; diff --git a/src/Gui/main.cpp b/src/Gui/main.cpp index 48f0933..fcf5f90 100644 --- a/src/Gui/main.cpp +++ b/src/Gui/main.cpp @@ -10,7 +10,7 @@ int main(int argc, char **argv) // set up rendering QSurfaceFormat format; format.setRenderableType(QSurfaceFormat::OpenGL); - format.setVersion(3, 2); + format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); format.setSamples(4); QSurfaceFormat::setDefaultFormat(format); From 2a0afc7c24024a178fc54aa4bf2df776017ec8b9 Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 5 Aug 2025 02:03:51 +0100 Subject: [PATCH 04/14] feat: only render solo points --- src/Engine/Operator/Geometry.cpp | 25 ++++++++++++++++++++++++- src/Engine/Operator/Geometry.h | 6 ++++++ src/Gui/Viewport/GLPoints.cpp | 19 +++++++++++-------- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/Engine/Operator/Geometry.cpp b/src/Engine/Operator/Geometry.cpp index 8f2a72d..a3e1cdc 100644 --- a/src/Engine/Operator/Geometry.cpp +++ b/src/Engine/Operator/Geometry.cpp @@ -30,7 +30,10 @@ geo::Geometry::Geometry(const Geometry& other): vertexCountHandlePrim_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"))}, closedHandlePrim_{enzo::ga::AttributeHandleBool(getAttribByName(ga::AttrOwner::PRIMITIVE, "closed"))}, pointOffsetHandleVert_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point"))}, - posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))} + posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))}, + + // other + soloPoints_{other.soloPoints_} { } @@ -40,6 +43,7 @@ void geo::Geometry::addFace(std::vector pointOffsets, bool closed) for(ga::Offset pointOffset : pointOffsets) { pointOffsetHandleVert_.addValue(pointOffset); + soloPoints_.erase(pointOffset); } vertexCountHandlePrim_.addValue(pointOffsets.size()); closedHandlePrim_.addValue(closed); @@ -49,10 +53,29 @@ void geo::Geometry::addFace(std::vector pointOffsets, bool closed) void geo::Geometry::addPoint(const bt::Vector3& pos) { posHandlePoint_.addValue(pos); + soloPoints_.emplace(posHandlePoint_.getSize()-1); +} + +ga::Offset geo::Geometry::getNumSoloPoints() const +{ + return soloPoints_.size(); } + +std::set::const_iterator geo::Geometry::soloPointsBegin() +{ + return soloPoints_.begin(); +} + +std::set::const_iterator geo::Geometry::soloPointsEnd() +{ + return soloPoints_.end(); +} + + + bt::Vector3 geo::Geometry::getPosFromVert(ga::Offset vertexOffset) const { // get point offset diff --git a/src/Engine/Operator/Geometry.h b/src/Engine/Operator/Geometry.h index e865149..5d9516a 100644 --- a/src/Engine/Operator/Geometry.h +++ b/src/Engine/Operator/Geometry.h @@ -34,6 +34,9 @@ public: void addFace(std::vector pointOffsets, bool closed=true); void addPoint(const bt::Vector3& pos); + std::set::const_iterator soloPointsBegin(); + std::set::const_iterator soloPointsEnd(); + void setPointPos(const ga::Offset offset, const bt::Vector3& pos); ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive @@ -43,6 +46,7 @@ public: ga::Offset getNumPrims() const; ga::Offset getNumVerts() const; ga::Offset getNumPoints() const; + ga::Offset getNumSoloPoints() const; bt::boolT isClosed(ga::Offset primOffset) const; @@ -58,6 +62,8 @@ private: attribVector primitiveAttributes_; attribVector globalAttributes_; + std::set soloPoints_; + std::vector primStarts_; // handles diff --git a/src/Gui/Viewport/GLPoints.cpp b/src/Gui/Viewport/GLPoints.cpp index c5d7fd1..89f9e97 100644 --- a/src/Gui/Viewport/GLPoints.cpp +++ b/src/Gui/Viewport/GLPoints.cpp @@ -10,9 +10,6 @@ #include "Gui/Viewport/GLCamera.h" #include "icecream.hpp" -#define GLM_ENABLE_EXPERIMENTAL -#include - GLPoints::GLPoints() { @@ -61,17 +58,23 @@ void GLPoints::initBuffers() void GLPoints::setPoints(enzo::geo::Geometry& geometry, GLCamera& camera) { - const enzo::ga::Offset numPoints = geometry.getNumPoints(); + const enzo::ga::Offset numPoints = geometry.getNumSoloPoints(); const glm::vec3 camPosGlm = camera.getPos(); const enzo::bt::Vector3 camPos(camPosGlm.x, camPosGlm.y, camPosGlm.z); points_ = std::vector(numPoints); - for(enzo::ga::Offset ptOffset=0; ptOffset soloPoints = {geometry.soloPointsBegin(), geometry.soloPointsEnd()}; + + tbb::parallel_for(tbb::blocked_range(0, numPoints), [&](tbb::blocked_range range) { - const enzo::bt::Vector3 pos = geometry.getPointPos(ptOffset); - points_[ptOffset] = {glm::vec3(pos.x(), pos.y(), pos.z()), static_cast((pos-camPos).norm())*0.005f}; - } + for(enzo::ga::Offset i=range.begin(); i((pos-camPos).norm())*0.005f}; + } + }); pointCount = points_.size(); glBindBuffer(GL_ARRAY_BUFFER, pointDataBuffer_); From ef372a9630ca05ff115932cc95cd262e1ac68954 Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 5 Aug 2025 19:48:22 +0100 Subject: [PATCH 05/14] feat: add geometry spreadsheet widget --- CMakeLists.txt | 2 + .../GeometrySpreadsheetMenuBar.cpp | 132 ++++++++++++++++++ .../GeometrySpreadsheetMenuBar.h | 39 ++++++ .../GeometrySpreadsheetPanel.cpp | 43 ++++++ .../GeometrySpreadsheetPanel.h | 20 +++ src/Gui/Interface.cpp | 18 ++- src/Gui/Interface.h | 1 + 7 files changed, 249 insertions(+), 6 deletions(-) create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ad55f02..ff59e0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,8 @@ set(GUI_SOURCES src/Gui/main.cpp src/Gui/Interface.cpp src/Gui/UtilWidgets/Splitter.cpp + src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp + src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp src/Gui/Viewport/Viewport.cpp src/Gui/Viewport/ViewportGLWidget.cpp src/Gui/Viewport/GLCamera.cpp diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp new file mode 100644 index 0000000..966d202 --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -0,0 +1,132 @@ +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" +#include +#include +#include +#include +#include +#include +#include +#include + +GeoSheetModeButton::GeoSheetModeButton(QWidget* parent) +: QPushButton(parent) +{ + setFixedSize(QSize(23,23)); + setObjectName("GeoSheetModeButton"); + setCheckable(true); + // setStyleSheet( + // R"( + // #GeoSheetModeButton + // { + // background: transparent; + // border: none; + // } + // #GeoSheetModeButton::checked + // { + // opacity: 50; + // border: none; + // } + // )"); + + setIcon(QIcon(":/node-icons/grid.svg")); +} + +void GeoSheetModeButton::enterEvent(QEnterEvent *event) +{ + hovered_=true; + QPushButton::enterEvent(event); + +} + +void GeoSheetModeButton::leaveEvent(QEvent *event) +{ + hovered_=false; + QPushButton::leaveEvent(event); +} + +void GeoSheetModeButton::paintEvent(QPaintEvent* event) +{ + const QIcon buttonIcon = icon(); + + if(!buttonIcon.isNull()) + { + QPainter painter(this); + + QSize size = iconSize(); + + if(!isChecked()) + { + painter.setOpacity(0.5); + } + if(hovered_) + { + size*=1.1; + } + + + + QPixmap pixmap = buttonIcon.pixmap(size); + QPoint center = event->rect().center() - QPoint(size.width() / 2, size.height() / 2); + // QPoint center = QPoint(0,0); + painter.drawPixmap(center, pixmap); + + } + +} + + +GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +{ + mainLayout_ = new QHBoxLayout(); + QWidget* buttonBg = new QWidget(); + buttonBg->setObjectName("GeoSheetMenuBarButtonBg"); + buttonBg->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + constexpr int bgSizeMargin = 5; + buttonBg->setContentsMargins(bgSizeMargin,0,bgSizeMargin,0); + buttonBg->setStyleSheet( + R"( + #GeoSheetMenuBarButtonBg + { + background-color: #383838; + border-radius: 8px; + } + + )"); + QHBoxLayout* buttonBgLayout = new QHBoxLayout(); + constexpr int margin = 0; + buttonBgLayout->setContentsMargins(margin,margin,margin,margin); + + modeButtonGroup_.setExclusive(true); + + auto newButton = [this, &buttonBgLayout]() + { + auto newButton = new GeoSheetModeButton(); + modeButtonGroup_.addButton(newButton); + buttonBgLayout->addWidget(newButton); + return newButton; + }; + + auto pointButton = newButton(); + auto vertButton = newButton(); + auto primButton = newButton(); + auto globalButton = newButton(); + + pointButton->setChecked(true); + + buttonBg->setLayout(buttonBgLayout); + + mainLayout_->addWidget(buttonBg); + + setLayout(mainLayout_); +} + +GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +{ + mainLayout_ = new QHBoxLayout(); + mainLayout_->addWidget(new QLabel("Node: testGeometryRat")); + mainLayout_->addWidget(new GeoSheetMenuBarModeSelection()); + + setLayout(mainLayout_); +} diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h new file mode 100644 index 0000000..4b4e433 --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +class GeoSheetModeButton +: public QPushButton +{ +public: + GeoSheetModeButton(QWidget *parent = nullptr); +private: + QHBoxLayout* mainLayout_; +protected: + void paintEvent(QPaintEvent *) override; + void enterEvent(QEnterEvent *event) override; + void leaveEvent(QEvent *event) override; + bool hovered_ = false; +}; + +class GeometrySpreadsheetMenuBar +: public QWidget +{ +public: + GeometrySpreadsheetMenuBar(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); +private: + QHBoxLayout* mainLayout_; +}; + +class GeoSheetMenuBarModeSelection +: public QWidget +{ +public: + GeoSheetMenuBarModeSelection(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); +private: + QHBoxLayout* mainLayout_; + QButtonGroup modeButtonGroup_; +}; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp new file mode 100644 index 0000000..4a31c26 --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -0,0 +1,43 @@ +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h" +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" +#include +#include +#include +#include +#include +#include + +GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +{ + mainLayout_ = new QVBoxLayout(); + + + auto *t = new QTreeView(parent); + t->setRootIsDecorated(false); + t->setAlternatingRowColors(true); + t->setStyleSheet(R"( + QTreeView { + background-color: #282828; + alternate-background-color: #242424; + paint-alternating-row-colors-for-empty-area: 1; + } + )"); + t->setFrameStyle(QFrame::NoFrame); + + + mainLayout_->addWidget(new GeometrySpreadsheetMenuBar()); + mainLayout_->addWidget(t); + + setLayout(mainLayout_); +} + +void GeometrySpreadsheetPanel::resizeEvent(QResizeEvent *event) +{ + QPainterPath path; + constexpr float radius = 10; + path.addRoundedRect(mainLayout_->contentsRect(), radius, radius); + QRegion region = QRegion(path.toFillPolygon().toPolygon()); + this->setMask(region); +} + diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h new file mode 100644 index 0000000..6a9fc75 --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class GeometrySpreadsheetPanel +: public QWidget +{ +public: + GeometrySpreadsheetPanel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); +public Q_SLOTS: + void selectionChanged(); +private: + QVBoxLayout* mainLayout_; + QWidget* bgWidget_; +protected: + void resizeEvent(QResizeEvent *event) override; + + +}; diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index 66baf14..a298093 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -1,5 +1,6 @@ #include "Gui/Interface.h" #include "Engine/Network/NetworkManager.h" +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h" #include "Gui/ParametersPanel/ParametersPanel.h" #include "Gui/Viewport/Viewport.h" #include "Gui/Network/Network.h" @@ -26,30 +27,35 @@ EnzoUI::EnzoUI() Viewport* viewport = new Viewport(); Network* network = new Network(); ParametersPanel* parametersPanel = new ParametersPanel(); + GeometrySpreadsheetPanel* geometrySpreadsheetPanel = new GeometrySpreadsheetPanel(); constexpr int margin = 2; viewport->layout()->setContentsMargins(margin, margin, margin, margin); network->layout()->setContentsMargins(margin, margin, margin, margin); parametersPanel->layout()->setContentsMargins(margin, margin, margin, margin); + geometrySpreadsheetPanel->layout()->setContentsMargins(margin, margin, margin, margin); mainLayout_->setContentsMargins(margin, margin, margin, margin); + // TODO: dynamic splitters viewportSplitter_ = new Splitter(this); networkSplitter_ = new Splitter(this); + spreadsheetSplitter_ = new Splitter(this); networkSplitter_->setOrientation(Qt::Vertical); + spreadsheetSplitter_->setOrientation(Qt::Vertical); + spreadsheetSplitter_->addWidget(viewport); + spreadsheetSplitter_->addWidget(geometrySpreadsheetPanel); + spreadsheetSplitter_->setSizes({200,100}); - - viewportSplitter_->addWidget(viewport); + viewportSplitter_->addWidget(spreadsheetSplitter_); viewportSplitter_->addWidget(networkSplitter_); - viewportSplitter_->setStretchFactor(0, 4); - viewportSplitter_->setStretchFactor(1, 1); + viewportSplitter_->setSizes({100,100}); networkSplitter_->addWidget(parametersPanel); networkSplitter_->addWidget(network); - networkSplitter_->setStretchFactor(0, 10); - networkSplitter_->setStretchFactor(1, 1); + networkSplitter_->setSizes({40,100}); mainLayout_->addWidget(viewportSplitter_); diff --git a/src/Gui/Interface.h b/src/Gui/Interface.h index f84180e..7355022 100644 --- a/src/Gui/Interface.h +++ b/src/Gui/Interface.h @@ -15,6 +15,7 @@ class EnzoUI QVBoxLayout* viewportSplitLayout_; Splitter* viewportSplitter_; Splitter* networkSplitter_; + Splitter* spreadsheetSplitter_; }; From 2c139a5f6a417cd20b21c5f4b9f07bbbc62b4c1a Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 5 Aug 2025 22:10:10 +0100 Subject: [PATCH 06/14] feat: basic geometry spreadsheet model --- CMakeLists.txt | 1 + .../GeometrySpreadsheetModel.cpp | 32 +++++++++++++++++++ .../GeometrySpreadsheetModel.h | 19 +++++++++++ .../GeometrySpreadsheetPanel.cpp | 4 +++ 4 files changed, 56 insertions(+) create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp create mode 100644 src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ff59e0a..f151d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(GUI_SOURCES src/Gui/UtilWidgets/Splitter.cpp src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp + src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp src/Gui/Viewport/Viewport.cpp src/Gui/Viewport/ViewportGLWidget.cpp src/Gui/Viewport/GLCamera.cpp diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp new file mode 100644 index 0000000..bf3fe2f --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -0,0 +1,32 @@ +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" + +int GeometrySpreadsheetModel::rowCount(const QModelIndex &parent) const +{ + return stringList.count(); +} + +QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= stringList.size()) + return QVariant(); + + if (role == Qt::DisplayRole) + return stringList.at(index.row()); + else + return QVariant(); +} + +QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + return QStringLiteral("Column %1").arg(section); + else + return QStringLiteral("Row %1").arg(section); +} diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h new file mode 100644 index 0000000..6005224 --- /dev/null +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -0,0 +1,19 @@ +#pragma once +#include + +class GeometrySpreadsheetModel : public QAbstractListModel +{ + Q_OBJECT + +public: + GeometrySpreadsheetModel(const QStringList &strings, QObject *parent = nullptr) + : QAbstractListModel(parent), stringList(strings) {} + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + +private: + QStringList stringList; +}; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp index 4a31c26..81e5b59 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -1,5 +1,6 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h" #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" #include #include #include @@ -24,6 +25,9 @@ GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFl } )"); t->setFrameStyle(QFrame::NoFrame); + + auto model = new GeometrySpreadsheetModel({"hello", "world"}); + t->setModel(model); mainLayout_->addWidget(new GeometrySpreadsheetMenuBar()); From 898291e39eb2fe5262046f2ef836305d207fc6fb Mon Sep 17 00:00:00 2001 From: parker Date: Sat, 9 Aug 2025 23:16:21 +0100 Subject: [PATCH 07/14] feat: update model from geometry --- src/Engine/Network/NetworkManager.cpp | 2 +- src/Engine/Network/NetworkManager.h | 2 +- .../GeometrySpreadsheetModel.cpp | 36 +++++++++++++++++-- .../GeometrySpreadsheetModel.h | 12 +++++-- .../GeometrySpreadsheetPanel.cpp | 22 +++++++----- .../GeometrySpreadsheetPanel.h | 7 +++- src/Gui/Interface.cpp | 4 ++- src/Gui/ParametersPanel/ParametersPanel.cpp | 8 ++--- src/Gui/ParametersPanel/ParametersPanel.h | 3 +- 9 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/Engine/Network/NetworkManager.cpp b/src/Engine/Network/NetworkManager.cpp index 655d825..bd2da98 100644 --- a/src/Engine/Network/NetworkManager.cpp +++ b/src/Engine/Network/NetworkManager.cpp @@ -81,7 +81,7 @@ void enzo::nt::NetworkManager::setDisplayOp(OpId opId) enzo::nt::GeometryOperator& displayOp = getGeoOperator(opId); updateDisplay(displayOp.getOutputGeo(0)); - displayNodeChanged(); + displayNodeChanged(opId); } void enzo::nt::NetworkManager::cookOp(enzo::nt::OpId opId) diff --git a/src/Engine/Network/NetworkManager.h b/src/Engine/Network/NetworkManager.h index 52e52e4..a68619f 100644 --- a/src/Engine/Network/NetworkManager.h +++ b/src/Engine/Network/NetworkManager.h @@ -24,7 +24,7 @@ public: GeometryOperator& getGeoOperator(nt::OpId opId); void setDisplayOp(OpId opId); - boost::signals2::signal displayNodeChanged; + boost::signals2::signal displayNodeChanged; #ifdef UNIT_TEST void _reset(); diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index bf3fe2f..89877a0 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -1,22 +1,52 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" +#include "Engine/Network/NetworkManager.h" +#include "Engine/Operator/Geometry.h" +#include "Engine/Types.h" +#include + + +GeometrySpreadsheetModel::GeometrySpreadsheetModel(const QStringList &strings, QObject *parent) +: QAbstractListModel(parent), stringList(strings) +{ + +} + +void GeometrySpreadsheetModel::selectionChanged(enzo::nt::OpId opId) +{ + beginResetModel(); + enzo::nt::NetworkManager& nm = enzo::nt::nm(); + opId_ = opId; + IC(); + geometry_ = nm.getGeoOperator(opId).getOutputGeo(0); + endResetModel(); +} int GeometrySpreadsheetModel::rowCount(const QModelIndex &parent) const { - return stringList.count(); + return geometry_.getNumPoints(); } QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) + { return QVariant(); + } - if (index.row() >= stringList.size()) + if (index.row() >= geometry_.getNumPoints()) + { return QVariant(); + } if (role == Qt::DisplayRole) - return stringList.at(index.row()); + { + std::cout << geometry_.getPointPos(index.row()).x() << "\n"; + return geometry_.getPointPos(index.row()).x(); + } else + { return QVariant(); + } } QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orientation, diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index 6005224..953cbfa 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -1,19 +1,27 @@ #pragma once + #include +#include "Engine/Types.h" +#include "Engine/Operator/Geometry.h" class GeometrySpreadsheetModel : public QAbstractListModel { Q_OBJECT public: - GeometrySpreadsheetModel(const QStringList &strings, QObject *parent = nullptr) - : QAbstractListModel(parent), stringList(strings) {} + GeometrySpreadsheetModel(const QStringList &strings, QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + void selectionChanged(enzo::nt::OpId opId); + + private: QStringList stringList; + enzo::nt::OpId opId_; + enzo::geo::Geometry geometry_; + }; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp index 81e5b59..e169249 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -14,28 +14,34 @@ GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFl mainLayout_ = new QVBoxLayout(); - auto *t = new QTreeView(parent); - t->setRootIsDecorated(false); - t->setAlternatingRowColors(true); - t->setStyleSheet(R"( + view_ = new QTreeView(parent); + view_->setRootIsDecorated(false); + view_->setAlternatingRowColors(true); + view_->setStyleSheet(R"( QTreeView { background-color: #282828; alternate-background-color: #242424; paint-alternating-row-colors-for-empty-area: 1; } )"); - t->setFrameStyle(QFrame::NoFrame); + view_->setFrameStyle(QFrame::NoFrame); - auto model = new GeometrySpreadsheetModel({"hello", "world"}); - t->setModel(model); + model_ = new GeometrySpreadsheetModel({"hello", "world"}); + view_->setModel(model_); mainLayout_->addWidget(new GeometrySpreadsheetMenuBar()); - mainLayout_->addWidget(t); + mainLayout_->addWidget(view_); setLayout(mainLayout_); } +void GeometrySpreadsheetPanel::selectionChanged(enzo::nt::OpId opId) +{ + model_->selectionChanged(opId); + view_->update(); +} + void GeometrySpreadsheetPanel::resizeEvent(QResizeEvent *event) { QPainterPath path; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h index 6a9fc75..fd931db 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h @@ -2,6 +2,9 @@ #include #include +#include +#include "Engine/Types.h" +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" class GeometrySpreadsheetPanel : public QWidget @@ -9,10 +12,12 @@ class GeometrySpreadsheetPanel public: GeometrySpreadsheetPanel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); public Q_SLOTS: - void selectionChanged(); + void selectionChanged(enzo::nt::OpId opId); private: QVBoxLayout* mainLayout_; QWidget* bgWidget_; + GeometrySpreadsheetModel* model_; + QTreeView* view_; protected: void resizeEvent(QResizeEvent *event) override; diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index a298093..d56d863 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -9,6 +9,7 @@ #include #include #include +#include EnzoUI::EnzoUI() { @@ -61,6 +62,7 @@ EnzoUI::EnzoUI() // connect signals connect(&enzo::nt::nm(), &enzo::nt::NetworkManager::updateDisplay, viewport, &Viewport::geometryChanged); - enzo::nt::nm().displayNodeChanged.connect([parametersPanel](){parametersPanel->selectionChanged();}); + enzo::nt::nm().displayNodeChanged.connect([parametersPanel](enzo::nt::OpId opId){parametersPanel->selectionChanged(opId);}); + enzo::nt::nm().displayNodeChanged.connect([geometrySpreadsheetPanel](enzo::nt::OpId opId){geometrySpreadsheetPanel->selectionChanged(opId);}); // connect(&enzo::nt::nm(), &enzo::nt::NetworkManager::updateDisplay, parametersPanel, &ParametersPanel::selectionChanged); } diff --git a/src/Gui/ParametersPanel/ParametersPanel.cpp b/src/Gui/ParametersPanel/ParametersPanel.cpp index 83040d0..518a939 100644 --- a/src/Gui/ParametersPanel/ParametersPanel.cpp +++ b/src/Gui/ParametersPanel/ParametersPanel.cpp @@ -36,13 +36,11 @@ ParametersPanel::ParametersPanel(QWidget *parent, Qt::WindowFlags f) setLayout(mainLayout_); } -void ParametersPanel::selectionChanged() +void ParametersPanel::selectionChanged(enzo::nt::OpId opId) { using namespace enzo; enzo::nt::NetworkManager& nm = enzo::nt::nm(); - std::optional displayOpId = nm.getDisplayOp(); - - if(!displayOpId.has_value()) return; + const enzo::nt::OpId displayOpId = opId; // clear layout safely QLayoutItem *child; @@ -51,7 +49,7 @@ void ParametersPanel::selectionChanged() delete child; } - enzo::nt::GeometryOperator& displayOp = nm.getGeoOperator(displayOpId.value()); + enzo::nt::GeometryOperator& displayOp = nm.getGeoOperator(displayOpId); auto parameters = displayOp.getParameters(); std::vector parameterWidgets; diff --git a/src/Gui/ParametersPanel/ParametersPanel.h b/src/Gui/ParametersPanel/ParametersPanel.h index 5a99de1..8ed9755 100644 --- a/src/Gui/ParametersPanel/ParametersPanel.h +++ b/src/Gui/ParametersPanel/ParametersPanel.h @@ -2,6 +2,7 @@ #include #include +#include "Engine/Types.h" class ParametersPanel : public QWidget @@ -9,7 +10,7 @@ class ParametersPanel public: ParametersPanel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); public Q_SLOTS: - void selectionChanged(); + void selectionChanged(enzo::nt::OpId opId); private: QVBoxLayout* mainLayout_; QVBoxLayout* parametersLayout_; From add55e720f82af1c3fdf21f0ec982a545efe6c1b Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 02:01:28 +0100 Subject: [PATCH 08/14] feat(geometrySpreadsheet): read attributes from geometry --- src/Engine/Operator/Attribute.cpp | 14 ++++- src/Engine/Operator/Attribute.h | 4 +- src/Engine/Operator/AttributeHandle.h | 1 + src/Engine/Operator/Geometry.cpp | 52 ++++++++++++++- src/Engine/Operator/Geometry.h | 12 +++- .../GeometrySpreadsheetModel.cpp | 63 ++++++++++++++++++- .../GeometrySpreadsheetModel.h | 4 ++ 7 files changed, 145 insertions(+), 5 deletions(-) diff --git a/src/Engine/Operator/Attribute.cpp b/src/Engine/Operator/Attribute.cpp index 637aa72..bfbd264 100644 --- a/src/Engine/Operator/Attribute.cpp +++ b/src/Engine/Operator/Attribute.cpp @@ -15,15 +15,19 @@ ga::Attribute::Attribute(std::string name, ga::AttributeType type) { case(AttrType::intT): intStore_=std::make_shared>(); + typeSize_=1; break; case(AttrType::floatT): floatStore_=std::make_shared>(); + typeSize_=1; break; case(AttrType::vectorT): vector3Store_=std::make_shared>(); + typeSize_=3; break; case(AttrType::boolT): boolStore_=std::make_shared>(); + typeSize_=1; break; default: throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in Attribute constructor"); @@ -32,6 +36,13 @@ ga::Attribute::Attribute(std::string name, ga::AttributeType type) } +unsigned int ga::Attribute::Attribute::getTypeSize() const +{ + return typeSize_; +} + + + ga::Attribute::Attribute(const Attribute& other) { type_ = other.type_; @@ -39,6 +50,7 @@ ga::Attribute::Attribute(const Attribute& other) hidden_ = other.hidden_; readOnly_ = other.readOnly_; name_ = other.name_; + typeSize_ = other.typeSize_; switch(type_) { @@ -66,7 +78,7 @@ ga::AttributeType ga::Attribute::getType() return type_; } -std::string ga::Attribute::getName() +std::string ga::Attribute::getName() const { return name_; } diff --git a/src/Engine/Operator/Attribute.h b/src/Engine/Operator/Attribute.h index 8f4c6ad..4a7bdb2 100644 --- a/src/Engine/Operator/Attribute.h +++ b/src/Engine/Operator/Attribute.h @@ -22,7 +22,8 @@ namespace enzo{ Attribute(std::string name, ga::AttributeType type); Attribute(const Attribute& other); AttributeType getType(); - std::string getName(); + std::string getName() const; + unsigned int getTypeSize() const; @@ -40,6 +41,7 @@ namespace enzo{ bool readOnly_=false; ga::AttributeType type_; + unsigned int typeSize_=1; std::string name_; diff --git a/src/Engine/Operator/AttributeHandle.h b/src/Engine/Operator/AttributeHandle.h index 0178409..5f0909a 100644 --- a/src/Engine/Operator/AttributeHandle.h +++ b/src/Engine/Operator/AttributeHandle.h @@ -59,6 +59,7 @@ public: data_->push_back(value); } + void reserve(std::size_t newCap) { data_->reserve(newCap); diff --git a/src/Engine/Operator/Geometry.cpp b/src/Engine/Operator/Geometry.cpp index a3e1cdc..a66204c 100644 --- a/src/Engine/Operator/Geometry.cpp +++ b/src/Engine/Operator/Geometry.cpp @@ -63,6 +63,36 @@ ga::Offset geo::Geometry::getNumSoloPoints() const } +// enzo::geo::attributeIterator geo::Geometry::attributesBegin(const ga::AttributeOwner owner) +// { +// return getAttributeStore(owner).begin(); + +// } + +// enzo::geo::attributeIterator geo::Geometry::attributesEnd(const ga::AttributeOwner owner) +// { +// return getAttributeStore(owner).end(); +// } + +const size_t geo::Geometry::getNumAttributes(const ga::AttributeOwner owner) const +{ + return getAttributeStore(owner).size(); +} + +std::weak_ptr geo::Geometry::getAttributeByIndex(ga::AttributeOwner owner, unsigned int index) const +{ + auto attribStore = getAttributeStore(owner); + if(index>=attribStore.size()) + { + throw std::out_of_range("Attribute index out of range: " + std::to_string(index) + " max size: " + std::to_string(attribStore.size()) + "\n"); + } + return getAttributeStore(owner)[index]; + +} + + + + std::set::const_iterator geo::Geometry::soloPointsBegin() { @@ -265,7 +295,7 @@ ga::AttributeHandle geo::Geometry::addVector3Attribute(ga::Attribut return ga::AttributeHandle(newAttribute); } -std::vector>& geo::Geometry::getAttributeStore(ga::AttributeOwner& owner) +geo::Geometry::attribVector& geo::Geometry::getAttributeStore(const ga::AttributeOwner& owner) { switch(owner) { @@ -286,6 +316,26 @@ std::vector>& geo::Geometry::getAttributeStore(ga } } +const geo::Geometry::attribVector& geo::Geometry::getAttributeStore(const ga::AttributeOwner& owner) const +{ + switch(owner) + { + case ga::AttributeOwner::POINT: + return pointAttributes_; + break; + case ga::AttributeOwner::VERTEX: + return vertexAttributes_; + break; + case ga::AttributeOwner::PRIMITIVE: + return primitiveAttributes_; + break; + case ga::AttributeOwner::GLOBAL: + return globalAttributes_; + break; + default: + throw std::runtime_error("Unexpected, owner could not be found"); + } +} std::shared_ptr geo::Geometry::getAttribByName(ga::AttributeOwner owner, std::string name) { diff --git a/src/Engine/Operator/Geometry.h b/src/Engine/Operator/Geometry.h index 5d9516a..8e9f0e5 100644 --- a/src/Engine/Operator/Geometry.h +++ b/src/Engine/Operator/Geometry.h @@ -4,6 +4,7 @@ #include #include #include "Engine/Operator/AttributeHandle.h" +#include #include @@ -19,6 +20,8 @@ using faceDescriptor = HeMesh::Face_index; using V_index = HeMesh::Vertex_index; using F_index = HeMesh::Face_index; +using attributeIterator = std::vector>::iterator; + class Geometry { public: @@ -29,6 +32,12 @@ public: ga::AttributeHandle addVector3Attribute(ga::AttributeOwner owner, std::string name); // TODO: return weak ptr std::shared_ptr getAttribByName(ga::AttributeOwner owner, std::string name); + + const size_t getNumAttributes(const ga::AttributeOwner owner) const; + std::weak_ptr getAttributeByIndex(ga::AttributeOwner owner, unsigned int index) const; + // attributeIterator attributesBegin(const ga::AttributeOwner owner); + // attributeIterator attributesEnd(const ga::AttributeOwner owner); + std::vector derivePointNormals(); HeMesh computeHalfEdgeMesh(); void addFace(std::vector pointOffsets, bool closed=true); @@ -53,7 +62,8 @@ public: void computePrimStartVertices(); private: using attribVector = std::vector>; - attribVector& getAttributeStore(ga::AttributeOwner& owner); + geo::Geometry::attribVector& getAttributeStore(const ga::AttributeOwner& owner); + const geo::Geometry::attribVector& getAttributeStore(const ga::AttributeOwner& owner) const; attribVector deepCopyAttributes(attribVector source); diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index 89877a0..cb5c395 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -1,8 +1,11 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" #include "Engine/Network/NetworkManager.h" +#include "Engine/Operator/Attribute.h" #include "Engine/Operator/Geometry.h" #include "Engine/Types.h" #include +#include +#include GeometrySpreadsheetModel::GeometrySpreadsheetModel(const QStringList &strings, QObject *parent) @@ -18,6 +21,29 @@ void GeometrySpreadsheetModel::selectionChanged(enzo::nt::OpId opId) opId_ = opId; IC(); geometry_ = nm.getGeoOperator(opId).getOutputGeo(0); + + // get sizes + const auto attribCount = geometry_.getNumAttributes(enzo::ga::AttributeOwner::POINT); + + attribSizes_.clear(); + attribSizes_.reserve(attribCount); + + for(size_t i=0; igetTypeSize(); + attribSizes_.push_back(size); + + for(size_t j=0; j=sectionAttribMap_.size()) + { + throw std::out_of_range("Section is out of range of sectionAttributMap_"); + } + IC(sectionAttribMap_); + return sectionAttribMap_[section]; +} + + QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -56,7 +105,19 @@ QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orien return QVariant(); if (orientation == Qt::Horizontal) - return QStringLiteral("Column %1").arg(section); + { + if(auto attrib = geometry_.getAttributeByIndex(enzo::ga::AttributeOwner::POINT, indexFromSection(section)).lock()) + { + return QString::fromStdString(attrib->getName()); + } + else + { + throw std::runtime_error("failed to lock attriubte index"); + } + + } else + { return QStringLiteral("Row %1").arg(section); + } } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index 953cbfa..a4385df 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -12,9 +12,11 @@ public: GeometrySpreadsheetModel(const QStringList &strings, QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int indexFromSection(unsigned int section) const; void selectionChanged(enzo::nt::OpId opId); @@ -23,5 +25,7 @@ private: QStringList stringList; enzo::nt::OpId opId_; enzo::geo::Geometry geometry_; + std::vector attribSizes_; + std::vector sectionAttribMap_; }; From 13da4a79f41b8d78fad62aa011452f052011c0a8 Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 11:31:01 +0100 Subject: [PATCH 09/14] fix(geometrySpreadsheet): geometry updates with displayGeoChanged signal --- src/Engine/Network/NetworkManager.cpp | 4 ++-- src/Engine/Network/NetworkManager.h | 4 +--- .../GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp | 7 +++---- .../GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h | 2 +- .../GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp | 4 ++-- .../GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h | 2 +- src/Gui/Interface.cpp | 6 +++--- src/Gui/Viewport/Viewport.cpp | 2 +- src/Gui/Viewport/Viewport.h | 3 +-- 9 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/Engine/Network/NetworkManager.cpp b/src/Engine/Network/NetworkManager.cpp index bd2da98..9bd3824 100644 --- a/src/Engine/Network/NetworkManager.cpp +++ b/src/Engine/Network/NetworkManager.cpp @@ -35,7 +35,7 @@ enzo::nt::OpId enzo::nt::NetworkManager::addOperator(op::OpInfo opInfo) if(getDisplayOp().has_value() && getDisplayOp().value()==dependentId) { cookOp(dependentId); - updateDisplay(dependentOp.getOutputGeo(0)); + displayGeoChanged(dependentOp.getOutputGeo(0)); } } } @@ -80,7 +80,7 @@ void enzo::nt::NetworkManager::setDisplayOp(OpId opId) cookOp(opId); enzo::nt::GeometryOperator& displayOp = getGeoOperator(opId); - updateDisplay(displayOp.getOutputGeo(0)); + displayGeoChanged(displayOp.getOutputGeo(0)); displayNodeChanged(opId); } diff --git a/src/Engine/Network/NetworkManager.h b/src/Engine/Network/NetworkManager.h index a68619f..f90b935 100644 --- a/src/Engine/Network/NetworkManager.h +++ b/src/Engine/Network/NetworkManager.h @@ -25,6 +25,7 @@ public: void setDisplayOp(OpId opId); boost::signals2::signal displayNodeChanged; + boost::signals2::signal displayGeoChanged; #ifdef UNIT_TEST void _reset(); @@ -47,9 +48,6 @@ private: std::optional displayOp_=std::nullopt; -Q_SIGNALS: - void updateDisplay(enzo::geo::Geometry& geometry); - }; inline enzo::nt::NetworkManager& nm() { diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index cb5c395..fff71d8 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -14,13 +14,12 @@ GeometrySpreadsheetModel::GeometrySpreadsheetModel(const QStringList &strings, Q } -void GeometrySpreadsheetModel::selectionChanged(enzo::nt::OpId opId) +void GeometrySpreadsheetModel::geometryChanged(enzo::geo::Geometry& geometry) { beginResetModel(); - enzo::nt::NetworkManager& nm = enzo::nt::nm(); - opId_ = opId; + // enzo::nt::NetworkManager& nm = enzo::nt::nm(); IC(); - geometry_ = nm.getGeoOperator(opId).getOutputGeo(0); + geometry_ = geometry; // get sizes const auto attribCount = geometry_.getNumAttributes(enzo::ga::AttributeOwner::POINT); diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index a4385df..65f2e98 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -18,7 +18,7 @@ public: int role = Qt::DisplayRole) const override; int indexFromSection(unsigned int section) const; - void selectionChanged(enzo::nt::OpId opId); + void geometryChanged(enzo::geo::Geometry& geometry); private: diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp index e169249..1226b42 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -36,9 +36,9 @@ GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFl setLayout(mainLayout_); } -void GeometrySpreadsheetPanel::selectionChanged(enzo::nt::OpId opId) +void GeometrySpreadsheetPanel::geometryChanged(enzo::geo::Geometry& geometry) { - model_->selectionChanged(opId); + model_->geometryChanged(geometry); view_->update(); } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h index fd931db..18714ca 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h @@ -12,7 +12,7 @@ class GeometrySpreadsheetPanel public: GeometrySpreadsheetPanel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); public Q_SLOTS: - void selectionChanged(enzo::nt::OpId opId); + void geometryChanged(enzo::geo::Geometry& geometry); private: QVBoxLayout* mainLayout_; QWidget* bgWidget_; diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index d56d863..c3873fa 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -1,5 +1,6 @@ #include "Gui/Interface.h" #include "Engine/Network/NetworkManager.h" +#include "Engine/Operator/Geometry.h" #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h" #include "Gui/ParametersPanel/ParametersPanel.h" #include "Gui/Viewport/Viewport.h" @@ -61,8 +62,7 @@ EnzoUI::EnzoUI() mainLayout_->addWidget(viewportSplitter_); // connect signals - connect(&enzo::nt::nm(), &enzo::nt::NetworkManager::updateDisplay, viewport, &Viewport::geometryChanged); enzo::nt::nm().displayNodeChanged.connect([parametersPanel](enzo::nt::OpId opId){parametersPanel->selectionChanged(opId);}); - enzo::nt::nm().displayNodeChanged.connect([geometrySpreadsheetPanel](enzo::nt::OpId opId){geometrySpreadsheetPanel->selectionChanged(opId);}); - // connect(&enzo::nt::nm(), &enzo::nt::NetworkManager::updateDisplay, parametersPanel, &ParametersPanel::selectionChanged); + enzo::nt::nm().displayGeoChanged.connect([geometrySpreadsheetPanel](enzo::geo::Geometry& geometry){geometrySpreadsheetPanel->geometryChanged(geometry);}); + enzo::nt::nm().displayGeoChanged.connect([viewport](enzo::geo::Geometry& geometry){viewport->setGeometry(geometry);}); } diff --git a/src/Gui/Viewport/Viewport.cpp b/src/Gui/Viewport/Viewport.cpp index 746f374..b2aa903 100644 --- a/src/Gui/Viewport/Viewport.cpp +++ b/src/Gui/Viewport/Viewport.cpp @@ -20,7 +20,7 @@ Viewport::Viewport(QWidget *parent, Qt::WindowFlags f) this->setLayout(mainLayout_); } -void Viewport::geometryChanged(enzo::geo::Geometry& geometry) +void Viewport::setGeometry(enzo::geo::Geometry& geometry) { openGLWidget_->geometryChanged(geometry); } diff --git a/src/Gui/Viewport/Viewport.h b/src/Gui/Viewport/Viewport.h index fe86376..88868c1 100644 --- a/src/Gui/Viewport/Viewport.h +++ b/src/Gui/Viewport/Viewport.h @@ -8,6 +8,7 @@ class Viewport { public: Viewport(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + void setGeometry(enzo::geo::Geometry& geometry); private: QVBoxLayout* mainLayout_; ViewportGLWidget* openGLWidget_; @@ -23,6 +24,4 @@ private: QPointF leftStartPos_; bool rightMouseDown_=false; QPointF rightStartPos_; -public Q_SLOTS: - void geometryChanged(enzo::geo::Geometry& geometry); }; From 750dfea9a0ed5961deade4207437910a7429e553 Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 14:46:41 +0100 Subject: [PATCH 10/14] feat(geometrySpreadsheet): read all attributes of different types from geometry --- src/Engine/Operator/Attribute.cpp | 2 +- src/Engine/Operator/Attribute.h | 4 +- src/Engine/Operator/AttributeHandle.h | 92 ++++++++++++++++++- .../GeometrySpreadsheetModel.cpp | 85 ++++++++++++++--- .../GeometrySpreadsheetModel.h | 1 + src/Gui/Interface.cpp | 2 +- 6 files changed, 170 insertions(+), 16 deletions(-) diff --git a/src/Engine/Operator/Attribute.cpp b/src/Engine/Operator/Attribute.cpp index bfbd264..9849f19 100644 --- a/src/Engine/Operator/Attribute.cpp +++ b/src/Engine/Operator/Attribute.cpp @@ -73,7 +73,7 @@ ga::Attribute::Attribute(const Attribute& other) } -ga::AttributeType ga::Attribute::getType() +ga::AttributeType ga::Attribute::getType() const { return type_; } diff --git a/src/Engine/Operator/Attribute.h b/src/Engine/Operator/Attribute.h index 4a7bdb2..23eb096 100644 --- a/src/Engine/Operator/Attribute.h +++ b/src/Engine/Operator/Attribute.h @@ -21,7 +21,7 @@ namespace enzo{ public: Attribute(std::string name, ga::AttributeType type); Attribute(const Attribute& other); - AttributeType getType(); + AttributeType getType() const; std::string getName() const; unsigned int getTypeSize() const; @@ -29,6 +29,8 @@ namespace enzo{ template friend class AttributeHandle; + template + friend class AttributeHandleRO; private: // private attributes are attributes that are hidden from the user diff --git a/src/Engine/Operator/AttributeHandle.h b/src/Engine/Operator/AttributeHandle.h index 5f0909a..6f67901 100644 --- a/src/Engine/Operator/AttributeHandle.h +++ b/src/Engine/Operator/AttributeHandle.h @@ -51,8 +51,8 @@ public: { throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in AttributeHandle constructor"); } - } + void addValue(T value) { // TODO:make this private (primitive friend classes only) @@ -119,4 +119,94 @@ using AttributeHandleFloat = AttributeHandle; using AttributeHandleVector3 = AttributeHandle; using AttributeHandleBool = AttributeHandle; +template +class AttributeHandleRO +{ +public: + ga::AttributeType type_; + + AttributeHandleRO(std::shared_ptr attribute) + { + type_ = attribute->getType(); + // get attribute data pointer + // TODO: check types match + // TODO: add the other types + + // int + if constexpr (std::is_same::value) + { + data_=attribute->intStore_; + } + + // float + else if constexpr (std::is_same::value) + { + data_=attribute->floatStore_; + } + + // vector 3 + else if constexpr (std::is_same::value) + { + data_=attribute->vector3Store_; + } + else if constexpr (std::is_same::value) + { + data_=attribute->boolStore_; + } + else + { + throw std::runtime_error("Type " + std::to_string(static_cast(type_)) + " was not properly accounted for in AttributeHandle constructor"); + } + + } + + // TODO: replace with iterator + std::vector getAllValues() const + { + return {data_->begin(), data_->end()}; + } + + size_t getSize() const + { + return data_->size(); + } + + T getValue(size_t pos) const + { + // TODO:protect against invalid positions + // TODO: cast types + return (*data_)[pos]; + } + + std::string getName() const + { + return name_; + } + + + +private: + // private attributes are attributes that are hidden from the user + // for internal use + bool private_=false; + // hidden attributes are user accessible attributes that the user may + // or may want to use + bool hidden_=false; + // allows the user to read the attributeHandle but not modify it + bool readOnly_=false; + + std::string name_=""; + + std::shared_ptr> data_; + + // int typeID_; + +}; + +using AttributeHandleInt = AttributeHandle; +using AttributeHandleFloat = AttributeHandle; +using AttributeHandleVector3 = AttributeHandle; +using AttributeHandleBool = AttributeHandle; + + } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index fff71d8..80a5280 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -1,6 +1,7 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" #include "Engine/Network/NetworkManager.h" #include "Engine/Operator/Attribute.h" +#include "Engine/Operator/AttributeHandle.h" #include "Engine/Operator/Geometry.h" #include "Engine/Types.h" #include @@ -17,19 +18,17 @@ GeometrySpreadsheetModel::GeometrySpreadsheetModel(const QStringList &strings, Q void GeometrySpreadsheetModel::geometryChanged(enzo::geo::Geometry& geometry) { beginResetModel(); - // enzo::nt::NetworkManager& nm = enzo::nt::nm(); - IC(); geometry_ = geometry; // get sizes - const auto attribCount = geometry_.getNumAttributes(enzo::ga::AttributeOwner::POINT); + const auto attribCount = geometry_.getNumAttributes(attributeOwner_); attribSizes_.clear(); attribSizes_.reserve(attribCount); for(size_t i=0; igetTypeSize(); attribSizes_.push_back(size); @@ -48,7 +47,27 @@ void GeometrySpreadsheetModel::geometryChanged(enzo::geo::Geometry& geometry) int GeometrySpreadsheetModel::rowCount(const QModelIndex &parent) const { - return geometry_.getNumPoints(); + switch(attributeOwner_) + { + case enzo::ga::AttributeOwner::POINT: + { + return geometry_.getNumPoints(); + } + case enzo::ga::AttributeOwner::VERTEX: + { + return geometry_.getNumVerts(); + } + case enzo::ga::AttributeOwner::PRIMITIVE: + { + return geometry_.getNumPrims(); + } + case enzo::ga::AttributeOwner::GLOBAL: + { + return 1; + } + + } + return 1; } int GeometrySpreadsheetModel::columnCount(const QModelIndex &parent) const @@ -70,15 +89,57 @@ QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) cons return QVariant(); } - if (index.row() >= geometry_.getNumPoints()) - { - return QVariant(); - } + // TODO: reimplement check + // if (index.row() >= geometry_.getNumPoints()) + // { + // return QVariant(); + // } if (role == Qt::DisplayRole) { - std::cout << geometry_.getPointPos(index.row()).x() << "\n"; - return geometry_.getPointPos(index.row()).x(); + + // std::cout << geometry_.getPointPos(index.row()).x() << "\n"; + int attributeIndex = indexFromSection(index.column()); + if(std::shared_ptr attrib = geometry_.getAttributeByIndex(attributeOwner_, attributeIndex).lock()) + { + const unsigned int valueIndex = index.column()-attributeIndex; + using namespace enzo::ga; + + switch(attrib->getType()) + { + case(AttributeType::intT): + { + const auto attribHandle = enzo::ga::AttributeHandleRO(attrib); + return static_cast(attribHandle.getValue(index.row())); + } + case(AttributeType::floatT): + { + const auto attribHandle = enzo::ga::AttributeHandleRO(attrib); + return attribHandle.getValue(index.row()); + } + case(AttributeType::boolT): + { + const auto attribHandle = enzo::ga::AttributeHandleRO(attrib); + return attribHandle.getValue(index.row()) ? "true" : "false"; + } + case(AttributeType::vectorT): + { + const auto attribHandle = enzo::ga::AttributeHandleRO(attrib); + return attribHandle.getValue(index.row())[valueIndex]; + } + default: + { + return "Failed"; + break; + } + + } + } + else + { + throw std::runtime_error("Couldn't lock attribute"); + } + // return geometry_.getPointPos(index.row()).x(); } else { @@ -105,7 +166,7 @@ QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orien if (orientation == Qt::Horizontal) { - if(auto attrib = geometry_.getAttributeByIndex(enzo::ga::AttributeOwner::POINT, indexFromSection(section)).lock()) + if(auto attrib = geometry_.getAttributeByIndex(attributeOwner_, indexFromSection(section)).lock()) { return QString::fromStdString(attrib->getName()); } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index 65f2e98..e067017 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -27,5 +27,6 @@ private: enzo::geo::Geometry geometry_; std::vector attribSizes_; std::vector sectionAttribMap_; + enzo::ga::AttributeOwner attributeOwner_=enzo::ga::AttributeOwner::PRIMITIVE; }; diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index c3873fa..e640d18 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -53,7 +53,7 @@ EnzoUI::EnzoUI() viewportSplitter_->addWidget(spreadsheetSplitter_); viewportSplitter_->addWidget(networkSplitter_); - viewportSplitter_->setSizes({100,100}); + viewportSplitter_->setSizes({100,300}); networkSplitter_->addWidget(parametersPanel); networkSplitter_->addWidget(network); From b245e5333eb5ba74860e5e575b483356011b6fd5 Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 19:13:08 +0100 Subject: [PATCH 11/14] feat(geometrySpreadsheet): connect attribute buttons --- src/Engine/Operator/GeometryOperator.cpp | 6 +++ src/Engine/Operator/GeometryOperator.h | 1 + .../GeometrySpreadsheetMenuBar.cpp | 27 ++++++++--- .../GeometrySpreadsheetMenuBar.h | 30 ++++++++---- .../GeometrySpreadsheetModel.cpp | 46 +++++++++++++++++-- .../GeometrySpreadsheetModel.h | 7 +-- .../GeometrySpreadsheetPanel.cpp | 21 ++++++++- .../GeometrySpreadsheetPanel.h | 3 ++ src/Gui/Interface.cpp | 1 + 9 files changed, 116 insertions(+), 26 deletions(-) diff --git a/src/Engine/Operator/GeometryOperator.cpp b/src/Engine/Operator/GeometryOperator.cpp index cbfd0d7..b2ad040 100644 --- a/src/Engine/Operator/GeometryOperator.cpp +++ b/src/Engine/Operator/GeometryOperator.cpp @@ -124,6 +124,12 @@ std::vector> nt::GeometryOperator::getParameters() return {parameters_.begin(), parameters_.end()}; } +std::string nt::GeometryOperator::getLabel() +{ + return getTypeName(); +} + + std::vector> nt::GeometryOperator::getOutputConnections() const { return {outputConnections_.begin(), outputConnections_.end()}; diff --git a/src/Engine/Operator/GeometryOperator.h b/src/Engine/Operator/GeometryOperator.h index ea4c364..9dddca0 100644 --- a/src/Engine/Operator/GeometryOperator.h +++ b/src/Engine/Operator/GeometryOperator.h @@ -30,6 +30,7 @@ public: std::vector> getParameters(); std::weak_ptr getParameter(std::string parameterName); + std::string getLabel(); // TODO: implement node labels std::string getTypeName(); void dirtyNode(bool dirtyDescendents=true); diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp index 966d202..fa3dd8d 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -1,4 +1,6 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" +#include "Engine/Network/NetworkManager.h" +#include "Engine/Operator/GeometryOperator.h" #include #include #include @@ -99,18 +101,19 @@ GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt:: modeButtonGroup_.setExclusive(true); - auto newButton = [this, &buttonBgLayout]() + auto newButton = [this, &buttonBgLayout](const char* tooltip="") { auto newButton = new GeoSheetModeButton(); + newButton->setToolTip(tooltip); modeButtonGroup_.addButton(newButton); buttonBgLayout->addWidget(newButton); return newButton; }; - auto pointButton = newButton(); - auto vertButton = newButton(); - auto primButton = newButton(); - auto globalButton = newButton(); + pointButton = newButton("Point Attributes"); + vertexButton = newButton("Vertex Attributes"); + primitiveButton = newButton("Primitive Attributes"); + globalButton = newButton("Global Attributes"); pointButton->setChecked(true); @@ -121,12 +124,22 @@ GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt:: setLayout(mainLayout_); } + + GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) { mainLayout_ = new QHBoxLayout(); - mainLayout_->addWidget(new QLabel("Node: testGeometryRat")); - mainLayout_->addWidget(new GeoSheetMenuBarModeSelection()); + nodeLabel_ = new QLabel(); + mainLayout_->addWidget(nodeLabel_); + modeSelection = new GeoSheetMenuBarModeSelection(); + mainLayout_->addWidget(modeSelection); setLayout(mainLayout_); } + +void GeometrySpreadsheetMenuBar::setNode(enzo::nt::OpId opId) +{ + enzo::nt::GeometryOperator& geoOp = enzo::nt::nm().getGeoOperator(opId); + nodeLabel_->setText("Node: " + QString::fromStdString(geoOp.getLabel())); +} diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h index 4b4e433..094e756 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h @@ -1,9 +1,12 @@ #pragma once +#include "Engine/Operator/OpInfo.h" +#include "Engine/Types.h" #include #include #include #include +#include class GeoSheetModeButton : public QPushButton @@ -19,21 +22,30 @@ protected: bool hovered_ = false; }; -class GeometrySpreadsheetMenuBar -: public QWidget -{ -public: - GeometrySpreadsheetMenuBar(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); -private: - QHBoxLayout* mainLayout_; -}; - class GeoSheetMenuBarModeSelection : public QWidget { public: GeoSheetMenuBarModeSelection(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + + GeoSheetModeButton* pointButton; + GeoSheetModeButton* vertexButton; + GeoSheetModeButton* primitiveButton; + GeoSheetModeButton* globalButton; private: QHBoxLayout* mainLayout_; QButtonGroup modeButtonGroup_; }; + +class GeometrySpreadsheetMenuBar +: public QWidget +{ +public: + GeometrySpreadsheetMenuBar(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + GeoSheetMenuBarModeSelection* modeSelection; + void setNode(enzo::nt::OpId opId); +private: + QHBoxLayout* mainLayout_; + QLabel* nodeLabel_; +}; + diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index 80a5280..81654fa 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -1,5 +1,4 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" -#include "Engine/Network/NetworkManager.h" #include "Engine/Operator/Attribute.h" #include "Engine/Operator/AttributeHandle.h" #include "Engine/Operator/Geometry.h" @@ -7,10 +6,11 @@ #include #include #include +#include -GeometrySpreadsheetModel::GeometrySpreadsheetModel(const QStringList &strings, QObject *parent) -: QAbstractListModel(parent), stringList(strings) +GeometrySpreadsheetModel::GeometrySpreadsheetModel(QObject *parent) +: QAbstractListModel(parent) { } @@ -19,11 +19,18 @@ void GeometrySpreadsheetModel::geometryChanged(enzo::geo::Geometry& geometry) { beginResetModel(); geometry_ = geometry; + initBuffers(); + endResetModel(); +} + +void GeometrySpreadsheetModel::initBuffers() +{ // get sizes const auto attribCount = geometry_.getNumAttributes(attributeOwner_); attribSizes_.clear(); + sectionAttribMap_.clear(); attribSizes_.reserve(attribCount); for(size_t i=0; igetName()); + if(attribSizes_[attributeIndex]>1) + { + const unsigned int valueIndex = section-attributeIndex; + + std::string valueIndexString; + if(attrib->getType()==enzo::ga::AttrType::vectorT) + { + valueIndexString = std::array{".x", ".y", ".z", ".w"}.at(valueIndex); + } + else + { + valueIndexString = "["+std::to_string(valueIndex)+"]"; + } + + return QString::fromStdString(attrib->getName() + valueIndexString); + } + else + { + return QString::fromStdString(attrib->getName()); + } } else { diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index e067017..debff55 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -9,7 +9,7 @@ class GeometrySpreadsheetModel : public QAbstractListModel Q_OBJECT public: - GeometrySpreadsheetModel(const QStringList &strings, QObject *parent = nullptr); + GeometrySpreadsheetModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -19,14 +19,15 @@ public: int indexFromSection(unsigned int section) const; void geometryChanged(enzo::geo::Geometry& geometry); + void setOwner(const enzo::ga::AttributeOwner owner); + void initBuffers(); private: - QStringList stringList; enzo::nt::OpId opId_; enzo::geo::Geometry geometry_; std::vector attribSizes_; std::vector sectionAttribMap_; - enzo::ga::AttributeOwner attributeOwner_=enzo::ga::AttributeOwner::PRIMITIVE; + enzo::ga::AttributeOwner attributeOwner_=enzo::ga::AttributeOwner::POINT; }; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp index 1226b42..9aea7f7 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -1,10 +1,12 @@ #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h" #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" +#include "Engine/Network/NetworkManager.h" #include #include #include #include +#include #include #include @@ -26,16 +28,31 @@ GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFl )"); view_->setFrameStyle(QFrame::NoFrame); - model_ = new GeometrySpreadsheetModel({"hello", "world"}); + model_ = new GeometrySpreadsheetModel(); view_->setModel(model_); + menuBar_ = new GeometrySpreadsheetMenuBar(); + // connect buttons + connect(menuBar_->modeSelection->pointButton, &QPushButton::clicked, this, [this](){model_->setOwner(enzo::ga::AttributeOwner::POINT);}); + connect(menuBar_->modeSelection->vertexButton, &QPushButton::clicked, this, [this](){model_->setOwner(enzo::ga::AttributeOwner::VERTEX);}); + connect(menuBar_->modeSelection->primitiveButton, &QPushButton::clicked, this, [this](){model_->setOwner(enzo::ga::AttributeOwner::PRIMITIVE);}); + connect(menuBar_->modeSelection->globalButton, &QPushButton::clicked, this, [this](){model_->setOwner(enzo::ga::AttributeOwner::GLOBAL);}); + // set default + menuBar_->modeSelection->pointButton->click(); - mainLayout_->addWidget(new GeometrySpreadsheetMenuBar()); + + mainLayout_->addWidget(menuBar_); mainLayout_->addWidget(view_); setLayout(mainLayout_); } +void GeometrySpreadsheetPanel::setNode(enzo::nt::OpId opId) +{ + menuBar_->setNode(opId); +} + + void GeometrySpreadsheetPanel::geometryChanged(enzo::geo::Geometry& geometry) { model_->geometryChanged(geometry); diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h index 18714ca..f89285d 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.h @@ -5,6 +5,7 @@ #include #include "Engine/Types.h" #include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h" +#include "Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.h" class GeometrySpreadsheetPanel : public QWidget @@ -13,11 +14,13 @@ public: GeometrySpreadsheetPanel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); public Q_SLOTS: void geometryChanged(enzo::geo::Geometry& geometry); + void setNode(enzo::nt::OpId opId); private: QVBoxLayout* mainLayout_; QWidget* bgWidget_; GeometrySpreadsheetModel* model_; QTreeView* view_; + GeometrySpreadsheetMenuBar* menuBar_; protected: void resizeEvent(QResizeEvent *event) override; diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index e640d18..cdc8c6f 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -63,6 +63,7 @@ EnzoUI::EnzoUI() // connect signals enzo::nt::nm().displayNodeChanged.connect([parametersPanel](enzo::nt::OpId opId){parametersPanel->selectionChanged(opId);}); + enzo::nt::nm().displayNodeChanged.connect([geometrySpreadsheetPanel](enzo::nt::OpId opId){geometrySpreadsheetPanel->setNode(opId);}); enzo::nt::nm().displayGeoChanged.connect([geometrySpreadsheetPanel](enzo::geo::Geometry& geometry){geometrySpreadsheetPanel->geometryChanged(geometry);}); enzo::nt::nm().displayGeoChanged.connect([viewport](enzo::geo::Geometry& geometry){viewport->setGeometry(geometry);}); } From 500f860d5c0c3a56370cea23edf1342ceca2e1dc Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 23:30:12 +0100 Subject: [PATCH 12/14] feat(geometrySpreadsheet): add index column --- src/Engine/Operator/Geometry.cpp | 50 ++++++++++++++++++- src/Engine/Operator/Geometry.h | 28 +++++++---- .../GeometrySpreadsheetMenuBar.cpp | 4 ++ .../GeometrySpreadsheetModel.cpp | 39 ++++++++++++--- .../GeometrySpreadsheetModel.h | 2 + 5 files changed, 103 insertions(+), 20 deletions(-) diff --git a/src/Engine/Operator/Geometry.cpp b/src/Engine/Operator/Geometry.cpp index a66204c..a75b0cf 100644 --- a/src/Engine/Operator/Geometry.cpp +++ b/src/Engine/Operator/Geometry.cpp @@ -3,6 +3,7 @@ #include "Engine/Operator/AttributeHandle.h" #include "Engine/Types.h" #include +#include #include #include #include @@ -33,16 +34,45 @@ geo::Geometry::Geometry(const Geometry& other): posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))}, // other - soloPoints_{other.soloPoints_} + soloPoints_{other.soloPoints_}, + vertexPrims_{other.vertexPrims_}, + primStarts_{other.primStarts_}, + primStartsDirty_{other.primStartsDirty_.load()} { +} +enzo::geo::Geometry& enzo::geo::Geometry::operator=(const enzo::geo::Geometry& rhs) { + if (this == &rhs) return *this; + + // attributes + pointAttributes_ = deepCopyAttributes(rhs.pointAttributes_); + vertexAttributes_ = deepCopyAttributes(rhs.vertexAttributes_); + primitiveAttributes_ = deepCopyAttributes(rhs.primitiveAttributes_); + globalAttributes_ = deepCopyAttributes(rhs.globalAttributes_); + + // handles + vertexCountHandlePrim_ = enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount")); + closedHandlePrim_ = enzo::ga::AttributeHandleBool(getAttribByName(ga::AttrOwner::PRIMITIVE, "closed")); + pointOffsetHandleVert_ = enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point")); + posHandlePoint_ = enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P")); + + // other + soloPoints_ = rhs.soloPoints_; + vertexPrims_ = rhs.vertexPrims_; + primStarts_ = rhs.primStarts_; + + primStartsDirty_.store(rhs.primStartsDirty_.load()); + + return *this; } void geo::Geometry::addFace(std::vector pointOffsets, bool closed) { + const ga::Offset primNum = vertexCountHandlePrim_.getSize(); for(ga::Offset pointOffset : pointOffsets) { pointOffsetHandleVert_.addValue(pointOffset); + vertexPrims_.push_back(primNum); soloPoints_.erase(pointOffset); } vertexCountHandlePrim_.addValue(pointOffsets.size()); @@ -119,6 +149,11 @@ bt::Vector3 geo::Geometry::getPointPos(ga::Offset pointOffset) const return posHandlePoint_.getValue(pointOffset); } +ga::Offset geo::Geometry::getVertexPrim(ga::Offset vertexOffset) const +{ + return vertexPrims_[vertexOffset]; +} + void geo::Geometry::setPointPos(const ga::Offset offset, const bt::Vector3& pos) { posHandlePoint_.setValue(offset, pos); @@ -250,19 +285,30 @@ enzo::geo::HeMesh geo::Geometry::computeHalfEdgeMesh() ga::Offset geo::Geometry::getPrimStartVertex(ga::Offset primOffset) const { + if(primStartsDirty_.load()) + { + tbb::spin_mutex::scoped_lock lock(primStartsMutex_); //lock + if(primStartsDirty_.load()) // double check + { + computePrimStartVertices(); + } + } return primStarts_[primOffset]; } // TODO: handle this automatically -void geo::Geometry::computePrimStartVertices() +void geo::Geometry::computePrimStartVertices() const { const ga::Offset handleSize = vertexCountHandlePrim_.getSize(); + primStarts_.clear(); + primStarts_.reserve(handleSize); bt::intT primStart = 0; for(size_t i=0; i #include "Engine/Operator/AttributeHandle.h" #include +#include +#include #include @@ -27,6 +29,7 @@ class Geometry public: Geometry(); Geometry(const Geometry& other); + Geometry& operator=(const Geometry& rhs); ga::AttributeHandle addIntAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandleBool addBoolAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandle addVector3Attribute(ga::AttributeOwner owner, std::string name); @@ -48,18 +51,19 @@ public: void setPointPos(const ga::Offset offset, const bt::Vector3& pos); - ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive - bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; - bt::Vector3 getPointPos(ga::Offset pointOffset) const; - unsigned int getPrimVertCount(ga::Offset primOffset) const; - ga::Offset getNumPrims() const; - ga::Offset getNumVerts() const; - ga::Offset getNumPoints() const; - ga::Offset getNumSoloPoints() const; + ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive + bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; + bt::Vector3 getPointPos(ga::Offset pointOffset) const; + unsigned int getPrimVertCount(ga::Offset primOffset) const; + ga::Offset getVertexPrim(ga::Offset vertexOffset) const; + ga::Offset getNumPrims() const; + ga::Offset getNumVerts() const; + ga::Offset getNumPoints() const; + ga::Offset getNumSoloPoints() const; bt::boolT isClosed(ga::Offset primOffset) const; - void computePrimStartVertices(); + void computePrimStartVertices() const; private: using attribVector = std::vector>; geo::Geometry::attribVector& getAttributeStore(const ga::AttributeOwner& owner); @@ -74,7 +78,11 @@ private: std::set soloPoints_; - std::vector primStarts_; + mutable std::vector primStarts_; + mutable std::vector vertexPrims_; + + mutable std::atomic primStartsDirty_{true}; + mutable tbb::spin_mutex primStartsMutex_; // handles enzo::ga::AttributeHandleInt vertexCountHandlePrim_; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp index fa3dd8d..24e05ab 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -133,8 +133,12 @@ GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::Wind nodeLabel_ = new QLabel(); mainLayout_->addWidget(nodeLabel_); modeSelection = new GeoSheetMenuBarModeSelection(); + mainLayout_->addStretch(); mainLayout_->addWidget(modeSelection); + const int margins = 0; + mainLayout_->setContentsMargins(margins, margins, margins, margins); + setLayout(mainLayout_); } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index 81654fa..94318e6 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -87,7 +87,7 @@ int GeometrySpreadsheetModel::rowCount(const QModelIndex &parent) const int GeometrySpreadsheetModel::columnCount(const QModelIndex &parent) const { - int columnCount = 0; + int columnCount = attributeColumnPadding_; // first column is for indices for(auto size : attribSizes_) { columnCount += size; @@ -114,11 +114,34 @@ QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) cons if (role == Qt::DisplayRole) { - // std::cout << geometry_.getPointPos(index.row()).x() << "\n"; - int attributeIndex = indexFromSection(index.column()); + if(index.column()==0) + { + switch(attributeOwner_) + { + case enzo::ga::AttributeOwner::POINT: + case enzo::ga::AttributeOwner::PRIMITIVE: + { + return index.row(); + } + case enzo::ga::AttributeOwner::VERTEX: + { + const enzo::ga::Offset primOffset = geometry_.getVertexPrim(index.row()); + const enzo::ga::Offset startVert = geometry_.getPrimStartVertex(primOffset); + const enzo::ga::Offset vertexNumber = index.row()-startVert; + return QString::fromStdString(std::to_string(primOffset)+":"+std::to_string(vertexNumber)); + + } + case enzo::ga::AttributeOwner::GLOBAL: + { + return "global"; + } + + } + } + int attributeIndex = indexFromSection(index.column()-attributeColumnPadding_); if(std::shared_ptr attrib = geometry_.getAttributeByIndex(attributeOwner_, attributeIndex).lock()) { - const unsigned int valueIndex = index.column()-attributeIndex; + const unsigned int valueIndex = index.column()-attributeIndex-attributeColumnPadding_; using namespace enzo::ga; switch(attrib->getType()) @@ -167,9 +190,8 @@ int GeometrySpreadsheetModel::indexFromSection(unsigned int section) const { if(section>=sectionAttribMap_.size()) { - throw std::out_of_range("Section is out of range of sectionAttributMap_"); + throw std::out_of_range("Section is out of range of sectionAttributMap_, value: " + std::to_string(section) + " expected: <"+std::to_string(sectionAttribMap_.size())); } - IC(sectionAttribMap_); return sectionAttribMap_[section]; } @@ -182,12 +204,13 @@ QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orien if (orientation == Qt::Horizontal) { - auto attributeIndex = indexFromSection(section); + if(section==0) return "Index"; + auto attributeIndex = indexFromSection(section-attributeColumnPadding_); if(auto attrib = geometry_.getAttributeByIndex(attributeOwner_, attributeIndex).lock()) { if(attribSizes_[attributeIndex]>1) { - const unsigned int valueIndex = section-attributeIndex; + const unsigned int valueIndex = section-attributeIndex-attributeColumnPadding_; std::string valueIndexString; if(attrib->getType()==enzo::ga::AttrType::vectorT) diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index debff55..500b790 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -23,11 +23,13 @@ public: void initBuffers(); + private: enzo::nt::OpId opId_; enzo::geo::Geometry geometry_; std::vector attribSizes_; std::vector sectionAttribMap_; + const int attributeColumnPadding_ = 1; enzo::ga::AttributeOwner attributeOwner_=enzo::ga::AttributeOwner::POINT; }; From 03fe287327952405094c7f43cdf25da37dca7d86 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 11 Aug 2025 01:06:10 +0100 Subject: [PATCH 13/14] feat(geometrySpreadsheet): update styling --- .../GeometrySpreadsheetMenuBar.cpp | 21 +++++++++++++--- .../GeometrySpreadsheetModel.cpp | 9 ++++++- .../GeometrySpreadsheetPanel.cpp | 25 +++++++++++++++++++ src/Gui/Interface.cpp | 2 +- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp index 24e05ab..0b6fe82 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -81,6 +81,9 @@ GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt:: : QWidget(parent, f) { mainLayout_ = new QHBoxLayout(); + constexpr int mainMargin = 0; + mainLayout_->setContentsMargins(mainMargin,mainMargin,mainMargin,mainMargin); + QWidget* buttonBg = new QWidget(); buttonBg->setObjectName("GeoSheetMenuBarButtonBg"); buttonBg->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); @@ -90,7 +93,7 @@ GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt:: R"( #GeoSheetMenuBarButtonBg { - background-color: #383838; + background-color: #242424; border-radius: 8px; } @@ -131,12 +134,22 @@ GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::Wind { mainLayout_ = new QHBoxLayout(); nodeLabel_ = new QLabel(); - mainLayout_->addWidget(nodeLabel_); modeSelection = new GeoSheetMenuBarModeSelection(); + + mainLayout_->addWidget(nodeLabel_); mainLayout_->addStretch(); mainLayout_->addWidget(modeSelection); + setProperty("class", "GeometrySpreadsheetMenuBar"); + setStyleSheet( + R"( + .GeometrySpreadsheetMenuBar, + .GeometrySpreadsheetMenuBar * + { + background-color: #1B1B1B; + } + )"); - const int margins = 0; + constexpr int margins = 5; mainLayout_->setContentsMargins(margins, margins, margins, margins); setLayout(mainLayout_); @@ -145,5 +158,5 @@ GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::Wind void GeometrySpreadsheetMenuBar::setNode(enzo::nt::OpId opId) { enzo::nt::GeometryOperator& geoOp = enzo::nt::nm().getGeoOperator(opId); - nodeLabel_->setText("Node: " + QString::fromStdString(geoOp.getLabel())); + nodeLabel_->setText("Node: " + QString::fromStdString(geoOp.getLabel())); } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index 94318e6..2e87189 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -5,8 +5,10 @@ #include "Engine/Types.h" #include #include +#include #include #include +#include GeometrySpreadsheetModel::GeometrySpreadsheetModel(QObject *parent) @@ -111,7 +113,12 @@ QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) cons // return QVariant(); // } - if (role == Qt::DisplayRole) + if(role == Qt::BackgroundRole && index.column()==0) + { + return QBrush("#1B1B1B"); + + } + else if (role == Qt::DisplayRole) { if(index.column()==0) diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp index 9aea7f7..5377c3c 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetPanel.cpp @@ -14,17 +14,42 @@ GeometrySpreadsheetPanel::GeometrySpreadsheetPanel(QWidget *parent, Qt::WindowFl : QWidget(parent, f) { mainLayout_ = new QVBoxLayout(); + mainLayout_->setSpacing(0); view_ = new QTreeView(parent); view_->setRootIsDecorated(false); view_->setAlternatingRowColors(true); + view_->setUniformRowHeights(true); // improves performance view_->setStyleSheet(R"( QTreeView { background-color: #282828; alternate-background-color: #242424; paint-alternating-row-colors-for-empty-area: 1; } + QTreeView QScrollBar { + background: #1B1B1B; + width: 15px; + } + QTreeView QScrollBar::handle:vertical { + background: #282828; + min-height: 50px; + border-radius: 5px; + border-width: 1px; + border-color: #2D2D2D; + border-style: solid; + margin:2px; + } + + QTreeView QScrollBar::add-page:vertical, + QTreeView QScrollBar::sub-page:vertical, + QTreeView QScrollBar::add-line:vertical, + QTreeView QScrollBar::sub-line:vertical + { height: 0px; } + + QHeaderView::section { + background-color: #1B1B1B; + } )"); view_->setFrameStyle(QFrame::NoFrame); diff --git a/src/Gui/Interface.cpp b/src/Gui/Interface.cpp index cdc8c6f..16381ad 100644 --- a/src/Gui/Interface.cpp +++ b/src/Gui/Interface.cpp @@ -53,7 +53,7 @@ EnzoUI::EnzoUI() viewportSplitter_->addWidget(spreadsheetSplitter_); viewportSplitter_->addWidget(networkSplitter_); - viewportSplitter_->setSizes({100,300}); + viewportSplitter_->setSizes({100,200}); networkSplitter_->addWidget(parametersPanel); networkSplitter_->addWidget(network); From 8121414be1a31d3a5ae40bdcf9802e11b36e2134 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 11 Aug 2025 01:37:39 +0100 Subject: [PATCH 14/14] feat(geometrySpreadsheet): add icons --- .../GeometrySpreadsheetMenuBar.cpp | 15 +-- static/icons/attributeBase.svg | 76 +++++++++++ static/icons/attributeGlobal.svg | 76 +++++++++++ static/icons/attributePoint.svg | 81 ++++++++++++ static/icons/attributePrimitive.svg | 76 +++++++++++ static/icons/attributeVertex.svg | 121 ++++++++++++++++++ static/resources.qrc | 5 + 7 files changed, 442 insertions(+), 8 deletions(-) create mode 100644 static/icons/attributeBase.svg create mode 100644 static/icons/attributeGlobal.svg create mode 100644 static/icons/attributePoint.svg create mode 100644 static/icons/attributePrimitive.svg create mode 100644 static/icons/attributeVertex.svg diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp index 0b6fe82..1c66af4 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -30,7 +30,6 @@ GeoSheetModeButton::GeoSheetModeButton(QWidget* parent) // } // )"); - setIcon(QIcon(":/node-icons/grid.svg")); } void GeoSheetModeButton::enterEvent(QEnterEvent *event) @@ -68,8 +67,7 @@ void GeoSheetModeButton::paintEvent(QPaintEvent* event) QPixmap pixmap = buttonIcon.pixmap(size); - QPoint center = event->rect().center() - QPoint(size.width() / 2, size.height() / 2); - // QPoint center = QPoint(0,0); + QPoint center = rect().center() - QPoint(size.width() / 2, size.height() / 2); painter.drawPixmap(center, pixmap); } @@ -104,19 +102,20 @@ GeoSheetMenuBarModeSelection::GeoSheetMenuBarModeSelection(QWidget *parent, Qt:: modeButtonGroup_.setExclusive(true); - auto newButton = [this, &buttonBgLayout](const char* tooltip="") + auto newButton = [this, &buttonBgLayout](const char* tooltip="", const char* iconPath=":/icons/attributePoint.svg") { auto newButton = new GeoSheetModeButton(); newButton->setToolTip(tooltip); + newButton->setIcon(QIcon(iconPath)); modeButtonGroup_.addButton(newButton); buttonBgLayout->addWidget(newButton); return newButton; }; - pointButton = newButton("Point Attributes"); - vertexButton = newButton("Vertex Attributes"); - primitiveButton = newButton("Primitive Attributes"); - globalButton = newButton("Global Attributes"); + pointButton = newButton("Point Attributes", ":/icons/attributePoint.svg"); + vertexButton = newButton("Vertex Attributes", ":/icons/attributeVertex.svg"); + primitiveButton = newButton("Primitive Attributes", ":/icons/attributePrimitive.svg"); + globalButton = newButton("Global Attributes", ":/icons/attributeGlobal.svg"); pointButton->setChecked(true); diff --git a/static/icons/attributeBase.svg b/static/icons/attributeBase.svg new file mode 100644 index 0000000..7b27707 --- /dev/null +++ b/static/icons/attributeBase.svg @@ -0,0 +1,76 @@ + + + + diff --git a/static/icons/attributeGlobal.svg b/static/icons/attributeGlobal.svg new file mode 100644 index 0000000..83a219c --- /dev/null +++ b/static/icons/attributeGlobal.svg @@ -0,0 +1,76 @@ + + + + diff --git a/static/icons/attributePoint.svg b/static/icons/attributePoint.svg new file mode 100644 index 0000000..c496ad0 --- /dev/null +++ b/static/icons/attributePoint.svg @@ -0,0 +1,81 @@ + + + + diff --git a/static/icons/attributePrimitive.svg b/static/icons/attributePrimitive.svg new file mode 100644 index 0000000..59fbcdd --- /dev/null +++ b/static/icons/attributePrimitive.svg @@ -0,0 +1,76 @@ + + + + diff --git a/static/icons/attributeVertex.svg b/static/icons/attributeVertex.svg new file mode 100644 index 0000000..84c013b --- /dev/null +++ b/static/icons/attributeVertex.svg @@ -0,0 +1,121 @@ + + + + diff --git a/static/resources.qrc b/static/resources.qrc index e25bec4..21592b0 100644 --- a/static/resources.qrc +++ b/static/resources.qrc @@ -1,5 +1,10 @@ node-icons/grid.svg + icons/attributePoint.svg + icons/attributeVertex.svg + icons/attributePrimitive.svg + icons/attributeGlobal.svg + icons/attributeBase.svg