mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Merged conflicts.
This commit is contained in:
commit
5af1741333
17 changed files with 172 additions and 57 deletions
|
@ -202,7 +202,7 @@ module.exports = class LevelLoader extends CocoClass
|
|||
thangsToLoad = _.uniq( (t.spriteName for t in @world.thangs when t.exists) )
|
||||
nameModelTuples = ([thangType.get('name'), thangType] for thangType in @thangNames.models)
|
||||
nameModelMap = _.zipObject nameModelTuples
|
||||
@spriteSheetsToBuild = []
|
||||
@spriteSheetsToBuild ?= []
|
||||
|
||||
for thangTypeName in thangsToLoad
|
||||
thangType = nameModelMap[thangTypeName]
|
||||
|
@ -230,7 +230,7 @@ module.exports = class LevelLoader extends CocoClass
|
|||
|
||||
buildLoop: =>
|
||||
someLeft = false
|
||||
for spriteSheetResource, i in @spriteSheetsToBuild
|
||||
for spriteSheetResource, i in @spriteSheetsToBuild ? []
|
||||
continue if spriteSheetResource.spriteSheetKeys
|
||||
someLeft = true
|
||||
thangType = spriteSheetResource.thangType
|
||||
|
|
|
@ -78,9 +78,20 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@handledDisplayEvents = {}
|
||||
@age = 0
|
||||
@stillLoading = true
|
||||
<<<<<<< HEAD
|
||||
if @thangType.isFullyLoaded() then @onThangTypeLoaded() else @listenToOnce(@thangType, 'sync', @onThangTypeLoaded)
|
||||
|
||||
toString: -> "<CocoSprite: #{@thang?.id}>"
|
||||
=======
|
||||
@setNameLabel @thang.id if @thang?.showsName and not @thang.health <= 0
|
||||
if @thangType.isFullyLoaded()
|
||||
@setUpSprite()
|
||||
else
|
||||
@thangType.setProjection null
|
||||
@thangType.fetch() unless @thangType.loading
|
||||
@listenToOnce(@thangType, 'sync', @setUpSprite)
|
||||
@setUpPlaceholder()
|
||||
>>>>>>> master
|
||||
|
||||
onThangTypeLoaded: ->
|
||||
@stillLoading = false
|
||||
|
@ -438,6 +449,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
rotation = @getRotation()
|
||||
if relatedActions['111111111111'] # has grid-surrounding-wall-based actions
|
||||
if @wallGrid
|
||||
@hadWallGrid = true
|
||||
action = ''
|
||||
tileSize = 4
|
||||
[gx, gy] = [@thang.pos.x, @thang.pos.y]
|
||||
|
@ -464,6 +476,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
break
|
||||
#console.log 'returning', matchedAction, 'for', @thang.id, 'at', gx, gy
|
||||
return relatedActions[matchedAction]
|
||||
else if @hadWallGrid
|
||||
return null
|
||||
else
|
||||
keys = _.keys relatedActions
|
||||
index = Math.max 0, Math.floor((179 + rotation) / 360 * keys.length)
|
||||
|
@ -477,13 +491,15 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
relatedActions[direction]
|
||||
|
||||
updateStats: ->
|
||||
return unless @thang and @thang.health isnt @lastHealth
|
||||
@lastHealth = @thang.health
|
||||
if bar = @healthBar
|
||||
return if @thang.health is @lastHealth
|
||||
@lastHealth = @thang.health
|
||||
healthPct = Math.max(@thang.health / @thang.maxHealth, 0)
|
||||
bar.scaleX = healthPct / bar.baseScale
|
||||
healthOffset = @getOffset 'aboveHead'
|
||||
[bar.x, bar.y] = [healthOffset.x - bar.width / 2, healthOffset.y]
|
||||
if @thang.showsName
|
||||
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
|
||||
|
||||
configureMouse: ->
|
||||
@imageObject.cursor = 'pointer' if @thang?.isSelectable
|
||||
|
|
|
@ -22,7 +22,7 @@ module.exports = class RegionChooser extends CocoClass
|
|||
onMouseMove: (e) =>
|
||||
return unless @firstPoint
|
||||
@secondPoint = @options.camera.screenToWorld {x: e.stageX, y: e.stageY}
|
||||
@restrictRegion() if @options.restrictRatio
|
||||
@restrictRegion() if @options.restrictRatio or key.alt
|
||||
@updateShape()
|
||||
|
||||
onMouseUp: (e) =>
|
||||
|
|
|
@ -185,12 +185,17 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
@adjustSpriteExistence() if frameChanged
|
||||
sprite.update frameChanged for sprite in @spriteArray
|
||||
@updateSelection()
|
||||
<<<<<<< HEAD
|
||||
@spriteLayers['Default'].spriteContainer.updateLayerOrder()
|
||||
@cache()
|
||||
=======
|
||||
@spriteLayers['Default'].updateLayerOrder()
|
||||
@cacheObstacles()
|
||||
>>>>>>> master
|
||||
|
||||
adjustSpriteExistence: ->
|
||||
# Add anything new, remove anything old, update everything current
|
||||
updateCache = false
|
||||
updatedObstacles = []
|
||||
itemsJustEquipped = []
|
||||
for thang in @world.thangs when thang.exists and thang.pos
|
||||
itemsJustEquipped = itemsJustEquipped.concat @equipNewItems thang
|
||||
|
@ -199,16 +204,16 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
else
|
||||
sprite = @addThangToSprites(thang)
|
||||
Backbone.Mediator.publish 'surface:new-thang-added', thang: thang, sprite: sprite
|
||||
updateCache = updateCache or sprite.imageObject.parent is @spriteLayers['Obstacle']
|
||||
updatedObstacles.push sprite if sprite.imageObject.parent is @spriteLayers['Obstacle']
|
||||
sprite.playSounds()
|
||||
item.modifyStats() for item in itemsJustEquipped
|
||||
for thangID, sprite of @sprites
|
||||
missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists)
|
||||
isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle']
|
||||
updateCache = updateCache or (isObstacle and (missing or sprite.hasMoved))
|
||||
updatedObstacles.push sprite if isObstacle and (missing or sprite.hasMoved)
|
||||
sprite.hasMoved = false
|
||||
@removeSprite sprite if missing
|
||||
@cache true if updateCache and @cached
|
||||
@cacheObstacles updatedObstacles if updatedObstacles.length and @cachedObstacles
|
||||
|
||||
# mainly for handling selecting thangs from session when the thang is not always in existence
|
||||
if @willSelectThang and @sprites[@willSelectThang[0]]
|
||||
|
@ -229,8 +234,31 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
itemsJustEquipped.push item
|
||||
return itemsJustEquipped
|
||||
|
||||
<<<<<<< HEAD
|
||||
cache: (update=false) ->
|
||||
# TODO: remove caching
|
||||
=======
|
||||
cacheObstacles: (updatedObstacles=null) ->
|
||||
return if @cachedObstacles and not updatedObstacles
|
||||
wallSprites = (sprite for sprite in @spriteArray when sprite.thangType?.get('name').search(/(dungeon|indoor).wall/i) isnt -1)
|
||||
return if _.any (s.stillLoading for s in wallSprites)
|
||||
walls = (sprite.thang for sprite in wallSprites)
|
||||
@world.calculateBounds()
|
||||
wallGrid = new Grid walls, @world.size()...
|
||||
if updatedObstacles
|
||||
possiblyUpdatedWallSprites = (sprite for sprite in wallSprites when _.find updatedObstacles, (w2) -> sprite is w2 or (Math.abs(sprite.thang.pos.x - w2.thang.pos.x) + Math.abs(sprite.thang.pos.y - w2.thang.pos.y)) <= 16)
|
||||
else
|
||||
possiblyUpdatedWallSprites = wallSprites
|
||||
#console.log 'updating up to', possiblyUpdatedWallSprites.length, 'of', wallSprites.length, 'wall sprites from updatedObstacles', updatedObstacles
|
||||
for wallSprite in possiblyUpdatedWallSprites
|
||||
wallSprite.updateActionDirection wallGrid
|
||||
wallSprite.updateScale()
|
||||
wallSprite.updatePosition()
|
||||
#console.log @wallGrid.toString()
|
||||
@spriteLayers['Obstacle'].uncache() if @spriteLayers['Obstacle'].cacheID # might have changed sizes
|
||||
@spriteLayers['Obstacle'].cache()
|
||||
@cachedObstacles = true
|
||||
>>>>>>> master
|
||||
|
||||
spriteFor: (thangID) -> @sprites[thangID]
|
||||
|
||||
|
|
|
@ -488,7 +488,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
#- Canvas callbacks
|
||||
|
||||
onResize: (e) =>
|
||||
return if @destroyed
|
||||
return if @destroyed or @options.choosing
|
||||
oldWidth = parseInt @canvas.attr('width'), 10
|
||||
oldHeight = parseInt @canvas.attr('height'), 10
|
||||
aspectRatio = oldWidth / oldHeight
|
||||
|
|
|
@ -139,7 +139,7 @@ module.exports = class GoalManager extends CocoClass
|
|||
@initGoalState(state, [[], keepFrom.keepFromLocation?.who], 'arrived')
|
||||
@initGoalState(state, [goal.getToLocations?.who, goal.keepFromLocations?.who], 'arrived')
|
||||
@initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left')
|
||||
@initGoalState(state, [goal.collectThangs?.who, goal.keepFromCollectingThangs?.who], 'collected')
|
||||
@initGoalState(state, [goal.collectThangs?.targets, goal.keepFromCollectingThangs?.targets], 'collected')
|
||||
@goalStates[goal.id] = state
|
||||
|
||||
onThangDied: (e, frameNumber) ->
|
||||
|
@ -169,23 +169,23 @@ module.exports = class GoalManager extends CocoClass
|
|||
|
||||
onThangLeftMap: (e, frameNumber) ->
|
||||
for goal in @goals ? []
|
||||
@checkLeft(goal.id, goal.leaveOffSides.who, goal.leaveOffSides.sides, e.thang.id, e.side, frameNumber) if goal.leaveOffSides?
|
||||
@checkLeft(goal.id, goal.keepFromLeavingOffSides.who, goal.keepFromLeavingOffSides.sides, e.thang.id, e.side, frameNumber) if goal.keepFromLeavingOffSides?
|
||||
@checkLeft(goal.id, goal.leaveOffSides.who, goal.leaveOffSides.sides, e.thang, e.side, frameNumber) if goal.leaveOffSides?
|
||||
@checkLeft(goal.id, goal.keepFromLeavingOffSides.who, goal.keepFromLeavingOffSides.sides, e.thang, e.side, frameNumber) if goal.keepFromLeavingOffSides?
|
||||
|
||||
checkLeft: (goalID, who, sides, thangID, side, frameNumber) ->
|
||||
checkLeft: (goalID, who, sides, thang, side, frameNumber) ->
|
||||
return if sides and side and not (side in sides)
|
||||
return unless thangID in who
|
||||
@updateGoalState(goalID, thangID, 'left', frameNumber)
|
||||
return unless thang.id in who or thang.team in who
|
||||
@updateGoalState(goalID, thang.id, 'left', frameNumber)
|
||||
|
||||
onThangCollectedItem: (e, frameNumber) ->
|
||||
for goal in @goals ? []
|
||||
@checkCollected(goal.id, goal.collectThangs.who, goal.collectThangs.targets, e.actor.id, e.item.id, frameNumber) if goal.collectThangs?
|
||||
@checkCollected(goal.id, goal.keepFromCollectingThangs.who, goal.keepFromCollectingThangs.targets, e.actor.id, e.item.id, frameNumber) if goal.keepFromCollectingThangs?
|
||||
@checkCollected(goal.id, goal.collectThangs.who, goal.collectThangs.targets, e.actor, e.item.id, frameNumber) if goal.collectThangs?
|
||||
@checkCollected(goal.id, goal.keepFromCollectingThangs.who, goal.keepFromCollectingThangs.targets, e.actor, e.item.id, frameNumber) if goal.keepFromCollectingThangs?
|
||||
|
||||
checkCollected: (goalID, who, targets, thangID, itemID, frameNumber) ->
|
||||
checkCollected: (goalID, who, targets, thang, itemID, frameNumber) ->
|
||||
return unless itemID in targets
|
||||
return unless thangID in who
|
||||
@updateGoalState(goalID, thangID, 'collected', frameNumber)
|
||||
return unless thang.id in who or thang.team in who
|
||||
@updateGoalState(goalID, itemID, 'collected', frameNumber)
|
||||
|
||||
wrapUpGoalStates: (finalFrame) ->
|
||||
for goalID, state of @goalStates
|
||||
|
|
|
@ -62,7 +62,7 @@ class CocoModel extends Backbone.Model
|
|||
super(attribute)
|
||||
|
||||
set: (attributes, options) ->
|
||||
delete @attributesWithDefaults
|
||||
delete @attributesWithDefaults unless attributes is 'thangs' # unless attributes is 'thangs': performance optimization for Levels keeping their cache.
|
||||
inFlux = @loading or not @loaded
|
||||
@markToRevert() unless inFlux or @_revertAttributes or @project or options?.fromMerge
|
||||
res = super attributes, options
|
||||
|
@ -125,8 +125,12 @@ class CocoModel extends Backbone.Model
|
|||
error(@, res) if error
|
||||
return unless @notyErrors
|
||||
errorMessage = "Error saving #{@get('name') ? @type()}"
|
||||
console.error errorMessage, res.responseJSON
|
||||
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
|
||||
console.log 'going to log an error message'
|
||||
console.warn errorMessage, res.responseJSON
|
||||
try
|
||||
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
|
||||
catch notyError
|
||||
console.warn "Couldn't even show noty error for", error, "because", notyError
|
||||
@trigger 'save', @
|
||||
return super attrs, options
|
||||
|
||||
|
|
|
@ -128,19 +128,27 @@ module.exports = class Level extends CocoModel
|
|||
# Here we have to sort the Components by their dependencies.
|
||||
# It's a bit tricky though, because we don't have either soft dependencies or priority levels.
|
||||
# Example: Programmable must come last, since it has to override any Component-provided methods that any other Component might have created. Can't enumerate all soft dependencies.
|
||||
# Example: Plans needs to come after everything except Programmable, since other Components that add plannable methods need to have done so by the time Plans is attached.
|
||||
# Example: Collides doesn't depend on Allied, but if both exist, Collides must come after Allied. Soft dependency example. Can't just figure out a proper priority to take care of it.
|
||||
# Decision? Just special case the sort logic in here until we have more examples than these two and decide how best to handle most of the cases then, since we don't really know the whole of the problem yet.
|
||||
# TODO: anything that depends on Programmable will break right now.
|
||||
|
||||
for thang in thangs ? []
|
||||
programmableLevelComponent = null
|
||||
plansLevelComponent = null
|
||||
sorted = []
|
||||
visit = (c) ->
|
||||
return if c in sorted
|
||||
lc = _.find levelComponents, {original: c.original}
|
||||
console.error thang.id or thang.name, 'couldn\'t find lc for', c, 'of', levelComponents unless lc
|
||||
return unless lc
|
||||
if lc.name is 'Programmable'
|
||||
if lc.name is 'Plans'
|
||||
# Plans always comes second-to-last, behind Programmable
|
||||
plansLevelComponent = c
|
||||
visit c2 for c2 in _.without thang.components, c, programmableLevelComponent
|
||||
else if lc.name is 'Programmable'
|
||||
# Programmable always comes last
|
||||
programmableLevelComponent = c
|
||||
visit c2 for c2 in _.without thang.components, c
|
||||
else
|
||||
for d in lc.dependencies or []
|
||||
|
@ -162,14 +170,31 @@ module.exports = class Level extends CocoModel
|
|||
thang.components = sorted
|
||||
|
||||
fillInDefaultComponentConfiguration: (thangs, levelComponents) ->
|
||||
# This is slow, so I inserted some optimizations to speed it up by caching the eventual defaults of commonly-used Components.
|
||||
@defaultComponentConfigurations ?= {}
|
||||
cached = 0
|
||||
missed = 0
|
||||
cachedConfigs = 0
|
||||
for thang in thangs ? []
|
||||
for component in thang.components or []
|
||||
isPhysical = component.original is LevelComponent.PhysicalID
|
||||
if not isPhysical and defaultConfiguration = _.find @defaultComponentConfigurations[component.original], ((d) -> _.isEqual component, d.originalComponent)
|
||||
component.config = defaultConfiguration.defaultedConfig
|
||||
++cached
|
||||
continue
|
||||
continue unless lc = _.find levelComponents, {original: component.original}
|
||||
unless isPhysical
|
||||
originalComponent = $.extend true, {}, component
|
||||
component.config ?= {}
|
||||
TreemaUtils.populateDefaults(component.config, lc.configSchema, tv4)
|
||||
TreemaUtils.populateDefaults(component.config, lc.configSchema ? {}, tv4)
|
||||
@lastType = 'component'
|
||||
@lastOriginal = component.original
|
||||
@walkDefaults component.config, lc.configSchema.properties
|
||||
unless isPhysical
|
||||
@defaultComponentConfigurations[component.original] ?= []
|
||||
@defaultComponentConfigurations[component.original].push originalComponent: originalComponent, defaultedConfig: component.config
|
||||
++cachedConfigs
|
||||
++missed
|
||||
#console.log 'cached', cached, 'missed', missed
|
||||
|
||||
fillInDefaultSystemConfiguration: (levelSystems) ->
|
||||
for system in levelSystems ? []
|
||||
|
@ -177,21 +202,6 @@ module.exports = class Level extends CocoModel
|
|||
TreemaUtils.populateDefaults(system.config, system.model.configSchema, tv4)
|
||||
@lastType = 'system'
|
||||
@lastOriginal = system.model.name
|
||||
@walkDefaults system.config, system.model.configSchema.properties
|
||||
|
||||
walkDefaults: (config, properties) ->
|
||||
# This function is redundant, but is the old implementation.
|
||||
# Remove it and calls to it once we stop seeing these warnings.
|
||||
return unless properties
|
||||
for prop, schema of properties
|
||||
if schema.default? and config[prop] is undefined
|
||||
console.warn 'Setting default of', config, 'for', prop, 'to', schema.default, 'but this method is deprecated... check your config schema!', @lastType, @lastOriginal
|
||||
config[prop] = schema.default
|
||||
if schema.type is 'object' and config[prop]
|
||||
@walkDefaults config[prop], schema.properties
|
||||
else if schema.type is 'array' and config[prop]
|
||||
for item in config[prop] or []
|
||||
@walkDefaults item, schema.items
|
||||
|
||||
dimensions: ->
|
||||
width = 0
|
||||
|
|
|
@ -102,7 +102,7 @@ DependencySchema = c.object {
|
|||
LevelComponentSchema = c.object {
|
||||
title: 'Component'
|
||||
description: 'A Component which can affect Thang behavior.'
|
||||
required: ['system', 'name', 'description', 'code', 'dependencies', 'propertyDocumentation', 'codeLanguage']
|
||||
required: ['system', 'name', 'code']
|
||||
default:
|
||||
system: 'ai'
|
||||
name: 'AttacksSelf'
|
||||
|
|
|
@ -24,6 +24,10 @@ module.exports =
|
|||
'editor:edit-level-thang': c.object {required: ['thangID']},
|
||||
thangID: {type: 'string'}
|
||||
|
||||
'editor:level-thang-edited': c.object {required: ['thangData', 'oldPath']},
|
||||
thangData: {type: 'object'}
|
||||
oldPath: {type: 'string'}
|
||||
|
||||
'editor:level-thang-done-editing': c.object {required: ['thangData', 'oldPath']},
|
||||
thangData: {type: 'object'}
|
||||
oldPath: {type: 'string'}
|
||||
|
|
|
@ -177,7 +177,7 @@ block content
|
|||
if !editing && !myProfile
|
||||
button#contact-candidate.btn.btn-large.btn-inverse.flat-button
|
||||
span(data-i18n="account_profile.contact") Contact
|
||||
| #{profile.name.split(' ')[0]}
|
||||
| #{(profile.name || user.get('name') || 'Anonymous').split(' ')[0]}
|
||||
if me.isAdmin()
|
||||
select#admin-contact.form-control
|
||||
for contact in adminContacts
|
||||
|
|
|
@ -24,9 +24,14 @@ block modal-body-content
|
|||
div.alert.alert-info
|
||||
strong Shift-drag
|
||||
| to select
|
||||
div.alert.alert-info
|
||||
strong Enter
|
||||
| to confirm
|
||||
if flexibleRegion
|
||||
div.alert.alert-info
|
||||
strong Alt-shift-drag
|
||||
| to select ratio
|
||||
else
|
||||
div.alert.alert-info
|
||||
strong Enter
|
||||
| to confirm
|
||||
canvas(width=924, height=589)
|
||||
|
||||
block modal-footer-content
|
||||
|
|
|
@ -26,7 +26,7 @@ module.exports = class NewLevelComponentModal extends ModalView
|
|||
component = new LevelComponent()
|
||||
component.set 'system', system
|
||||
component.set 'name', name
|
||||
component.set 'code', component.get('code').replace(/AttacksSelf/g, name)
|
||||
component.set 'code', component.get('code', true).replace(/AttacksSelf/g, name)
|
||||
component.set 'permissions', [{access: 'owner', target: me.id}] # Private until saved in a published Level
|
||||
res = component.save()
|
||||
return unless res
|
||||
|
|
|
@ -31,11 +31,11 @@ module.exports = class WorldSelectModal extends ModalView
|
|||
getRenderData: (c={}) =>
|
||||
c = super(c)
|
||||
c.selectingPoint = @dataType is 'point'
|
||||
c.flexibleRegion = @dataType is 'region'
|
||||
c
|
||||
|
||||
afterInsert: ->
|
||||
super()
|
||||
window.e = @$el
|
||||
@initSurface()
|
||||
|
||||
# surface setup
|
||||
|
@ -54,7 +54,6 @@ module.exports = class WorldSelectModal extends ModalView
|
|||
thangTypes: @supermodel.getModels(ThangType)
|
||||
showInvisible: true
|
||||
}
|
||||
window.s = @surface
|
||||
@surface.playing = false
|
||||
@surface.setWorld @world
|
||||
@surface.camera.zoomTo({x: 262, y: -164}, 1.66, 0)
|
||||
|
|
|
@ -19,6 +19,8 @@ module.exports = class LevelThangEditView extends CocoView
|
|||
'click #thang-type-link span': 'toggleTypeEdit'
|
||||
'blur #thang-name-link input': 'toggleNameEdit'
|
||||
'blur #thang-type-link input': 'toggleTypeEdit'
|
||||
'keydown #thang-name-link input': 'toggleNameEditIfReturn'
|
||||
'keydown #thang-type-link input': 'toggleTypeEditIfReturn'
|
||||
|
||||
constructor: (options) ->
|
||||
options ?= {}
|
||||
|
@ -27,6 +29,7 @@ module.exports = class LevelThangEditView extends CocoView
|
|||
@thangData = $.extend true, {}, options.thangData ? {}
|
||||
@level = options.level
|
||||
@oldPath = options.oldPath
|
||||
@reportChanges = _.debounce @reportChanges, 1000
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
|
@ -83,5 +86,16 @@ module.exports = class LevelThangEditView extends CocoView
|
|||
if thangType and wasEditing
|
||||
@thangData.thangType = thangType.get('original')
|
||||
|
||||
toggleNameEditIfReturn: (e) ->
|
||||
@$el.find('#thang-name-link input').blur() if e.which is 13
|
||||
|
||||
toggleTypeEditIfReturn: (e) ->
|
||||
@$el.find('#thang-type-link input').blur() if e.which is 13
|
||||
|
||||
onComponentsChanged: (components) =>
|
||||
@thangData.components = components
|
||||
@reportChanges()
|
||||
|
||||
reportChanges: =>
|
||||
return if @destroyed
|
||||
Backbone.Mediator.publish 'editor:level-thang-edited', {thangData: $.extend(true, {}, @thangData), oldPath: @oldPath}
|
||||
|
|
|
@ -16,7 +16,7 @@ MOVE_MARGIN = 0.15
|
|||
MOVE_SPEED = 13
|
||||
|
||||
# Let us place these on top of other Thangs
|
||||
overlappableThangTypeNames = ['Torch', 'Chains', 'Bird', 'Cloud 1', 'Cloud 2', 'Cloud 3', 'Waterfall', 'Obstacle']
|
||||
overlappableThangTypeNames = ['Torch', 'Chains', 'Bird', 'Cloud 1', 'Cloud 2', 'Cloud 3', 'Waterfall', 'Obstacle', 'Electrowall']
|
||||
|
||||
class ThangTypeSearchCollection extends CocoCollection
|
||||
url: '/db/thang.type?project=original,name,version,slug,kind,components'
|
||||
|
@ -33,12 +33,14 @@ module.exports = class ThangsTabView extends CocoView
|
|||
'surface:mouse-over': 'onSurfaceMouseOver'
|
||||
'surface:mouse-out': 'onSurfaceMouseOut'
|
||||
'editor:edit-level-thang': 'editThang'
|
||||
'editor:level-thang-edited': 'onLevelThangEdited'
|
||||
'editor:level-thang-done-editing': 'onLevelThangDoneEditing'
|
||||
'editor:view-switched': 'onViewSwitched'
|
||||
'sprite:dragged': 'onSpriteDragged'
|
||||
'sprite:mouse-up': 'onSpriteMouseUp'
|
||||
'sprite:mouse-down': 'onSpriteMouseDown'
|
||||
'sprite:double-clicked': 'onSpriteDoubleClicked'
|
||||
'surface:stage-mouse-down': 'onStageMouseDown'
|
||||
'surface:stage-mouse-up': 'onStageMouseUp'
|
||||
'editor:random-terrain-generated': 'onRandomTerrainGenerated'
|
||||
|
||||
|
@ -225,8 +227,17 @@ module.exports = class ThangsTabView extends CocoView
|
|||
# if e.originalEvent.nativeEvent.button == 2
|
||||
# @onSpriteContextMenu e
|
||||
|
||||
onStageMouseDown: (e) ->
|
||||
return unless @addThangSprite?.thangType.get('kind') is 'Wall'
|
||||
@surface.camera.dragDisabled = true
|
||||
@paintingWalls = true
|
||||
|
||||
onStageMouseUp: (e) ->
|
||||
if @addThangSprite
|
||||
if @paintingWalls
|
||||
# We need to stop painting walls, but we may also stop in onExtantThangSelected.
|
||||
_.defer =>
|
||||
@paintingWalls = @paintedWalls = @surface.camera.dragDisabled = false
|
||||
else if @addThangSprite
|
||||
@surface.camera.lock()
|
||||
# If we click on the background, we need to add @addThangSprite, but not if onSpriteMouseUp will fire.
|
||||
@backgroundAddClickTimeout = _.defer => @onExtantThangSelected {}
|
||||
|
@ -295,7 +306,12 @@ module.exports = class ThangsTabView extends CocoView
|
|||
@selectedExtantSprite?.setNameLabel? null unless @selectedExtantSprite is e.sprite
|
||||
@selectedExtantThang = e.thang
|
||||
@selectedExtantSprite = e.sprite
|
||||
if e.thang and (key.alt or key.meta)
|
||||
paintedAWall = @paintedWalls
|
||||
@paintingWalls = @paintedWalls = @surface.camera.dragDisabled = false
|
||||
if paintedAWall
|
||||
# Skip adding a wall now, because we already dragged to add one
|
||||
null
|
||||
else if e.thang and (key.alt or key.meta)
|
||||
# We alt-clicked, so create a clone addThang
|
||||
@selectAddThangType e.thang.spriteName, @selectedExtantThang
|
||||
else if @justAdded()
|
||||
|
@ -389,6 +405,16 @@ module.exports = class ThangsTabView extends CocoView
|
|||
wop = @surface.camera.screenToWorld x: e.x, y: e.y
|
||||
wop.z = 0.5
|
||||
@adjustThangPos @addThangSprite, @addThangSprite.thang, wop
|
||||
if @paintingWalls
|
||||
unless _.find @surface.spriteBoss.spriteArray, ((sprite) =>
|
||||
sprite.thangType.get('kind') is 'Wall' and
|
||||
Math.abs(sprite.thang.pos.x - @addThangSprite.thang.pos.x) < 2 and
|
||||
Math.abs(sprite.thang.pos.y - @addThangSprite.thang.pos.y) < 2 and
|
||||
sprite isnt @addThangSprite
|
||||
)
|
||||
@addThang @addThangType, @addThangSprite.thang.pos
|
||||
@lastAddTime = new Date()
|
||||
@paintedWalls = true
|
||||
null
|
||||
|
||||
onSurfaceMouseOver: (e) ->
|
||||
|
@ -427,6 +453,7 @@ module.exports = class ThangsTabView extends CocoView
|
|||
|
||||
deleteSelectedExtantThang: (e) =>
|
||||
return if $(e.target).hasClass 'treema-node'
|
||||
return unless @selectedExtantThang
|
||||
thang = @getThangByID(@selectedExtantThang.id)
|
||||
@thangsTreema.delete(@pathForThang(thang))
|
||||
Thang.resetThangIDs() # TODO: find some way to do this when we delete from treema, too
|
||||
|
@ -547,14 +574,19 @@ module.exports = class ThangsTabView extends CocoView
|
|||
onLevelThangDoneEditing: (e) ->
|
||||
@removeSubView @editThangView
|
||||
@editThangView = null
|
||||
newThang = e.thangData
|
||||
@updateEditedThang e.thangData, e.oldPath
|
||||
@$el.find('>').show()
|
||||
|
||||
onLevelThangEdited: (e) ->
|
||||
@updateEditedThang e.thangData, e.oldPath
|
||||
|
||||
updateEditedThang: (newThang, oldPath) ->
|
||||
@hush = true
|
||||
@thangsTreema.delete e.oldPath
|
||||
@thangsTreema.delete oldPath
|
||||
@populateFoldersForThang(newThang)
|
||||
@thangsTreema.set(@pathForThang(newThang), newThang)
|
||||
@hush = false
|
||||
@onThangsChanged()
|
||||
@$el.find('>').show()
|
||||
|
||||
preventDefaultContextMenu: (e) ->
|
||||
return unless $(e.target).closest('#canvas-wrapper').length
|
||||
|
|
|
@ -27,7 +27,10 @@ module.exports = class LevelChatView extends CocoView
|
|||
|
||||
updateMultiplayerVisibility: ->
|
||||
return unless @$el?
|
||||
@$el.toggle Boolean @session.get('multiplayer')
|
||||
try
|
||||
@$el.toggle Boolean @session.get('multiplayer')
|
||||
catch e
|
||||
console.error "Couldn't toggle the style on the LevelChatView to #{Boolean @session.get('multiplayer')} because of an error:", e
|
||||
|
||||
afterRender: ->
|
||||
@chatTables = $('table', @$el)
|
||||
|
|
Loading…
Reference in a new issue