diff --git a/src/Core/Object.cpp b/src/Core/Object.cpp index 9f861b0..f1d92fb 100644 --- a/src/Core/Object.cpp +++ b/src/Core/Object.cpp @@ -59,6 +59,10 @@ public: GenericMFPtr sloptr; std::string slostr; }; + + ~ObjectPrivate() { + for (auto& s : sigv) delete s.signal; + } std::string m_InstanceName; std::vector sigv; @@ -71,7 +75,13 @@ public: // Implementations of Property methods void Object::RegisterDisplayProperty(PropertyBase* prop) { - if (prop) d->m_DisplayProperties.push_back(prop); + if (prop) { + for (auto* existing : d->m_DisplayProperties) { + if (existing == prop) return; + if (existing->GetName() == prop->GetName()) return; + } + d->m_DisplayProperties.push_back(prop); + } } const std::vector& Object::GetDisplayProperties() const { @@ -80,6 +90,10 @@ const std::vector& Object::GetDisplayProperties() const { void Object::RegisterProperty(PropertyBase* prop) { if (prop) { + for (auto* existing : d->m_Properties) { + if (existing == prop) return; + if (existing->GetName() == prop->GetName()) return; + } d->m_Properties.push_back(prop); } } @@ -105,13 +119,16 @@ PropertyBase* Object::GetProperty(const std::string& name) const { for (auto* p : d->m_DynamicProperties) { if (p->GetName() == name || p->GetQualifiedName() == name) return p; } + for (auto* p : d->m_DisplayProperties) { + if (p->GetName() == name || p->GetQualifiedName() == name) return p; + } return nullptr; } void Object::NotifyPropertiesUpdated() { + // Only notify properties in the primary list to avoid duplicates, + // as all registered properties should be there. for (auto* p : d->m_Properties) p->Updated(); - for (auto* p : d->m_DynamicProperties) p->Updated(); - this->Updated(); } void Object::Updated() { ULIB_SIGNAL_EMIT(Object::Updated); } @@ -147,6 +164,9 @@ Object::~Object() { for (auto* p : d->m_DynamicProperties) { delete p; } + for (auto* p : d->m_DisplayProperties) { + delete p; + } delete d; } diff --git a/src/Core/Property.h b/src/Core/Property.h index acf9348..e9386da 100644 --- a/src/Core/Property.h +++ b/src/Core/Property.h @@ -103,6 +103,7 @@ public: // Accessors const T& Get() const { return *m_value; } void Set(const T& value) { + if (!m_value) return; T val = value; if constexpr (std::is_arithmetic::value) { if (m_HasRange) { if (val < m_Min) val = m_Min; if (val > m_Max) val = m_Max; } diff --git a/src/Core/testing/ObjectWrapperTest.cpp b/src/Core/testing/ObjectWrapperTest.cpp index 84191dd..06b9e72 100644 --- a/src/Core/testing/ObjectWrapperTest.cpp +++ b/src/Core/testing/ObjectWrapperTest.cpp @@ -24,3 +24,5 @@ int main() { std::cout << "Tests passed (compilation and manual instantiation)!" << std::endl; return 0; } + + diff --git a/src/Vtk/Math/testing/vtkContainerBoxTest.cpp b/src/Vtk/Math/testing/vtkContainerBoxTest.cpp index 1804776..5ab94ab 100644 --- a/src/Vtk/Math/testing/vtkContainerBoxTest.cpp +++ b/src/Vtk/Math/testing/vtkContainerBoxTest.cpp @@ -36,11 +36,11 @@ int main() { BEGIN_TESTING(vtk ContainerBox Test); { - ContainerBox box; - box.Scale(Vector3f(1_m, 2_m, 1_m)); - box.SetPosition(Vector3f(0, 0, 0)); + ContainerBox* box = new ContainerBox(); + box->Scale(Vector3f(1_m, 2_m, 1_m)); + box->SetPosition(Vector3f(0, 0, 0)); - Vtk::ContainerBox v_box(&box); + Vtk::ContainerBox v_box(box); v_box.Update(); v_box.SetRepresentation(Vtk::Prop3D::Surface); diff --git a/src/Vtk/Math/testing/vtkContainerBoxTest2.cpp b/src/Vtk/Math/testing/vtkContainerBoxTest2.cpp index 1db8e3b..11b858a 100644 --- a/src/Vtk/Math/testing/vtkContainerBoxTest2.cpp +++ b/src/Vtk/Math/testing/vtkContainerBoxTest2.cpp @@ -15,11 +15,11 @@ using namespace uLib; int main() { std::cout << "Creating ContainerBox..." << std::endl; - ContainerBox box(Vector3f(1.0, 1.0, 1.0)); // 1x1x1 unit box - box.SetInstanceName("MyTestBox"); + ContainerBox* box = new ContainerBox(Vector3f(1.0, 1.0, 1.0)); // 1x1x1 unit box + box->SetInstanceName("MyTestBox"); std::cout << "Creating VTK representation..." << std::endl; - Vtk::ContainerBox v_box(&box); + Vtk::ContainerBox v_box(box); v_box.SetRepresentation(Vtk::Prop3D::Wireframe); v_box.SetColor(1.0, 0.0, 0.0); // Red diff --git a/src/Vtk/testing/Prop3DPropertyTest.cpp b/src/Vtk/testing/Prop3DPropertyTest.cpp index 72bff19..60c0c31 100644 --- a/src/Vtk/testing/Prop3DPropertyTest.cpp +++ b/src/Vtk/testing/Prop3DPropertyTest.cpp @@ -11,6 +11,7 @@ #include "Vtk/uLibVtkInterface.h" #include "Core/Property.h" +#include "Math/Dense.h" #include #include #include "testing-prototype.h" @@ -33,7 +34,7 @@ int main() { // Verify specific properties exist Property* opacityProp = nullptr; - Property* colorRProp = nullptr; + Property* colorProp = nullptr; for (auto* prop : props) { std::cout << " - [" << prop->GetTypeName() << "] " << prop->GetName() @@ -42,13 +43,13 @@ int main() { if (prop->GetName() == "Opacity") { opacityProp = dynamic_cast*>(prop); } - if (prop->GetName() == "ColorR") { - colorRProp = dynamic_cast*>(prop); + if (prop->GetName() == "Color") { + colorProp = dynamic_cast*>(prop); } } assert(opacityProp != nullptr && "Opacity property not registered!"); - assert(colorRProp != nullptr && "ColorR property not registered!"); + assert(colorProp != nullptr && "Color property not registered!"); // Test modification via uLib Property interface std::cout << "Modifying Opacity via property proxy (0.25)..." << std::endl; @@ -58,9 +59,9 @@ int main() { assert(opacityProp->Get() == 0.25); assert(opacityProp->GetValueAsString().find("0.25") != std::string::npos); - std::cout << "Modifying ColorR via property proxy (0.9)..." << std::endl; - *colorRProp = 0.9; - assert(colorRProp->Get() == 0.9); + std::cout << "Modifying Color via property proxy (0.9, 0.1, 0.1)..." << std::endl; + *colorProp = Vector3d(0.9, 0.1, 0.1); + assert(colorProp->Get().x() == 0.9); std::cout << "All Prop3D Property Registration Tests PASSED!" << std::endl; diff --git a/src/Vtk/uLibVtkInterface.cxx b/src/Vtk/uLibVtkInterface.cxx index 6dbd2bf..90ad2f8 100644 --- a/src/Vtk/uLibVtkInterface.cxx +++ b/src/Vtk/uLibVtkInterface.cxx @@ -290,9 +290,6 @@ public: Prop3D::Prop3D() : Object(), pd(new Prop3DData(this)) { ULIB_ACTIVATE_DISPLAY_PROPERTIES; - for (auto* p : this->GetDisplayProperties()) { - uLib::Object::connect(p, &uLib::Object::Updated, this, &Prop3D::Update); - } } Prop3D::~Prop3D()