From 60d68ca23cce74b164bdafeb299344fc5a6851fb Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Mon, 2 Feb 2015 18:02:57 -0800 Subject: [PATCH] Fixed some memory leaks and particle disposal problems. Re-enabled particles. Tweaked particle stylings. --- app/core/ParticleMan.coffee | 73 +++++++++++++++---- app/models/User.coffee | 1 - app/styles/play/campaign-view.sass | 4 +- app/templates/play/campaign-view.jade | 4 +- app/views/core/AchievementPopup.coffee | 2 +- app/views/core/CocoView.coffee | 2 +- .../editor/level/thangs/AddThangsView.coffee | 2 +- app/views/play/CampaignView.coffee | 6 +- app/views/play/level/tome/SpellView.coffee | 1 + app/views/play/modal/PlayHeroesModal.coffee | 4 +- 10 files changed, 73 insertions(+), 26 deletions(-) diff --git a/app/core/ParticleMan.coffee b/app/core/ParticleMan.coffee index f54c02cd9..4df18a3df 100644 --- a/app/core/ParticleMan.coffee +++ b/app/core/ParticleMan.coffee @@ -13,14 +13,24 @@ module.exports = ParticleMan = class ParticleMan extends CocoClass destroy: -> @detach() - # TODO: figure out how to dispose everything - # scene.remove(mesh) - # mesh.dispose() - # geometry.dispose() - # material.dispose() - # texture.dispose() + @disposeObject3D @scene + for child in @scene?.children?.slice() or [] + @scene.remove child super() + disposeObject3D: (obj) -> + return unless obj + @disposeObject3D child for child in obj.children + obj.geometry?.dispose() + obj.geometry = undefined + if obj.material + material.dispose() for material in obj.material.materials ? [] + obj.material.dispose() + obj.material = undefined + if obj.texture + obj.texture.dispose() + obj.texture = undefined + attach: (@$el) -> return if @unsupported width = @$el.innerWidth() @@ -71,7 +81,6 @@ module.exports = ParticleMan = class ParticleMan extends CocoClass addEmitter: (x, y, kind="level-dungeon-premium") -> return if @unsupported - console.log 'adding kind', kind options = $.extend true, {}, particleKinds[kind] options.group.texture = THREE.ImageUtils.loadTexture "/images/common/particles/#{options.group.texture}.png" scale = 100 @@ -93,7 +102,7 @@ module.exports = ParticleMan = class ParticleMan extends CocoClass removeEmitters: -> return if @unsupported @removeEmitter group for group in @particleGroups.slice() - + #addTestCube: -> #geometry = new THREE.BoxGeometry 5, 5, 5 #material = new THREE.MeshLambertMaterial color: 0xFF0000 @@ -181,10 +190,19 @@ particleKinds = colorMiddle: hsl 0.56, 0.57, 0.5 colorEnd: hsl 0.56, 0.17, 0.5 +particleKinds['level-dungeon-premium-hero'] = ext particleKinds['level-dungeon-premium'], + emitter: + particleCount: 200 + radius: 1.5 + acceleration: vec 0, 4, 0 + opacityStart: 0.25 + opacityMiddle: 0.5 + opacityEnd: 0.75 + particleKinds['level-dungeon-gate'] = ext particleKinds['level-dungeon-premium'], emitter: - particleCount: 120 - velocity: vec 0, 6, 0 + particleCount: 2000 + acceleration: vec 0, 8, 0 colorStart: hsl 0.5, 0.75, 0.9 colorMiddle: hsl 0.5, 0.75, 0.7 colorEnd: hsl 0.5, 0.75, 0.3 @@ -194,12 +212,21 @@ particleKinds['level-dungeon-gate'] = ext particleKinds['level-dungeon-premium'] particleKinds['level-dungeon-hero-ladder'] = ext particleKinds['level-dungeon-premium'], emitter: - particleCount: 90 - velocity: vec 0, 4, 0 + particleCount: 200 + acceleration: vec 0, 3, 0 colorStart: hsl 0, 0.75, 0.7 colorMiddle: hsl 0, 0.75, 0.5 colorEnd: hsl 0, 0.75, 0.3 +particleKinds['level-forest-premium-hero'] = ext particleKinds['level-forest-premium'], + emitter: + particleCount: 200 + radius: 1.5 + acceleration: vec 0, 4, 0 + opacityStart: 0.25 + opacityMiddle: 0.5 + opacityEnd: 0.75 + particleKinds['level-forest-gate'] = ext particleKinds['level-forest-premium'], emitter: particleCount: 120 @@ -219,6 +246,15 @@ particleKinds['level-forest-hero-ladder'] = ext particleKinds['level-forest-prem colorMiddle: hsl 0, 1, 0.5 colorEnd: hsl 0, 0.75, 0.1 +particleKinds['level-desert-premium-hero'] = ext particleKinds['level-desert-premium'], + emitter: + particleCount: 200 + radius: 1.5 + acceleration: vec 0, 4, 0 + opacityStart: 0.25 + opacityMiddle: 0.5 + opacityEnd: 0.75 + particleKinds['level-desert-gate'] = ext particleKinds['level-desert-premium'], emitter: particleCount: 120 @@ -238,7 +274,16 @@ particleKinds['level-desert-hero-ladder'] = ext particleKinds['level-desert-prem colorMiddle: hsl 0, 1, 0.5 colorEnd: hsl 0, 0.75, 0.1 -particleKinds['level-dungeon-gate'] = ext particleKinds['level-dungeon-premium'], +particleKinds['level-mountain-premium-hero'] = ext particleKinds['level-mountain-premium'], + emitter: + particleCount: 200 + radius: 1.5 + acceleration: vec 0, 4, 0 + opacityStart: 0.25 + opacityMiddle: 0.5 + opacityEnd: 0.75 + +particleKinds['level-mountain-gate'] = ext particleKinds['level-mountain-premium'], emitter: particleCount: 120 velocity: vec 0, 8, 0 @@ -249,7 +294,7 @@ particleKinds['level-dungeon-gate'] = ext particleKinds['level-dungeon-premium'] colorMiddleSpread: vec 1.5, 1.5, 1.5 colorEndSpread: vec 2.5, 2.5, 2.5 -particleKinds['level-dungeon-hero-ladder'] = ext particleKinds['level-dungeon-premium'], +particleKinds['level-mountain-hero-ladder'] = ext particleKinds['level-mountain-premium'], emitter: particleCount: 90 velocity: vec 0, 4, 0 diff --git a/app/models/User.coffee b/app/models/User.coffee index fcadc0f04..2dcc1dcc6 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -125,7 +125,6 @@ module.exports = class User extends CocoModel getForeshadowsLevels: -> return @foreshadowsLevels if @foreshadowsLevels? - return false # bad performance problems, reenable later group = me.get('testGroupNumber') % 16 @foreshadowsLevels = switch group when 0, 1, 2, 3, 4, 5, 6, 7 then true diff --git a/app/styles/play/campaign-view.sass b/app/styles/play/campaign-view.sass index 915da4bd8..aff7eb023 100644 --- a/app/styles/play/campaign-view.sass +++ b/app/styles/play/campaign-view.sass @@ -145,9 +145,9 @@ $gameControlMargin: 30px border-radius: 50% background: white width: $levelDotWidth * 1.5 - height: $levelDotHeight * 1.5 + height: $levelDotHeight * 1.5 / 1.75 margin-left: -0.5 * $levelDotWidth * 1.5 - margin-bottom: -$levelDotHeight / 3 * 1.5 + margin-bottom: -$levelDotHeight / 3 * 1.5 / 1.75 .level-shadow z-index: 1 diff --git a/app/templates/play/campaign-view.jade b/app/templates/play/campaign-view.jade index 98a11ce44..04c15f475 100644 --- a/app/templates/play/campaign-view.jade +++ b/app/templates/play/campaign-view.jade @@ -7,7 +7,7 @@ each level in levels if !level.hidden - div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + levelStatusMap[level.slug] || "", data-level-slug=level.slug, data-level-original=level.original, title=i18n(level, 'name') + (level.disabled ? ' (Coming Soon to Adventurers)' : '')) + div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + (levelStatusMap[level.slug] || ""), data-level-slug=level.slug, data-level-original=level.original, title=i18n(level, 'name') + (level.disabled ? ' (Coming Soon to Adventurers)' : '')) if level.unlocksHero && (!level.purchasedHero || editorMode) img.hero-portrait(src="/file/db/thang.type/#{level.unlocksHero}/portrait.png") a(href=level.type == 'hero' ? '#' : level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.slug}", disabled=level.disabled, data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name) @@ -17,7 +17,7 @@ img.banner(src="/images/pages/play/level-banner-complete.png") if levelStatusMap[level.slug] === 'started' img.banner(src="/images/pages/play/level-banner-started.png") - div(style="left: #{level.position.x}%; bottom: #{level.position.y}%", class="level-shadow" + (level.next ? " next" : "") + " " + levelStatusMap[level.slug] || "") + div(style="left: #{level.position.x}%; bottom: #{level.position.y}%", class="level-shadow" + (level.next ? " next" : "") + " " + (levelStatusMap[level.slug] || "")) .level-info-container(data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name) div(class="level-info " + (levelStatusMap[level.slug] || "")) h3= i18n(level, 'name') + (level.disabled ? " (Coming soon!)" : (level.locked ? " (Locked)" : "")) diff --git a/app/views/core/AchievementPopup.coffee b/app/views/core/AchievementPopup.coffee index 9cc75e34b..4d0b2036d 100644 --- a/app/views/core/AchievementPopup.coffee +++ b/app/views/core/AchievementPopup.coffee @@ -85,4 +85,4 @@ module.exports = class AchievementPopup extends CocoView _.delay @initializeTooltips, 1000 # TODO this could be smoother initializeTooltips: -> - $('.progress-bar').tooltip() + $('.progress-bar').addClass('has-tooltip').tooltip() diff --git a/app/views/core/CocoView.coffee b/app/views/core/CocoView.coffee index 2d2491d73..73835d28e 100644 --- a/app/views/core/CocoView.coffee +++ b/app/views/core/CocoView.coffee @@ -60,7 +60,7 @@ module.exports = class CocoView extends Backbone.View @undelegateEvents() # removes both events and subs view.destroy() for id, view of @subviews $('#modal-wrapper .modal').off 'hidden.bs.modal', @modalClosed - @$el.find('[data-original-title]').tooltip 'destroy' + @$el.find('.has-tooltip, [data-original-title]').tooltip 'destroy' @endHighlight() @getPointer(false).remove() @[key] = undefined for key, value of @ diff --git a/app/views/editor/level/thangs/AddThangsView.coffee b/app/views/editor/level/thangs/AddThangsView.coffee index be00f3f37..cdc50db1e 100644 --- a/app/views/editor/level/thangs/AddThangsView.coffee +++ b/app/views/editor/level/thangs/AddThangsView.coffee @@ -62,7 +62,7 @@ module.exports = class AddThangsView extends CocoView @buildAddThangPopovers() buildAddThangPopovers: -> - @$el.find('#thangs-list .add-thang-palette-icon').tooltip(container: 'body', animation: false) + @$el.find('#thangs-list .add-thang-palette-icon').addClass('has-tooltip').tooltip(container: 'body', animation: false) runSearch: (e) => if e?.which is 27 diff --git a/app/views/play/CampaignView.coffee b/app/views/play/CampaignView.coffee index 4d373aff5..b9c8a9a7c 100644 --- a/app/views/play/CampaignView.coffee +++ b/app/views/play/CampaignView.coffee @@ -100,6 +100,7 @@ module.exports = class CampaignView extends RootView createjs.Tween.get(ambientSound).to({volume: 0.0}, 1500).call -> ambientSound.stop() @musicPlayer?.destroy() clearTimeout @playMusicTimeout + @particleMan?.destroy() super() getLevelPlayCounts: -> @@ -186,9 +187,9 @@ module.exports = class CampaignView extends RootView super() @onWindowResize() unless application.isIPadApp - _.defer => @$el?.find('.game-controls .btn').tooltip() # Have to defer or i18n doesn't take effect. + _.defer => @$el?.find('.game-controls .btn').addClass('has-tooltip').tooltip() # Have to defer or i18n doesn't take effect. view = @ - @$el.find('.level, .campaign-switch').tooltip().each -> + @$el.find('.level, .campaign-switch').addClass('has-tooltip').tooltip().each -> return unless me.isAdmin() $(@).draggable().on 'dragstop', -> bg = $('.map-background') @@ -275,6 +276,7 @@ module.exports = class CampaignView extends RootView particleKey.push level.type if level.type and level.type isnt 'hero' particleKey.push 'premium' if level.requiresSubscription particleKey.push 'gate' if level.slug in ['kithgard-gates', 'siege-of-stonehold', 'clash-of-clones'] + particleKey.push 'hero' if level.unlocksHero and not level.unlockedHero continue if particleKey.length is 2 # Don't show basic levels @particleMan.addEmitter level.position.x / 100, level.position.y / 100, particleKey.join('-') diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index 57a81c996..e70be5443 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -1093,5 +1093,6 @@ module.exports = class SpellView extends CocoView @aceSession?.selection.off 'changeCursor', @onCursorActivity @destroyAceEditor(@ace) @debugView?.destroy() + @toolbarView?.destroy() $(window).off 'resize', @onWindowResize super() diff --git a/app/views/play/modal/PlayHeroesModal.coffee b/app/views/play/modal/PlayHeroesModal.coffee index 539b0d898..17218c71f 100644 --- a/app/views/play/modal/PlayHeroesModal.coffee +++ b/app/views/play/modal/PlayHeroesModal.coffee @@ -82,14 +82,14 @@ module.exports = class PlayHeroesModal extends ModalView @$el.find('.hero-indicator').each -> heroID = $(@).data('hero-id') hero = _.find heroes, (hero) -> hero.get('original') is heroID - $(@).find('.hero-avatar').css('background-image', "url(#{hero.getPortraitURL()})").tooltip() + $(@).find('.hero-avatar').css('background-image', "url(#{hero.getPortraitURL()})").addClass('has-tooltip').tooltip() @canvasWidth = 313 # @$el.find('canvas').width() # unreliable, whatever @canvasHeight = @$el.find('canvas').height() heroConfig = @options?.session?.get('heroConfig') ? me.get('heroConfig') ? {} heroIndex = Math.max 0, _.findIndex(heroes, ((hero) -> hero.get('original') is heroConfig.thangType)) @$el.find(".hero-item:nth-child(#{heroIndex + 1}), .hero-indicator:nth-child(#{heroIndex + 1})").addClass('active') @onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[heroIndex] - @$el.find('.hero-stat').tooltip() + @$el.find('.hero-stat').addClass('has-tooltip').tooltip() @buildCodeLanguages() rerenderFooter: ->