From a4c8b77f3a756d9b3deb6b9e78aa81c5a8a601f6 Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Mon, 24 Nov 2025 21:14:24 -0800 Subject: [PATCH] Fixed crash on initialization of KRResourceBinding encapsulated in KRNodeProperty by changing default value to an empty string rather than nullptr. Implemented KRNODE_PROPERTY_ARRAY. KRModel meshes are now using KRNODE_PROPERTY_ARRAY --- kraken/nodes/KRAmbientZone.h | 2 +- kraken/nodes/KRAudioSource.h | 2 +- kraken/nodes/KRCollider.h | 2 +- kraken/nodes/KRModel.cpp | 39 +++++++++++++++---------------- kraken/nodes/KRModel.h | 3 +-- kraken/nodes/KRNode.h | 45 +++++++++++++++++++++++++----------- kraken/nodes/KRReverbZone.h | 2 +- 7 files changed, 55 insertions(+), 40 deletions(-) diff --git a/kraken/nodes/KRAmbientZone.h b/kraken/nodes/KRAmbientZone.h index b49383c..cd076f9 100755 --- a/kraken/nodes/KRAmbientZone.h +++ b/kraken/nodes/KRAmbientZone.h @@ -71,5 +71,5 @@ private: KRNODE_PROPERTY(std::string, m_zone, "", "zone"); KRNODE_PROPERTY(float, m_gradient_distance, 0.25f, "gradient"); KRNODE_PROPERTY(float, m_ambient_gain, 1.f, "gain"); - KRNODE_PROPERTY(KRAudioSampleBinding, m_ambient, nullptr, "sample"); + KRNODE_PROPERTY(KRAudioSampleBinding, m_ambient, "", "sample"); }; diff --git a/kraken/nodes/KRAudioSource.h b/kraken/nodes/KRAudioSource.h index 5e695cd..7932c39 100755 --- a/kraken/nodes/KRAudioSource.h +++ b/kraken/nodes/KRAudioSource.h @@ -133,7 +133,7 @@ private: int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer void advanceBuffer(); - KRNODE_PROPERTY(KRAudioSampleBinding, m_sample, nullptr, "sample"); + KRNODE_PROPERTY(KRAudioSampleBinding, m_sample, "", "sample"); KRNODE_PROPERTY(float, m_gain, 1.f, "gain"); KRNODE_PROPERTY(float, m_pitch, 1.f, "pitch"); KRNODE_PROPERTY(bool, m_looping, false, "looping"); diff --git a/kraken/nodes/KRCollider.h b/kraken/nodes/KRCollider.h index 484f8e9..0c37ba5 100755 --- a/kraken/nodes/KRCollider.h +++ b/kraken/nodes/KRCollider.h @@ -74,7 +74,7 @@ public: void render(RenderInfo& ri) override; private: - KRNODE_PROPERTY(KRMeshBinding, m_model, nullptr, "mesh"); + KRNODE_PROPERTY(KRMeshBinding, m_model, "", "mesh"); KRNODE_PROPERTY(unsigned int, m_layer_mask, 0xffffffff, "layer_mask"); KRNODE_PROPERTY(float, m_audio_occlusion, 1.f, "audio_occlusion"); diff --git a/kraken/nodes/KRModel.cpp b/kraken/nodes/KRModel.cpp index adb00c0..027e230 100755 --- a/kraken/nodes/KRModel.cpp +++ b/kraken/nodes/KRModel.cpp @@ -109,7 +109,7 @@ KrResult KRModel::update(const KrNodeInfo* nodeInfo) return res; } } - m_meshes[lod].set(mesh); + m_meshes[lod].val.set(mesh); } return KR_SUCCESS; @@ -128,13 +128,12 @@ void KRModel::loadXML(tinyxml2::XMLElement* e) m_receivesShadow.load(e); m_rim_power.load(e); m_rim_color.load(e); - std::string meshNames[KRModel::kMeshLODCount]; - m_meshes[0].set(e->Attribute("mesh")); + m_meshes[0].load(e); for (int lod = 1; lod < KRModel::kMeshLODCount; lod++) { char attribName[8]; snprintf(attribName, 8, "mesh%i", lod); - m_meshes[lod].set(e->Attribute(attribName)); + m_meshes[lod].load(e, attribName); } m_lightMap.load(e); @@ -143,11 +142,11 @@ void KRModel::loadXML(tinyxml2::XMLElement* e) tinyxml2::XMLElement* KRModel::saveXML(tinyxml2::XMLNode* parent) { tinyxml2::XMLElement* e = KRNode::saveXML(parent); - e->SetAttribute("mesh", m_meshes[0].getName().c_str()); + m_meshes[0].load(e); for (int lod = 1; lod < kMeshLODCount; lod++) { char attribName[8]; snprintf(attribName, 8, "mesh%i", lod); - e->SetAttribute(attribName, m_meshes[lod].getName().c_str()); + m_meshes[lod].load(e, attribName); } m_lightMap.save(e); m_min_lod_coverage.save(e); @@ -193,13 +192,13 @@ void KRModel::loadModel() bool meshChanged = false; for (int lod = 0; lod < kMeshLODCount; lod++) { KRMesh* prevMesh = nullptr; - prevMesh = m_meshes[lod].get(); - m_meshes[lod].bind(&getContext()); - if (m_meshes[lod].get() != prevMesh) { + prevMesh = m_meshes[lod].val.get(); + m_meshes[lod].val.bind(&getContext()); + if (m_meshes[lod].val.get() != prevMesh) { meshChanged = true; } - if (m_meshes[lod].isBound()) { - KRMesh* model = m_meshes[lod].get(); + if (m_meshes[lod].val.isBound()) { + KRMesh* model = m_meshes[lod].val.get(); std::vector model_bones; int bone_count = model->getBoneCount(); bool all_bones_found = true; @@ -262,8 +261,8 @@ void KRModel::render(KRNode::RenderInfo& ri) int bestLOD = -1; KRMesh* pModel = nullptr; for (int lod = 0; lod < kMeshLODCount; lod++) { - if (m_meshes[lod].isBound()) { - KRMesh* pLODModel = m_meshes[lod].get(); + if (m_meshes[lod].val.isBound()) { + KRMesh* pLODModel = m_meshes[lod].val.get(); if ((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage) { if(bestLOD == -1 || pLODModel->getLODCoverage() < pModel->getLODCoverage()) { @@ -294,7 +293,7 @@ void KRModel::getResourceBindings(std::list& bindings) KRNode::getResourceBindings(bindings); for (int i = 0; i < kMeshLODCount; i++) { - bindings.push_back(&m_meshes[i]); + bindings.push_back(&m_meshes[i].val); } bindings.push_back(&m_lightMap.val); } @@ -306,8 +305,8 @@ void KRModel::preStream(const KRViewport& viewport, std::list loadModel(); for (int i = 0; i < kMeshLODCount; i++) { - if (m_meshes[i].isBound()) { - m_meshes[i].get()->preStream(); + if (m_meshes[i].val.isBound()) { + m_meshes[i].val.get()->preStream(); } } } @@ -319,8 +318,8 @@ kraken_stream_level KRModel::getStreamLevel(const KRViewport& viewport) loadModel(); for (int lod = 0; lod < kMeshLODCount; lod++) { - if (m_meshes[lod].isBound()) { - stream_level = KRMIN(stream_level, m_meshes[lod].get()->getStreamLevel()); + if (m_meshes[lod].val.isBound()) { + stream_level = KRMIN(stream_level, m_meshes[lod].val.get()->getStreamLevel()); } } @@ -333,10 +332,10 @@ AABB KRModel::getBounds() // Get the bounds of the lowest lod mesh for(int lod=0; lodgetMinPoint(), mesh->getMaxPoint(), getModelMatrix()); float max_dimension = normal_bounds.longest_radius(); diff --git a/kraken/nodes/KRModel.h b/kraken/nodes/KRModel.h index 7ef92ad..ab3399a 100755 --- a/kraken/nodes/KRModel.h +++ b/kraken/nodes/KRModel.h @@ -80,8 +80,7 @@ public: private: - std::array m_meshes; - + KRNODE_PROPERTY_ARRAY(KRMeshBinding, m_meshes, "", "mesh", kMeshLODCount); KRNODE_PROPERTY(KRTextureBinding, m_lightMap, KRTexture::TEXTURE_USAGE_LIGHT_MAP, "light_map"); KRNODE_PROPERTY(float, m_min_lod_coverage, 0.f, "min_lod_coverage"); KRNODE_PROPERTY(bool, m_receivesShadow, true, "receives_shadow"); diff --git a/kraken/nodes/KRNode.h b/kraken/nodes/KRNode.h index ea8c077..ce84899 100755 --- a/kraken/nodes/KRNode.h +++ b/kraken/nodes/KRNode.h @@ -96,53 +96,63 @@ public: } void save(tinyxml2::XMLElement* element) const + { + save(element, config::name); + } + + void save(tinyxml2::XMLElement* element, const char* attributeName) const { if constexpr (std::is_same::value) { - element->SetAttribute(config::name, val ? "true" : "false"); + element->SetAttribute(attributeName, val ? "true" : "false"); } else if constexpr (std::is_same::value) { - kraken::setXMLAttribute(config::name, element, val, config::defaultVal); + kraken::setXMLAttribute(attributeName, element, val, config::defaultVal); } else if constexpr (std::is_same::value) { - kraken::setXMLAttribute(config::name, element, val, config::defaultVal); + kraken::setXMLAttribute(attributeName, element, val, config::defaultVal); } else if constexpr (std::is_same::value) { - element->SetAttribute(config::name, val.c_str()); + element->SetAttribute(attributeName, val.c_str()); } else if constexpr (std::is_base_of::value) { - element->SetAttribute(config::name, val.getName().c_str()); + element->SetAttribute(attributeName, val.getName().c_str()); } else { - element->SetAttribute(config::name, val); + element->SetAttribute(attributeName, val); } } void load(tinyxml2::XMLElement* element) + { + load(element, config::name); + } + + void load(tinyxml2::XMLElement* element, const char* attributeName) { if constexpr (std::is_same::value) { - if (element->QueryIntAttribute(config::name, &val) != tinyxml2::XML_SUCCESS) { + if (element->QueryIntAttribute(attributeName, &val) != tinyxml2::XML_SUCCESS) { val = config::defaultVal; } } else if constexpr (std::is_same::value) { - if (element->QueryUnsignedAttribute(config::name, &val) != tinyxml2::XML_SUCCESS) { + if (element->QueryUnsignedAttribute(attributeName, &val) != tinyxml2::XML_SUCCESS) { val = config::defaultVal; } } else if constexpr (std::is_same::value) { - if (element->QueryFloatAttribute(config::name, &val) != tinyxml2::XML_SUCCESS) { + if (element->QueryFloatAttribute(attributeName, &val) != tinyxml2::XML_SUCCESS) { val = config::defaultVal; } } else if constexpr (std::is_same::value) { - if (element->QueryBoolAttribute(config::name, &val) != tinyxml2::XML_SUCCESS) { + if (element->QueryBoolAttribute(attributeName, &val) != tinyxml2::XML_SUCCESS) { val = config::defaultVal; } } else if constexpr (std::is_same::value) { - val = kraken::getXMLAttribute(config::name, element, config::defaultVal); + val = kraken::getXMLAttribute(attributeName, element, config::defaultVal); } else if constexpr (std::is_same::value) { - val = kraken::getXMLAttribute(config::name, element, config::defaultVal); + val = kraken::getXMLAttribute(attributeName, element, config::defaultVal); } else if constexpr (std::is_same::value) { - const char* name = element->Attribute(config::name); + const char* name = element->Attribute(attributeName); if (name) { val = name; } else { val = config::defaultVal; } } else if constexpr (std::is_base_of::value) { - const char* name = element->Attribute(config::name); + const char* name = element->Attribute(attributeName); if (name) { val.set(name); } else { @@ -163,6 +173,13 @@ public: }; \ KRNodeProperty VAR; +#define KRNODE_PROPERTY_ARRAY(PROP_TYPE, VAR, PROP_DEFAULT, PROP_NAME, ARRAY_SIZE) \ + struct VAR ## _config { \ + static constexpr decltype(PROP_DEFAULT) defaultVal = PROP_DEFAULT; \ + static constexpr const char* name = PROP_NAME; \ + }; \ + std::array, ARRAY_SIZE> VAR; + class KRNode : public KRContextObject , public KRReflectedObject diff --git a/kraken/nodes/KRReverbZone.h b/kraken/nodes/KRReverbZone.h index 6b9f9fb..2ed2572 100755 --- a/kraken/nodes/KRReverbZone.h +++ b/kraken/nodes/KRReverbZone.h @@ -69,6 +69,6 @@ public: private: KRNODE_PROPERTY(std::string, m_zone, "", "zone"); KRNODE_PROPERTY(float, m_gradient_distance, 0.25f, "gradient"); - KRNODE_PROPERTY(KRAudioSampleBinding, m_reverb, nullptr, "sample"); + KRNODE_PROPERTY(KRAudioSampleBinding, m_reverb, "", "sample"); KRNODE_PROPERTY(float, m_reverb_gain, 1.f, "gain"); };