Improvements to how Tome subviews manage Thang updates.

This commit is contained in:
Nick Winter 2014-02-05 15:16:59 -08:00
parent 323d3570ec
commit cec52d70f3
9 changed files with 47 additions and 21 deletions

View file

@ -248,6 +248,8 @@ module.exports = class SpriteBoss extends CocoClass
# Marks # Marks
updateSelection: -> updateSelection: ->
if @selectedSprite and (not @selectedSprite.thang.exists or not @world.getThangByID @selectedSprite.thang.id)
@selectSprite null, null, null
@updateTarget() @updateTarget()
return unless @selectionMark return unless @selectionMark
@selectionMark.toggle @selectedSprite? @selectionMark.toggle @selectedSprite?

View file

@ -223,7 +223,10 @@
.hud-hint .hud-hint
font-weight: normal font-weight: normal
color: #888888 color: #aaa
position: absolute
top: 0
right: 4px
.enter .enter
position: absolute position: absolute

View file

@ -163,7 +163,7 @@ module.exports = class HUDView extends View
else else
s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (press shift-space)") s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (press shift-space)")
if @shiftSpacePressed > 4 and not @escapePressed if @shiftSpacePressed > 4 and not @escapePressed
group.append('<span class="hud-hint">Press esc to skip dialog</span>') @bubble.append('<span class="hud-hint">skip: esc</span>')
group.append($('<button class="btn btn-small banner with-dot">' + s + ' <div class="dot"></div></button>')) group.append($('<button class="btn btn-small banner with-dot">' + s + ' <div class="dot"></div></button>'))
@lastResponses = null @lastResponses = null
@bubble.append($("<h3>#{@speaker ? 'Captain Anya'}</h3>")) @bubble.append($("<h3>#{@speaker ? 'Captain Anya'}</h3>"))

View file

@ -30,6 +30,9 @@ module.exports = class Spell
addThang: (thang) -> addThang: (thang) ->
@thangs[thang.id] ?= {thang: thang, aether: @createAether(thang), castAether: null} @thangs[thang.id] ?= {thang: thang, aether: @createAether(thang), castAether: null}
removeThangID: (thangID) ->
delete @thangs[thangID]
canRead: (team) -> canRead: (team) ->
(team ? me.team) in @permissions.read or (team ? me.team) in @permissions.readwrite (team ? me.team) in @permissions.read or (team ? me.team) in @permissions.readwrite

View file

@ -79,3 +79,11 @@ module.exports = class SpellListView extends View
addThang: (thang) -> addThang: (thang) ->
@sortSpells() @sortSpells()
@addSpellListEntries() @addSpellListEntries()
adjustSpells: (spells) ->
for entry in @entries when _.isEmpty entry.spell.thangs
entry.$el.remove()
entry.destroy()
@spells = @options.spells = spells
@sortSpells()
@addSpellListEntries()

View file

@ -377,11 +377,12 @@ module.exports = class SpellView extends View
@updateAether false, false @updateAether false, false
onNewWorld: (e) -> onNewWorld: (e) ->
@spell.removeThangID thangID for thangID of @spell.thangs when not e.world.getThangByID thangID
for thangID, spellThang of @spell.thangs for thangID, spellThang of @spell.thangs
aether = e.world.userCodeMap[thangID][@spell.name] thang = e.world.getThangByID(thangID)
#console.log thangID, "got new castAether with raw", aether.raw, "problems", aether.problems aether = e.world.userCodeMap[thangID]?[@spell.name] # Might not be there if this is a new Programmable Thang.
spellThang.castAether = aether spellThang.castAether = aether
spellThang.aether = @spell.createAether e.world.getThangByID(thangID) spellThang.aether = @spell.createAether thang
#console.log thangID, @spell.spellKey, "ran", aether.metrics.callsExecuted, "times over", aether.metrics.statementsExecuted, "statements, with max recursion depth", aether.metrics.maxDepth, "and full flow/metrics", aether.metrics, aether.flow #console.log thangID, @spell.spellKey, "ran", aether.metrics.callsExecuted, "times over", aether.metrics.statementsExecuted, "statements, with max recursion depth", aether.metrics.maxDepth, "and full flow/metrics", aether.metrics, aether.flow
@spell.transpile() @spell.transpile()
@updateAether false, false @updateAether false, false

View file

@ -46,6 +46,7 @@ module.exports = class ThangListEntryView extends View
@$el.append @avatar.el # Before rendering, so render can use parent for popover @$el.append @avatar.el # Before rendering, so render can use parent for popover
@avatar.render() @avatar.render()
@avatar.setSharedThangs @spells.length # A bit weird to call it sharedThangs; could refactor if we like this @avatar.setSharedThangs @spells.length # A bit weird to call it sharedThangs; could refactor if we like this
@$el.toggle Boolean(@thang.exists)
@$el.popover( @$el.popover(
animation: false animation: false
html: true html: true

View file

@ -72,7 +72,11 @@ module.exports = class ThangListView extends View
return entry.spells[0] return entry.spells[0]
null null
addThang: (thang) -> adjustThangs: (spells, thangs, toRemove, toAdd) ->
@thangs.push thang for entry in @entries when _.find toRemove, {id: entry.thang.id}
entry.$el.remove()
entry.destroy()
@spells = @options.spells = spells
@thangs = @options.thangs = _.filter thangs, 'isSelectable'
@sortThangs() @sortThangs()
@addThangListEntries [thang] @addThangListEntries toAdd

View file

@ -47,7 +47,7 @@ module.exports = class TomeView extends View
'tome:cast-spell': "onCastSpell" 'tome:cast-spell': "onCastSpell"
'tome:toggle-spell-list': 'onToggleSpellList' 'tome:toggle-spell-list': 'onToggleSpellList'
'surface:sprite-selected': 'onSpriteSelected' 'surface:sprite-selected': 'onSpriteSelected'
'surface:new-thang-added': 'onNewThangAdded' 'god:new-world-created': 'onNewWorld'
events: events:
'click #spell-view': 'onSpellViewClick' 'click #spell-view': 'onSpellViewClick'
@ -58,7 +58,7 @@ module.exports = class TomeView extends View
programmableThangs = _.filter @options.thangs, 'isProgrammable' programmableThangs = _.filter @options.thangs, 'isProgrammable'
if programmableThangs.length if programmableThangs.length
@createSpells programmableThangs # Do before spellList, thangList, and castButton @createSpells programmableThangs, programmableThangs[0].world # Do before spellList, thangList, and castButton
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel @spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel
@thangList = @insertSubView new ThangListView spells: @spells, thangs: @options.thangs, supermodel: @supermodel @thangList = @insertSubView new ThangListView spells: @spells, thangs: @options.thangs, supermodel: @supermodel
@castButton = @insertSubView new CastButtonView spells: @spells @castButton = @insertSubView new CastButtonView spells: @spells
@ -66,20 +66,20 @@ module.exports = class TomeView extends View
@cast() @cast()
console.log "Warning: There are no Programmable Thangs in this level, which makes it unplayable." console.log "Warning: There are no Programmable Thangs in this level, which makes it unplayable."
onNewThangAdded: (e) -> onNewWorld: (e) ->
return unless e.thang.isProgrammable and not _.find @thangList.thangs, id: e.thang.id oldThangs = @thangList.thangs
@createSpells [e.thang] newThangs = e.world.thangs
@spellList.addThang e.thang toRemove = (thang for thang in oldThangs when not e.world.getThangByID thang.id)
@thangList.addThang e.thang toAdd = (thang for thang in newThangs when not _.find oldThangs, id: thang.id)
@createSpells toAdd, e.world
@thangList.adjustThangs @spells, newThangs, toRemove, toAdd
@spellList.adjustSpells @spells
createSpells: (programmableThangs) -> createSpells: (programmableThangs, world) ->
# If needed, we could make this able to update when programmableThangs changes.
# We haven't done that yet, so call it just once on init.
pathPrefixComponents = ['play', 'level', @options.levelID, @options.session.id, 'code'] pathPrefixComponents = ['play', 'level', @options.levelID, @options.session.id, 'code']
@spells ?= {} @spells ?= {}
@thangSpells ?= {} @thangSpells ?= {}
for thang in programmableThangs for thang in programmableThangs
world = thang.world
continue if @thangSpells[thang.id]? continue if @thangSpells[thang.id]?
@thangSpells[thang.id] = [] @thangSpells[thang.id] = []
for methodName, method of thang.programmableMethods for methodName, method of thang.programmableMethods
@ -92,8 +92,12 @@ module.exports = class TomeView extends View
unless method.cloneOf unless method.cloneOf
spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: @getQueryVariable("skip_flow") is "true", skipProtectAPI: @getQueryVariable("skip_protect_api") is "true" spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: @getQueryVariable("skip_flow") is "true", skipProtectAPI: @getQueryVariable("skip_protect_api") is "true"
for thangID, spellKeys of @thangSpells for thangID, spellKeys of @thangSpells
thang = world.getThangByID(thangID) thang = world.getThangByID thangID
@spells[spellKey].addThang thang for spellKey in spellKeys if thang
@spells[spellKey].addThang thang for spellKey in spellKeys
else
delete @thangSpells[thangID]
@spells[spellKey].removeThangID thangID for spellKey in spellKeys
null null
onSpellLoaded: (e) -> onSpellLoaded: (e) ->