diff --git a/include/threepp/core/EventDispatcher.hpp b/include/threepp/core/EventDispatcher.hpp index ab457b0b..8bcd4b25 100644 --- a/include/threepp/core/EventDispatcher.hpp +++ b/include/threepp/core/EventDispatcher.hpp @@ -33,6 +33,8 @@ namespace threepp { void removeEventListener(const std::string& type, const EventListener* listener); + void removeAllEventListeners(const std::string& type); + void dispatchEvent(const std::string& type, void* target = nullptr); virtual ~EventDispatcher() = default; diff --git a/include/threepp/renderers/GLRenderer.hpp b/include/threepp/renderers/GLRenderer.hpp index f2a3579e..51225983 100644 --- a/include/threepp/renderers/GLRenderer.hpp +++ b/include/threepp/renderers/GLRenderer.hpp @@ -154,7 +154,7 @@ namespace threepp { [[nodiscard]] const gl::GLInfo& info() const; - [[nodiscard]] std::optional getGlTextureId(const Texture& texture) const; + [[nodiscard]] std::optional getGlTextureId(Texture& texture) const; ~GLRenderer(); diff --git a/src/threepp/core/EventDispatcher.cpp b/src/threepp/core/EventDispatcher.cpp index 3b3f3ee0..24121f18 100644 --- a/src/threepp/core/EventDispatcher.cpp +++ b/src/threepp/core/EventDispatcher.cpp @@ -46,3 +46,7 @@ void EventDispatcher::dispatchEvent(const std::string& type, void* target) { } } } +void EventDispatcher::removeAllEventListeners(const std::string& type) { + + listeners_.erase(type); +} diff --git a/src/threepp/renderers/GLRenderer.cpp b/src/threepp/renderers/GLRenderer.cpp index 2255384e..e3d78b0b 100644 --- a/src/threepp/renderers/GLRenderer.cpp +++ b/src/threepp/renderers/GLRenderer.cpp @@ -161,7 +161,7 @@ struct GLRenderer::Impl { this->setScissor(0, 0, _size.width, _size.height); } - [[nodiscard]] std::optional getGlTextureId(const Texture& texture) const { + [[nodiscard]] std::optional getGlTextureId(Texture& texture) const { return textures.getGlTexture(texture); } @@ -170,12 +170,12 @@ struct GLRenderer::Impl { releaseMaterialProgramReferences(material); - properties.materialProperties.remove(material->uuid()); + properties.materialProperties.remove(material); } void releaseMaterialProgramReferences(Material* material) { - auto& programs = properties.materialProperties.get(material->uuid())->programs; + auto& programs = properties.materialProperties.get(material)->programs; if (!programs.empty()) { @@ -580,7 +580,7 @@ struct GLRenderer::Impl { auto* scene = _scene->as(); if (!scene) scene = _emptyScene.get();// scene could be a Mesh, Line, Points, ... - auto materialProperties = properties.materialProperties.get(material->uuid()); + auto materialProperties = properties.materialProperties.get(material); auto& lights = currentRenderState->getLights(); auto& shadowsArray = currentRenderState->getShadowsArray(); @@ -686,7 +686,7 @@ struct GLRenderer::Impl { void updateCommonMaterialProperties(Material* material, gl::ProgramParameters& parameters) { - auto materialProperties = properties.materialProperties.get(material->uuid()); + auto materialProperties = properties.materialProperties.get(material); materialProperties->outputEncoding = parameters.outputEncoding; materialProperties->instancing = parameters.instancing; @@ -730,7 +730,7 @@ struct GLRenderer::Impl { object->geometry()->hasAttribute("color") && object->geometry()->getAttribute("color")->itemSize() == 4; - auto materialProperties = properties.materialProperties.get(material->uuid()); + auto materialProperties = properties.materialProperties.get(material); auto& lights = currentRenderState->getLights(); if (_clippingEnabled) { @@ -1029,7 +1029,7 @@ struct GLRenderer::Impl { _currentActiveCubeFace = activeCubeFace; _currentActiveMipmapLevel = activeMipmapLevel; - if (renderTarget && !properties.renderTargetProperties.get(renderTarget->uuid)->glFramebuffer) { + if (renderTarget && !properties.renderTargetProperties.get(renderTarget)->glFramebuffer) { textures.setupRenderTarget(renderTarget); } @@ -1040,7 +1040,7 @@ struct GLRenderer::Impl { const auto& texture = renderTarget->texture; - framebuffer = *properties.renderTargetProperties.get(renderTarget->uuid)->glFramebuffer; + framebuffer = *properties.renderTargetProperties.get(renderTarget)->glFramebuffer; _currentViewport.copy(renderTarget->viewport); _currentScissor.copy(renderTarget->scissor); @@ -1356,7 +1356,7 @@ GLRenderTarget* threepp::GLRenderer::getRenderTarget() { return pimpl_->_currentRenderTarget; } -std::optional GLRenderer::getGlTextureId(const Texture& texture) const { +std::optional GLRenderer::getGlTextureId(Texture& texture) const { return pimpl_->getGlTextureId(texture); } diff --git a/src/threepp/renderers/gl/GLClipping.cpp b/src/threepp/renderers/gl/GLClipping.cpp index 0a1c78c0..4078d6d4 100644 --- a/src/threepp/renderers/gl/GLClipping.cpp +++ b/src/threepp/renderers/gl/GLClipping.cpp @@ -53,7 +53,7 @@ struct GLClipping::Impl { auto clipIntersection = material->clipIntersection; auto clipShadows = material->clipShadows; - auto materialProperties = properties.materialProperties.get(material->uuid()); + auto materialProperties = properties.materialProperties.get(material); if (!scope.localClippingEnabled || planes.empty() || scope.renderingShadows && !clipShadows) { diff --git a/src/threepp/renderers/gl/GLGeometries.cpp b/src/threepp/renderers/gl/GLGeometries.cpp index cbe62ff7..7431c2f6 100644 --- a/src/threepp/renderers/gl/GLGeometries.cpp +++ b/src/threepp/renderers/gl/GLGeometries.cpp @@ -192,6 +192,13 @@ struct GLGeometries::Impl { return wireframeAttributes_.at(geometry).get(); } + + ~Impl() { + + for (auto& [geom, _] : geometries_) { + geom->removeAllEventListeners("dispose"); + } + } }; diff --git a/src/threepp/renderers/gl/GLMaterials.cpp b/src/threepp/renderers/gl/GLMaterials.cpp index a8a013a2..3feec8a7 100644 --- a/src/threepp/renderers/gl/GLMaterials.cpp +++ b/src/threepp/renderers/gl/GLMaterials.cpp @@ -65,7 +65,7 @@ struct GLMaterials::Impl { uniforms.at("specularMap").setValue(specularMaterial->specularMap.get()); } - auto envMap = properties.materialProperties.get(material->uuid())->envMap; + auto envMap = properties.materialProperties.get(material)->envMap; if (envMap) { auto cubeTexture = dynamic_cast(envMap); @@ -79,7 +79,7 @@ struct GLMaterials::Impl { uniforms.at("refractionRatio").value() = reflectiveMaterial->refractionRatio; } - const auto maxMipMapLevel = properties.textureProperties.get(envMap->uuid)->maxMipLevel; + const auto maxMipMapLevel = properties.textureProperties.get(envMap)->maxMipLevel; if (maxMipMapLevel) { uniforms["maxMipLevel"].value() = *maxMipMapLevel; } @@ -258,7 +258,7 @@ struct GLMaterials::Impl { uniforms.at("displacementBias").value() = material->displacementBias; } - auto envMap = properties.materialProperties.get(material->uuid()); + auto envMap = properties.materialProperties.get(material); if (envMap) { uniforms["envMapIntensity"].value() = material->envMapIntensity; diff --git a/src/threepp/renderers/gl/GLProperties.hpp b/src/threepp/renderers/gl/GLProperties.hpp index f25c7f66..51dec748 100644 --- a/src/threepp/renderers/gl/GLProperties.hpp +++ b/src/threepp/renderers/gl/GLProperties.hpp @@ -7,6 +7,9 @@ #include "GLUniforms.hpp" #include "threepp/core/Uniform.hpp" +#include "threepp/materials/Material.hpp" +#include "threepp/renderers/GLRenderer.hpp" +#include "threepp/textures/Texture.hpp" #include #include @@ -60,15 +63,15 @@ namespace threepp::gl { unsigned int version{}; }; - template + template struct GLTypeProperties { - T* get(const std::string& key) { + T* get(E* key) { return &properties_[key]; } - void remove(const std::string& key) { + void remove(E* key) { properties_.erase(key); } @@ -79,17 +82,25 @@ namespace threepp::gl { } private: - std::unordered_map properties_; + friend struct GLProperties; + std::unordered_map properties_; }; struct GLProperties { - GLTypeProperties textureProperties; - GLTypeProperties materialProperties; - GLTypeProperties renderTargetProperties; + GLTypeProperties textureProperties; + GLTypeProperties materialProperties; + GLTypeProperties renderTargetProperties; void dispose() { + for (auto& [tex, _] : textureProperties.properties_) { + tex->removeAllEventListeners("dispose"); + } + for (auto& [mat, _] : materialProperties.properties_) { + mat->removeAllEventListeners("dispose"); + } + textureProperties.dispose(); materialProperties.dispose(); renderTargetProperties.dispose(); diff --git a/src/threepp/renderers/gl/GLRenderLists.cpp b/src/threepp/renderers/gl/GLRenderLists.cpp index 91f53bbe..3f85fed7 100644 --- a/src/threepp/renderers/gl/GLRenderLists.cpp +++ b/src/threepp/renderers/gl/GLRenderLists.cpp @@ -62,7 +62,7 @@ gl::RenderItem* gl::GLRenderList::getNextRenderItem( unsigned int groupOrder, float z, std::optional group) { gl::RenderItem* renderItem = nullptr; - auto materialProperties = properties.materialProperties.get(material->uuid()); + auto materialProperties = properties.materialProperties.get(material); if (renderItemsIndex >= renderItems.size()) { auto r = std::make_unique(RenderItem{object->id, diff --git a/src/threepp/renderers/gl/GLTextures.cpp b/src/threepp/renderers/gl/GLTextures.cpp index 0423e870..3e5f625f 100644 --- a/src/threepp/renderers/gl/GLTextures.cpp +++ b/src/threepp/renderers/gl/GLTextures.cpp @@ -90,11 +90,11 @@ gl::GLTextures::GLTextures(gl::GLState& state, gl::GLProperties& properties, gl: onTextureDispose_(this), onRenderTargetDispose_(this) {} -void gl::GLTextures::generateMipmap(GLuint target, const Texture& texture, GLuint width, GLuint height) { +void gl::GLTextures::generateMipmap(GLuint target, Texture& texture, GLuint width, GLuint height) { glGenerateMipmap(target); - auto textureProperties = properties->textureProperties.get(texture.uuid); + auto textureProperties = properties->textureProperties.get(&texture); textureProperties->maxMipLevel = static_cast(std::log2(std::max(width, height))); } @@ -220,13 +220,13 @@ void gl::GLTextures::deallocateTexture(Texture* texture) { if (!properties) return; - auto textureProperties = properties->textureProperties.get(texture->uuid); + auto textureProperties = properties->textureProperties.get(texture); if (!textureProperties->glInit) return; glDeleteTextures(1, &textureProperties->glTexture.value()); - properties->textureProperties.remove(texture->uuid); + properties->textureProperties.remove(texture); } void gl::GLTextures::deallocateRenderTarget(GLRenderTarget* renderTarget) { @@ -235,8 +235,8 @@ void gl::GLTextures::deallocateRenderTarget(GLRenderTarget* renderTarget) { const auto& texture = renderTarget->texture; - auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget->uuid); - const auto& textureProperties = properties->textureProperties.get(texture->uuid); + auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget); + const auto& textureProperties = properties->textureProperties.get(texture.get()); if (textureProperties->glTexture) { @@ -253,8 +253,8 @@ void gl::GLTextures::deallocateRenderTarget(GLRenderTarget* renderTarget) { glDeleteFramebuffers(1, &renderTargetProperties->glFramebuffer.value()); if (renderTargetProperties->glDepthbuffer) glDeleteRenderbuffers(1, &renderTargetProperties->glDepthbuffer.value()); - properties->textureProperties.remove(texture->uuid); - properties->renderTargetProperties.remove(renderTarget->uuid); + properties->textureProperties.remove(texture.get()); + properties->renderTargetProperties.remove(renderTarget); } void gl::GLTextures::resetTextureUnits() { @@ -278,7 +278,7 @@ int gl::GLTextures::allocateTextureUnit() { void gl::GLTextures::setTexture2D(Texture& texture, GLuint slot) { - auto textureProperties = properties->textureProperties.get(texture.uuid); + auto textureProperties = properties->textureProperties.get(&texture); if (texture.version() > 0 && textureProperties->version != texture.version()) { @@ -301,7 +301,7 @@ void gl::GLTextures::setTexture2D(Texture& texture, GLuint slot) { void gl::GLTextures::setTexture2DArray(Texture& texture, GLuint slot) { - auto textureProperties = properties->textureProperties.get(texture.uuid); + auto textureProperties = properties->textureProperties.get(&texture); if (texture.version() > 0 && textureProperties->version != texture.version()) { @@ -315,7 +315,7 @@ void gl::GLTextures::setTexture2DArray(Texture& texture, GLuint slot) { void gl::GLTextures::setTexture3D(Texture& texture, GLuint slot) { - auto textureProperties = properties->textureProperties.get(texture.uuid); + auto textureProperties = properties->textureProperties.get(&texture); if (texture.version() > 0 && textureProperties->version != texture.version()) { @@ -329,7 +329,7 @@ void gl::GLTextures::setTexture3D(Texture& texture, GLuint slot) { void gl::GLTextures::setTextureCube(Texture& texture, GLuint slot) { - auto textureProperties = properties->textureProperties.get(texture.uuid); + auto textureProperties = properties->textureProperties.get(&texture); if (texture.version() > 0 && textureProperties->version != texture.version()) { @@ -397,7 +397,7 @@ void gl::GLTextures::setupFrameBufferTexture( } state->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, textureTarget, *properties->textureProperties.get(texture.uuid)->glTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, textureTarget, *properties->textureProperties.get(&texture)->glTexture, 0); state->bindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -447,7 +447,7 @@ void gl::GLTextures::setupDepthTexture(unsigned int framebuffer, GLRenderTarget* } // upload an empty depth texture with framebuffer size - if (!properties->textureProperties.get(renderTarget->depthTexture->uuid)->glTexture || + if (!properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture || renderTarget->depthTexture->image.front().width != renderTarget->width || renderTarget->depthTexture->image.front().height != renderTarget->height) { @@ -458,7 +458,7 @@ void gl::GLTextures::setupDepthTexture(unsigned int framebuffer, GLRenderTarget* setTexture2D(*renderTarget->depthTexture, 0); - const auto glDepthTexture = properties->textureProperties.get(renderTarget->depthTexture->uuid)->glTexture; + const auto glDepthTexture = properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture; if (renderTarget->depthTexture->format == Format::Depth) { @@ -476,7 +476,7 @@ void gl::GLTextures::setupDepthTexture(unsigned int framebuffer, GLRenderTarget* void gl::GLTextures::setupDepthRenderbuffer(GLRenderTarget* renderTarget) { - auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget->uuid); + auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget); if (renderTarget->depthTexture) { @@ -498,8 +498,8 @@ void gl::GLTextures::setupRenderTarget(GLRenderTarget* renderTarget) { const auto& texture = renderTarget->texture; - auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget->uuid); - auto textureProperties = properties->textureProperties.get(texture->uuid); + auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget); + auto textureProperties = properties->textureProperties.get(texture.get()); renderTarget->addEventListener("dispose", &onRenderTargetDispose_); @@ -555,7 +555,7 @@ void gl::GLTextures::updateRenderTargetMipmap(GLRenderTarget* renderTarget) { if (textureNeedsGenerateMipmaps(*texture)) { const auto target = GL_TEXTURE_2D; - const auto glTexture = properties->textureProperties.get(texture->uuid)->glTexture; + const auto glTexture = properties->textureProperties.get(texture.get())->glTexture; state->bindTexture(target, *glTexture); generateMipmap(target, *texture, renderTarget->width, renderTarget->height); @@ -563,9 +563,9 @@ void gl::GLTextures::updateRenderTargetMipmap(GLRenderTarget* renderTarget) { } } -std::optional gl::GLTextures::getGlTexture(const Texture& texture) const { +std::optional gl::GLTextures::getGlTexture(Texture& texture) const { - const auto textureProperties = properties->textureProperties.get(texture.uuid); + const auto textureProperties = properties->textureProperties.get(&texture); return textureProperties->glTexture; } diff --git a/src/threepp/renderers/gl/GLTextures.hpp b/src/threepp/renderers/gl/GLTextures.hpp index 78705c5c..b04dae48 100644 --- a/src/threepp/renderers/gl/GLTextures.hpp +++ b/src/threepp/renderers/gl/GLTextures.hpp @@ -25,7 +25,7 @@ namespace threepp::gl { GLTextures(GLState& state, GLProperties& properties, GLInfo& info); - void generateMipmap(unsigned int target, const Texture& texture, unsigned int width, unsigned int height); + void generateMipmap(unsigned int target, Texture& texture, unsigned int width, unsigned int height); void setTextureParameters(unsigned int textureType, Texture& texture); @@ -67,7 +67,7 @@ namespace threepp::gl { void updateRenderTargetMipmap(GLRenderTarget* renderTarget); - [[nodiscard]] std::optional getGlTexture(const Texture& texture) const; + [[nodiscard]] std::optional getGlTexture(Texture& texture) const; private: struct TextureEventListener: EventListener {