Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-09-03 10:59:14 -07:00
commit 2e5feebf59
45 changed files with 369 additions and 418 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -428,7 +428,7 @@ module.exports = Surface = class Surface extends CocoClass
pageHeight = $('#page-container').height() - $('#control-bar-view').outerHeight() - $('#playback-view').outerHeight()
newWidth = Math.min pageWidth, pageHeight * aspectRatio
newHeight = newWidth / aspectRatio
else if $('#editor-level-thangs-tab-view')
else if $('#thangs-tab-view')
newWidth = $('#canvas-wrapper').width()
newHeight = newWidth / aspectRatio
else
@ -482,7 +482,10 @@ module.exports = Surface = class Surface extends CocoClass
onMouseDown: (e) =>
return if @disabled
onBackground = not @stage.hitTest e.stageX, e.stageY
newPos = @camera.screenToCanvas({x: e.stageX, y: e.stageY})
# getObject(s)UnderPoint is broken, so we have to use the private method to get what we want
onBackground = not @stage._getObjectsUnderPoint(newPos.x, newPos.y, null, true)
worldPos = @camera.screenToWorld x: e.stageX, y: e.stageY
event = onBackground: onBackground, x: e.stageX, y: e.stageY, originalEvent: e, worldPos: worldPos
Backbone.Mediator.publish 'surface:stage-mouse-down', event

View file

@ -557,7 +557,7 @@
grassy: "Grassy"
fork_title: "Fork New Version"
fork_creating: "Creating Fork..."
randomize: "Randomize"
generate_terrain: "Generate Terrain"
more: "More"
wiki: "Wiki"
live_chat: "Live Chat"

View file

@ -20,7 +20,7 @@ module.exports = class Achievement extends CocoModel
4: 'achievement-gold'
5: 'achievement-diamond'
getStyle: -> Achievement.styleMapping[@get 'difficulty']
getStyle: -> Achievement.styleMapping[@get 'difficulty', true]
@defaultImageURL: '/images/achievements/default.png'

View file

@ -61,11 +61,11 @@ class CocoModel extends Backbone.Model
else
super(attribute)
set: ->
set: (attributes, options) ->
delete @attributesWithDefaults
inFlux = @loading or not @loaded
@markToRevert() unless inFlux or @_revertAttributes
res = super(arguments...)
@markToRevert() unless inFlux or @_revertAttributes or @project or options?.fromMerge
res = super attributes, options
@saveBackup() if @saveBackups and (not inFlux) and @hasLocalChanges()
res
@ -154,7 +154,10 @@ class CocoModel extends Backbone.Model
markToRevert: ->
if @type() is 'ThangType'
@_revertAttributes = _.clone @attributes # No deep clones for these!
# Don't deep clone the raw vector data, but do deep clone everything else.
@_revertAttributes = _.clone @attributes
for smallProp, value of @attributes when value and smallProp isnt 'raw'
@_revertAttributes[smallProp] = _.cloneDeep value
else
@_revertAttributes = $.extend(true, {}, @attributes)

View file

@ -8,13 +8,13 @@ module.exports = class Level extends CocoModel
@schema: require 'schemas/models/level'
urlRoot: '/db/level'
serialize: (supermodel, session) ->
o = @denormalize supermodel, session
serialize: (supermodel, session, cached=false) ->
o = @denormalize supermodel, session # hot spot to optimize
# Figure out Components
o.levelComponents = $.extend true, [], (lc.attributes for lc in supermodel.getModels LevelComponent)
o.levelComponents = if cached then @getCachedLevelComponents(supermodel) else $.extend true, [], (lc.attributes for lc in supermodel.getModels LevelComponent)
@sortThangComponents o.thangs, o.levelComponents, 'Level Thang'
@fillInDefaultComponentConfiguration o.thangs, o.levelComponents
@fillInDefaultComponentConfiguration o.thangs, o.levelComponents # hot spot to optimize
# Figure out Systems
systemModels = $.extend true, [], (ls.attributes for ls in supermodel.getModels LevelSystem)
@ -22,15 +22,31 @@ module.exports = class Level extends CocoModel
@fillInDefaultSystemConfiguration o.systems
# Figure out ThangTypes' Components
o.thangTypes = (original: tt.get('original'), name: tt.get('name'), components: $.extend(true, [], tt.get('components')) for tt in supermodel.getModels ThangType)
tmap = {}
tmap[t.thangType] = true for t in o.thangs
o.thangTypes = (original: tt.get('original'), name: tt.get('name'), components: $.extend(true, [], tt.get('components')) for tt in supermodel.getModels ThangType when tmap[tt.get('original')] or tt.isFullyLoaded())
@sortThangComponents o.thangTypes, o.levelComponents, 'ThangType'
@fillInDefaultComponentConfiguration o.thangTypes, o.levelComponents
o
cachedLevelComponents: null
getCachedLevelComponents: (supermodel) ->
@cachedLevelComponents ?= {}
levelComponents = supermodel.getModels LevelComponent
newLevelComponents = []
for levelComponent in levelComponents
if levelComponent.hasLocalChanges()
newLevelComponents.push $.extend(true, {}, levelComponent.attributes)
continue
@cachedLevelComponents[levelComponent.id] ?= @cachedLevelComponents[levelComponent.id] = $.extend(true, {}, levelComponent.attributes)
newLevelComponents.push(@cachedLevelComponents[levelComponent.id])
newLevelComponents
denormalize: (supermodel, session) ->
o = $.extend true, {}, @attributes
if @get('type', true) is 'hero'
if o.thangs and @get('type', true) is 'hero'
# TOOD: figure out if/when/how we are doing this for non-Hero levels that aren't expecting denormalization.
for levelThang in o.thangs
@denormalizeThang(levelThang, supermodel, session)

View file

@ -120,7 +120,7 @@ module.exports = class SuperModel extends Backbone.Model
cachedModel = @getModelByURL(model.getURL())
if cachedModel
clone = $.extend true, {}, model.attributes
cachedModel.set(clone, {silent: true})
cachedModel.set(clone, {silent: true, fromMerge: true})
console.debug "Updated cached model <#{cachedModel.get('name') or cachedModel.getURL()}> with new data"
else
@registerModel(model)

View file

@ -56,3 +56,6 @@ module.exports =
'editor:thang-type-kind-changed': c.object {required: ['kind']},
kind: {type: 'string'}
'editor:thang-type-color-groups-changed': c.object {required: ['colorGroups']},
colorGroups: {type: 'object'}

View file

@ -38,8 +38,8 @@ module.exports =
time: {type: 'number', minimum: 0}
ratio: {type: 'number', minimum: 0, maximum: 1}
ratioOffset: {type: 'number'}
frameOffset: {type: 'integer'}
scrubDuration: {type: 'integer', minimum: 0}
frameOffset: {type: 'number'}
scrubDuration: {type: 'number', minimum: 0}
'level:select-sprite': c.object {},
thangID: {type: ['string', 'null', 'undefined']}

View file

@ -0,0 +1,76 @@
@import "../../bootstrap/mixins"
#add-thangs-view
$addPaletteIconColumns: 6
$addPaletteIconWidth: 40px
$addPaletteIconPadding: 0px
$addPaletteIconMargin: 4px
$addPaletteWidth: ($addPaletteIconWidth + 2 * $addPaletteIconPadding + 2 * $addPaletteIconMargin) * $addPaletteIconColumns + 26
width: $addPaletteWidth
background: white
box-sizing: border-box
position: absolute
right: 0
top: 0
bottom: 0
padding: 5px
border: 1px solid
input
width: 100%
margin-top: 5px
#thangs-list
position: absolute
left: 8px
top: 80px
bottom: 0px
overflow: scroll
margin: 0
h3
margin: 0 0 10px
width: 100%
h4
margin: 0 0 10px
clear: both
padding: 5px
background: rgba(150, 150, 150, 0.5)
width: $addPaletteWidth - 20px
box-sizing: border-box
.clearfix
margin-bottom: 20px
.add-thang-palette-icon
position: relative
float: left
background: white
padding: $addPaletteIconPadding
margin: $addPaletteIconMargin
cursor: pointer
width: $addPaletteIconWidth
height: $addPaletteIconWidth
img
position: absolute
width: $addPaletteIconWidth
height: $addPaletteIconWidth
transition: box-shadow 0.25s ease-out
&:hover
$hoverScaleIncreaseFactor: 0.2
outline: 1px dotted blue
img
left: -($hoverScaleIncreaseFactor / 2) * $addPaletteIconWidth
top: -($hoverScaleIncreaseFactor / 2) * $addPaletteIconWidth
width: (1 + $hoverScaleIncreaseFactor) * $addPaletteIconWidth
height: (1 + $hoverScaleIncreaseFactor) * $addPaletteIconWidth
&.selected
outline: 1px solid blue
@include box-shadow(0px 5px 25px rgba(79, 79, 213, 0.6))
background: #add8e6

View file

@ -1,4 +1,4 @@
#editor-level-component-edit-view
#level-component-edit-view
nav
margin-bottom: 0

View file

@ -1,13 +1,16 @@
#terrain-randomize-modal
#generate-terrain-modal
.choose-option
margin-bottom: 15px
width: 100%
width: 48%
margin-right: 1%
margin-left: 1%
height: 200px
overflow: hidden
background: white
border: 1px solid #333
position: relative
float: left
-webkit-transition: opacity 0.3s ease-in-out
-moz-transition: opacity 0.3s ease-in-out

View file

@ -1,4 +1,4 @@
#editor-level-system-edit-view
#level-system-edit-view
nav
margin-bottom: 0

View file

@ -1,4 +1,4 @@
#editor-level-systems-tab-view
#systems-tab-view
h3
margin-top: 0
@media screen and (max-width: 800px)
@ -28,6 +28,9 @@
@media screen and (max-width: 800px)
z-index: 10
bottom: -35px
.treema-add-child
display: none
.treema-children .treema-row *
cursor: pointer !important

View file

@ -0,0 +1,88 @@
@import "../../bootstrap/mixins"
#thangs-tab-view
$extantThangsWidth: 300px
position: absolute
top: 0
bottom: 0
overflow: hidden
left: 0
right: 0
margin: -15px
#thangs-container-toggle, #thangs-palette-toggle
top: 5px
position: absolute
z-index: 12
padding: 8px
#thangs-container-toggle
left: 5px
box-shadow: 1px 1px 5px black
#thangs-palette-toggle
right: 5px
box-shadow: -1px 1px 5px black
.thangs-container
background: white
width: $extantThangsWidth
position: absolute
left: 0
top: 0
bottom: 0
z-index: 11
padding: 5px
border: 1px solid black
h3
text-align: right
margin: 0
.editor-nano-container
height: 90%
position: relative
top: 20px
#thangs-treema
position: absolute
top: 37px
left: 0
right: 0
bottom: 0
overflow: scroll
margin: 0
outline: thin
border: none
padding-top: 0
.treema-children .treema-row *
cursor: pointer !important
.world-container
margin-left: 0
margin-right: 0
box-sizing: border-box
.world-container
position: relative
#canvas-wrapper
width: 100%
position: relative
text-align: center
.generate-terrain-button
position: absolute
top: 45%
//height: 40px
// Below snatched from play/level.sass; should refactor?
canvas#surface
background-color: #ddd
width: 100%
display: block
z-index: 1
border: 1px solid black

View file

@ -1,265 +0,0 @@
@import "../../bootstrap/mixins"
$mobile: 1050px
#editor-level-thangs-tab-view
$addPaletteIconColumns: 3
$extantThangsWidth: 300px
$addPaletteIconWidth: 40px
$addPaletteIconPadding: 0px
$addPaletteIconMargin: 4px
$addPaletteWidth: ($addPaletteIconWidth + 2 * $addPaletteIconPadding + 2 * $addPaletteIconMargin) * $addPaletteIconColumns + 20
#toggle
display: none
position: absolute
z-index: 11
left: -14px
@media screen and (max-width: $mobile)
display: block
.toggle
left: 0
.toggle
display: none
float: none
z-index: 11
position: absolute
right: -14px
z-index: 11
margin: 0
padding: 8px
@media screen and (max-width: $mobile)
display: block
.thangs-column
background-color: #E4CF8C
@media screen and (max-width: $mobile)
display: block
h3
@media screen and (max-width: $mobile)
display: none
#all-thangs
display: block
@media screen and (max-width: $mobile)
display: none
.thangs-container
width: $extantThangsWidth
position: absolute
left: 0
top: 0
bottom: 0
z-index: 11
@media screen and (max-width: $mobile)
width: auto
left: 18px
bottom: -18px
.btn-group
margin: 0
@media screen and (max-width: $mobile)
margin: 5px
h3
margin: 0 -20px 0 0
.editor-nano-container
height: 90%
position: relative
top: 20px
#thangs-treema
height: 100%
width: 100%
position: absolute
left: 0
right: 0
bottom: 0
overflow: scroll
margin: 0
outline: thin
@media screen and (max-width: $mobile)
margin: 5px
top: 40px
&.hide-except-Unit
.treema-node
display: none
.treema-node.treema-Unit
display: block
&.hide-except-Doodad
.treema-node
display: none
.treema-node.treema-Doodad
display: block
&.hide-except-Floor
.treema-node
display: none
.treema-node.treema-Floor
display: block
&.hide-except-Wall
.treema-node
display: none
.treema-node.treema-Wall
display: block
&.hide-except-Item
.treema-node
display: none
.treema-node.treema-Item
display: block
&.hide-except-Misc
.treema-node
display: none
.treema-node.treema-Misc
display: block
.treema-children .treema-row *
cursor: pointer !important
.world-container
margin-left: $extantThangsWidth
margin-right: $addPaletteWidth
@media screen and (max-width: $mobile)
margin-left: 0
margin-right: 0
padding: 0 20px
box-sizing: border-box
h3
margin: 0 -10px 0 0
text-align: center
.add-thangs-palette
width: $addPaletteWidth
box-sizing: border-box
position: absolute
right: 0
top: 0
bottom: 0
@media screen and (max-width: $mobile)
display: none
right: 18px
z-index: 11
width: $addPaletteWidth + 10
bottom: -15px
//height: auto
//padding-bottom: 10px
input
width: $addPaletteWidth
margin: 0
margin-top: 5px
padding-left: 5px
@media screen and (max-width: $mobile)
margin: 0 5px
#thangs-list-container
height: 90%
#thangs-list
position: relative
right: 0
top: 10px
bottom: 10px
overflow: scroll
height: 100%
margin: 0
@media screen and (max-width: $mobile)
margin: 0 5px
h3
margin: 0 -20px 0 0
width: 100%
h4
margin: 0 0 10px
clear: both
padding: 5px
background: rgba(150, 150, 150, 0.5)
width: $addPaletteWidth - 20px
box-sizing: border-box
.clearfix
margin-bottom: 20px
.add-thang-palette-icon
position: relative
float: left
background: white
padding: $addPaletteIconPadding
margin: $addPaletteIconMargin
cursor: pointer
width: $addPaletteIconWidth
height: $addPaletteIconWidth
img
position: absolute
width: $addPaletteIconWidth
height: $addPaletteIconWidth
transition: box-shadow 0.25s ease-out
&:hover
$hoverScaleIncreaseFactor: 0.2
outline: 1px dotted blue
img
left: -($hoverScaleIncreaseFactor / 2) * $addPaletteIconWidth
top: -($hoverScaleIncreaseFactor / 2) * $addPaletteIconWidth
width: (1 + $hoverScaleIncreaseFactor) * $addPaletteIconWidth
height: (1 + $hoverScaleIncreaseFactor) * $addPaletteIconWidth
&.selected
outline: 1px solid blue
@include box-shadow(0px 5px 25px rgba(79, 79, 213, 0.6))
background: #add8e6
.world-container
position: relative
#canvas-wrapper
width: 100%
position: relative
text-align: center
#randomize-button
position: absolute
top: 45%
height: 40px
// Below snatched from play/level.sass; should refactor?
canvas#surface
background-color: #ddd
width: 100%
display: block
z-index: 1
$GI: 0.5 // gradient intensity; can tweak this 0-1
.gradient
position: absolute
z-index: 10
#canvas-left-gradient
left: 0px
width: 5px
background: linear-gradient(to left, rgba(0,0,0,0) 0%,rgba(0,0,0,0.8*$GI) 100%)
bottom: 0
top: 0
#canvas-top-gradient
top: 0
height: 5px
left: 0
right: 0
background: linear-gradient(to top, rgba(0,0,0,0) 0%,rgba(0,0,0,0.8*$GI) 100%)

View file

@ -25,12 +25,17 @@ $height: 550px
box-sizing: border-box
button
width: 20px
height: 25px
border: 2px solid white
margin: 1px
width: 36px
height: 36px
margin: 7px
padding: 0
border: 7px solid white
&.selected
width: 48px
height: 48px
margin: 1px
border: 2px solid black
#controls

View file

@ -11,4 +11,4 @@
span.icon-plus
span.text(data-i18n="editor.level_component_btn_new") Create New Component
#editor-level-component-edit-view
#level-component-edit-view

View file

@ -18,7 +18,7 @@ block header
ul.nav.navbar-nav.nav-tabs
li.active
a(href="#editor-level-thangs-tab-view", data-toggle="tab", data-i18n="editor.level_tab_thangs") Thangs
a(href="#thangs-tab-view", data-toggle="tab", data-i18n="editor.level_tab_thangs") Thangs
li
a(href="#editor-level-scripts-tab-view", data-toggle="tab", data-i18n="editor.level_tab_scripts") Scripts
li
@ -26,7 +26,7 @@ block header
li
a(href="#editor-level-components-tab-view", data-toggle="tab", data-i18n="editor.level_tab_components")#components-tab Components
li
a(href="#editor-level-systems-tab-view", data-toggle="tab", data-i18n="editor.level_tab_systems") Systems
a(href="#systems-tab-view", data-toggle="tab", data-i18n="editor.level_tab_systems") Systems
li
a(href="#editor-level-patches", data-toggle="tab")#patches-tab
span(data-i18n="resources.patches").spr Patches
@ -94,7 +94,7 @@ block header
li(class=anonymous ? "disabled": "")
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert
li(class=anonymous ? "disabled": "")
a(data-toggle="coco-modal", data-target="editor/level/modals/TerrainRandomizeModal", data-i18n="editor.randomize")#randomize-button Randomize
a(data-toggle="coco-modal", data-target="editor/level/modals/GenerateTerrainModal", data-i18n="editor.generate_terrain").generate-terrain-button Generate Terrain
li(class=anonymous ? "disabled": "")
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
li.divider
@ -115,7 +115,7 @@ block header
block outer_content
.outer-content
div.tab-content#level-editor-tabs
div.tab-pane.active#editor-level-thangs-tab-view
div.tab-pane.active#thangs-tab-view
div.tab-pane#editor-level-scripts-tab-view
@ -123,7 +123,7 @@ block outer_content
div.tab-pane#editor-level-components-tab-view
div.tab-pane#editor-level-systems-tab-view
div.tab-pane#systems-tab-view
div.tab-pane#editor-level-patches
.patches-view

View file

@ -13,4 +13,5 @@ block modal-body-content
span(data-i18n="editor."+size) #{size}
div.preset-name.capitalize
span(data-i18n="editor."+preset.type) #{preset.type}
.clearfix
block modal-footer

View file

@ -21,3 +21,8 @@ block modal-body-content
label
input(type="checkbox", name="queryOptions" id="#{goal.id}" value="#{goal.id}")
span.spl= goal.name
block modal-footer
.modal-footer
button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel
button#save-new-achievement-link.btn.btn-primary.new-model-submit(data-i18n="common.create") Create

View file

@ -18,6 +18,6 @@ else
td(style="width: 20px")
img.achievement-icon-small(src=achievement.getImageURL() alt="#{achievement.get('name') icon")
td
a(href="/editor/achievement/#{achievement.get('slug')}")= achievement.get('name')
td= achievement.get('description')
td= achievement.get('worth')
a(href="/editor/achievement/#{achievement.get('slug')}")= achievement.get('name', true)
td= achievement.get('description', true)
td= achievement.get('worth', true)

View file

@ -11,7 +11,7 @@
span.icon-file
span.text(data-i18n="editor.level_systems_btn_new") Create New System
#editor-level-system-edit-view
#level-system-edit-view
button.btn.btn-primary#add-system-button
span.icon-plus

View file

@ -0,0 +1,22 @@
button.btn#thangs-container-toggle
span.icon-list
button.btn#thangs-palette-toggle
span.icon-plus
.thangs-container.hide#all-thangs
h3(data-i18n="editor.level_tab_thangs_title") Current Thangs
#thangs-treema(title="Double click to configure a thang")
.world-container
#canvas-wrapper
button.generate-terrain-button.btn.btn-info.btn-lg(data-toggle="coco-modal", data-target="editor/level/modals/GenerateTerrainModal", data-i18n="editor.generate_terrain", title="Generate Terrain") Generate Terrain
ul.dropdown-menu#contextmenu
li#delete
a(data-i18n="editor.delete") Delete
li#duplicate
a(data-i18n="editor.duplicate") Duplicate
canvas(width=924, height=589)#surface
#canvas-left-gradient.gradient
#canvas-top-gradient.gradient
#add-thangs-view
#level-thang-edit-view.secret

View file

@ -1,39 +0,0 @@
div#toggle
button.navbar-toggle.toggle.btn-primary#thangs-container-toggle(type="button", data-toggle="collapse", data-target="#all-thangs")
span.icon-list
button.navbar-toggle.toggle.btn-primary#thangs-palette-toggle(type="button", data-toggle="collapse", data-target="#add-thangs-column")
span.icon-plus
.thangs-container.thangs-column#all-thangs
h3(data-i18n="editor.level_tab_thangs_title") Current Thangs
.btn-group(data-toggle="buttons-radio")#extant-thangs-filter
button.btn.btn-primary(data-i18n="editor.level_tab_thangs_all") All
button.btn.btn-primary(value="Unit", title="Unit")
i.icon-user
button.btn.btn-primary(value="Wall", title="Wall")
i.icon-home
button.btn.btn-primary(value="Floor", title="Floor")
i.icon-globe
button.btn.btn-primary(value="Doodad", title="Doodad")
i.icon-leaf
button.btn.btn-primary(value="Item", title="Item")
i.icon-gift
button.btn.btn-primary(value="Misc", title="Misc")
i.icon-question-sign
.editor-nano-container.nano
#thangs-treema.nano-content(title="Double click to configure a thang")
.world-container.thangs-column
h3(data-i18n="editor.level_tab_thangs_conditions") Starting Conditions
#canvas-wrapper
button.btn.btn-primary(id="randomize-button", data-toggle="coco-modal", data-target="editor/level/modals/TerrainRandomizeModal", data-i18n="editor.randomize", title="Randomize Terrain") Randomize
ul.dropdown-menu#contextmenu
li#delete
a(data-i18n="editor.delete") Delete
li#duplicate
a(data-i18n="editor.duplicate") Duplicate
canvas(width=924, height=589)#surface
#canvas-left-gradient.gradient
#canvas-top-gradient.gradient
.add-thangs-palette.thangs-column#add-thangs-column
#level-thang-edit-view.secret

View file

@ -26,11 +26,11 @@ module.exports = class AchievementPopup extends CocoView
nextLevelXP = User.expForLevel(nextLevel)
totalExpNeeded = nextLevelXP - currentLevelExp
expFunction = @achievement.getExpFunction()
currentXP = me.get 'points'
currentXP = me.get 'points', true
if @achievement.isRepeatable()
achievedXP = expFunction(@earnedAchievement.get('previouslyAchievedAmount')) * @achievement.get('worth') if @achievement.isRepeatable()
else
achievedXP = @achievement.get 'worth'
achievedXP = @achievement.get 'worth', true
previousXP = currentXP - achievedXP
leveledUp = currentXP - achievedXP < currentLevelExp
#console.debug 'Leveled up' if leveledUp

View file

@ -15,9 +15,6 @@ module.exports = class AchievementEditView extends RootView
'click #recalculate-button': 'confirmRecalculation'
'click #delete-button': 'confirmDeletion'
subscriptions:
'save-new': 'saveAchievement'
constructor: (options, @achievementID) ->
super options
@achievement = new Achievement(_id: @achievementID)

View file

@ -52,7 +52,7 @@ module.exports = class ThangComponentConfigView extends CocoView
schema.default ?= {}
_.merge schema.default, @additionalDefaults if @additionalDefaults
if @level?.get('type') is 'hero'
if @level?.get('type', true) is 'hero'
schema.required = []
treemaOptions =
supermodel: @supermodel

View file

@ -135,11 +135,10 @@ module.exports = class LevelEditView extends RootView
@$el.find('#redo-button').attr('title', 'Redo ' + redoDescription + ' (Ctrl+Shift+Z)')
getCurrentView: ->
tabText = _.string.underscored $('li.active')[0]?.textContent
currentView = @subviews["editor_level_#{tabText}_tab_view"]
if tabText is 'patches' then currentView = @patchesView
if tabText is 'documentation' then currentView = @subviews.docs_components_view
currentView
currentViewID = @$el.find('.tab-pane.active').attr('id')
return @patchesView if currentViewID is 'editor-level-patches'
currentViewID = 'components-documentation-view' if currentViewID is 'editor-level-documentation'
return @subviews[_.string.underscored(currentViewID)]
startPatchingLevel: (e) ->
@openModalView new SaveVersionModal({model: @level})

View file

@ -37,7 +37,7 @@ module.exports = class LevelFeedbackView extends CocoView
context.allFeedback = []
context.averageRating = 0
context.totalRatings = 0
if @allFeedback
if @allFeedback?.models.length
context.allFeedback = (m.attributes for m in @allFeedback.models when @allFeedback.models.length < 20 or m.get('review'))
context.averageRating = _.reduce((m.get('rating') for m in @allFeedback.models), (acc, x) -> acc + (x ? 5)) / (@allFeedback.models.length)
context.totalRatings = @allFeedback.models.length

View file

@ -35,7 +35,9 @@ module.exports = class RelatedAchievementsView extends CocoView
c
onNewAchievementSaved: (achievement) ->
app.router.navigate('/editor/achievement/' + (achievement.get('slug') or achievement.id), {trigger: true})
# We actually open the new tab in NewAchievementModal, so we don't replace this window.
#url = '/editor/achievement/' + (achievement.get('slug') or achievement.id)
#app.router.navigate(, {trigger: true}) # Let's open a new tab instead.
makeNewAchievement: ->
modal = new NewAchievementModal model: Achievement, modelLabel: 'Achievement', level: @level

View file

@ -1,12 +1,12 @@
CocoView = require 'views/kinds/CocoView'
template = require 'templates/editor/level/component/edit'
template = require 'templates/editor/level/component/level-component-edit-view'
LevelComponent = require 'models/LevelComponent'
ComponentVersionsModal = require 'views/editor/component/ComponentVersionsModal'
PatchesView = require 'views/editor/PatchesView'
SaveVersionModal = require 'views/modal/SaveVersionModal'
module.exports = class LevelComponentEditView extends CocoView
id: 'editor-level-component-edit-view'
id: 'level-component-edit-view'
template: template
editableSettings: ['name', 'description', 'system', 'codeLanguage', 'dependencies', 'propertyDocumentation', 'i18n']
@ -69,7 +69,7 @@ module.exports = class LevelComponentEditView extends CocoView
@updatePatchButton()
buildConfigSchemaTreema: ->
configSchema = @levelComponent.get 'configSchema'
configSchema = $.extend true, {}, @levelComponent.get 'configSchema'
if configSchema.properties
# Alphabetize (#1297)
propertyNames = _.keys configSchema.properties

View file

@ -1,5 +1,5 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/editor/level/modal/terrain_randomize'
template = require 'templates/editor/level/modal/generate-terrain-modal'
CocoModel = require 'models/CocoModel'
clusters = {
@ -229,11 +229,14 @@ thangSizes = {
}}
module.exports = class TerrainRandomizeModal extends ModalView
id: 'terrain-randomize-modal'
module.exports = class GenerateTerrainModal extends ModalView
id: 'generate-terrain-modal'
template: template
plain: true
modalWidthPercent: 90
events:
'click .choose-option': 'onRandomize'
'click .choose-option': 'onGenerate'
onRevertModel: (e) ->
id = $(e.target).val()
@ -241,25 +244,25 @@ module.exports = class TerrainRandomizeModal extends ModalView
$(e.target).closest('tr').remove()
@reloadOnClose = true
onRandomize: (e) ->
onGenerate: (e) ->
target = $(e.target)
presetType = target.attr 'data-preset-type'
presetSize = target.attr 'data-preset-size'
@randomizeThangs presetType, presetSize
@generateThangs presetType, presetSize
Backbone.Mediator.publish 'editor:random-terrain-generated', thangs: @thangs, terrain: presets[presetType].terrainName
@hide()
randomizeThangs: (presetName, presetSize) ->
generateThangs: (presetName, presetSize) ->
@falseCount = 0
preset = presets[presetName]
presetSize = presetSizes[presetSize]
@thangs = []
@rects = []
@randomizeFloor preset, presetSize
@randomizeBorder preset, presetSize, preset.borderNoise
@randomizeDecorations preset, presetSize
@generateFloor preset, presetSize
@generateBorder preset, presetSize, preset.borderNoise
@generateDecorations preset, presetSize
randomizeFloor: (preset, presetSize) ->
generateFloor: (preset, presetSize) ->
for i in _.range(0, presetSize.x, thangSizes.floorSize.x)
for j in _.range(0, presetSize.y, thangSizes.floorSize.y)
@thangs.push {
@ -271,7 +274,7 @@ module.exports = class TerrainRandomizeModal extends ModalView
'margin': clusters[preset.floors].margin
}
randomizeBorder: (preset, presetSize, noiseFactor=1) ->
generateBorder: (preset, presetSize, noiseFactor=1) ->
for i in _.range(0, presetSize.x, thangSizes.borderSize.x)
for j in _.range(preset.borderThickness)
# Bottom wall
@ -349,7 +352,7 @@ module.exports = class TerrainRandomizeModal extends ModalView
}
continue
randomizeDecorations: (preset, presetSize)->
generateDecorations: (preset, presetSize)->
for name, decoration of preset.decorations
for num in _.range(presetSize.sizeFactor * _.random(decoration.num[0], decoration.num[1]))
if @['build'+name] isnt undefined

View file

@ -8,6 +8,9 @@ module.exports = class NewAchievementModal extends NewModelModal
template: template
plain: false
events:
'click #save-new-achievement-link': 'onAchievementSubmitted'
constructor: (options) ->
super options
@level = options.level
@ -15,9 +18,13 @@ module.exports = class NewAchievementModal extends NewModelModal
getRenderData: ->
c = super()
c.level = @level
console.debug 'level', c.level
c
onAchievementSubmitted: (e) ->
slug = _.string.slugify @$el.find('#name').val()
url = "/editor/achievement/#{slug}"
window.open url, '_blank'
createQuery: ->
checked = @$el.find('[name=queryOptions]:checked')
checkedValues = ($(check).val() for check in checked)

View file

@ -61,6 +61,15 @@ module.exports = class SettingsTabView extends CocoView
if (terrain = @settingsTreema.data.terrain) isnt @lastTerrain
@lastTerrain = terrain
Backbone.Mediator.publish 'editor:terrain-changed', terrain: terrain
for goal, index in @settingsTreema.data.goals ? []
continue if goal.id
goalIndex = index
goalID = "goal-#{goalIndex}"
goalID = "goal-#{++goalIndex}" while _.find @settingsTreema.get("goals"), id: goalID
@settingsTreema.disableTracking()
@settingsTreema.set "/goals/#{index}/id", goalID
@settingsTreema.set "/goals/#{index}/name", _.string.humanize goalID
@settingsTreema.enableTracking()
onThangsEdited: (e) ->
# Update in-place so existing Treema nodes refer to the same array.

View file

@ -1,12 +1,12 @@
CocoView = require 'views/kinds/CocoView'
template = require 'templates/editor/level/system/edit'
template = require 'templates/editor/level/system/level-system-edit-view'
LevelSystem = require 'models/LevelSystem'
SystemVersionsModal = require 'views/editor/level/systems/SystemVersionsModal'
PatchesView = require 'views/editor/PatchesView'
SaveVersionModal = require 'views/modal/SaveVersionModal'
module.exports = class LevelSystemEditView extends CocoView
id: 'editor-level-system-edit-view'
id: 'level-system-edit-view'
template: template
editableSettings: ['name', 'description', 'codeLanguage', 'dependencies', 'propertyDocumentation', 'i18n']
@ -66,7 +66,7 @@ module.exports = class LevelSystemEditView extends CocoView
treemaOptions =
supermodel: @supermodel
schema: LevelSystem.schema.properties.configSchema
data: @levelSystem.get 'configSchema'
data: $.extend true, {}, @levelSystem.get 'configSchema'
callbacks: {change: @onConfigSchemaEdited}
treemaOptions.readOnly = me.get('anonymous')
@configSchemaTreema = @$el.find('#config-schema-treema').treema treemaOptions

View file

@ -1,5 +1,5 @@
CocoView = require 'views/kinds/CocoView'
template = require 'templates/editor/level/systems_tab'
template = require 'templates/editor/level/systems-tab-view'
Level = require 'models/Level'
LevelSystem = require 'models/LevelSystem'
LevelSystemEditView = require './LevelSystemEditView'
@ -8,7 +8,7 @@ AddLevelSystemModal = require './AddLevelSystemModal'
{ThangTypeNode} = require './../treema_nodes'
module.exports = class SystemsTabView extends CocoView
id: 'editor-level-systems-tab-view'
id: 'systems-tab-view'
template: template
className: 'tab-pane'
@ -49,7 +49,6 @@ module.exports = class SystemsTabView extends CocoView
insertedDefaults = true
systems = @getSortedByName systems
treemaOptions =
# TODO: somehow get rid of the + button, or repurpose it to open the AddLevelSystemModal instead
supermodel: @supermodel
schema: Level.schema.properties.systems
data: systems
@ -153,8 +152,6 @@ class LevelSystemNode extends TreemaObjectNode
grabDBComponent: ->
data = @getData()
unless _.isString data.original
return alert('Press the "Add System" button at the bottom instead of the "+". Sorry.')
@system = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelSystem, data.original, data.majorVersion)
console.error 'Couldn\'t find system for', data.original, data.majorVersion, 'from models', @settings.supermodel.models unless @system

View file

@ -1,5 +1,5 @@
CocoView = require 'views/kinds/CocoView'
add_thangs_template = require 'templates/editor/level/add_thangs'
add_thangs_template = require 'templates/editor/level/add-thangs-view'
ThangType = require 'models/ThangType'
CocoCollection = require 'collections/CocoCollection'
@ -11,8 +11,8 @@ class ThangTypeSearchCollection extends CocoCollection
@url += "&term=#{term}" if term
module.exports = class AddThangsView extends CocoView
id: 'add-thangs-column'
className: 'add-thangs-palette thangs-column'
id: 'add-thangs-view'
className: 'add-thangs-palette'
template: add_thangs_template
events:

View file

@ -24,7 +24,7 @@ module.exports = class LevelThangEditView extends CocoView
options ?= {}
super options
@world = options.world
@thangData = options.thangData ? {}
@thangData = $.extend true, {}, options.thangData ? {}
@level = options.level
@oldID = @thangData.id
@ -42,8 +42,8 @@ module.exports = class LevelThangEditView extends CocoView
supermodel: @supermodel
level: @level
world: @world
if @level.get('type') is 'hero' then options.thangType = thangType
if @level.get('type', true) is 'hero' then options.thangType = thangType
@thangComponentEditView = new ThangComponentsEditView options
@listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged
@ -59,7 +59,7 @@ module.exports = class LevelThangEditView extends CocoView
saveThang: (e) ->
# Make sure it validates first?
Backbone.Mediator.publish 'editor:level-thang-edited', thangData: @thangData, thangID: @oldID
Backbone.Mediator.publish 'editor:level-thang-edited', thangData: $.extend(true, {}, @thangData), thangID: @oldID
navigateToAllThangs: ->
Backbone.Mediator.publish 'editor:level-thang-done-editing', {}

View file

@ -1,6 +1,6 @@
CocoView = require 'views/kinds/CocoView'
AddThangsView = require './AddThangsView'
thangs_template = require 'templates/editor/level/thangs_tab'
thangs_template = require 'templates/editor/level/thangs-tab-view'
Level = require 'models/Level'
ThangType = require 'models/ThangType'
LevelComponent = require 'models/LevelComponent'
@ -23,7 +23,7 @@ class ThangTypeSearchCollection extends CocoCollection
model: ThangType
module.exports = class ThangsTabView extends CocoView
id: 'editor-level-thangs-tab-view'
id: 'thangs-tab-view'
className: 'tab-pane active'
template: thangs_template
@ -48,7 +48,7 @@ module.exports = class ThangsTabView extends CocoView
'click #delete': 'onDeleteClicked'
'click #duplicate': 'onDuplicateClicked'
'click #thangs-container-toggle': 'toggleThangsContainer'
# 'click #thangs-palette-toggle': 'toggleThangsPalette'
'click #thangs-palette-toggle': 'toggleThangsPalette'
# 'click .add-thang-palette-icon': 'toggleThangsPalette'
shortcuts:
@ -95,17 +95,6 @@ module.exports = class ThangsTabView extends CocoView
context.groups = groups
context
onWindowResize: (e) ->
$('#thangs-list').height('100%')
thangsHeaderHeight = $('#thangs-header').height()
oldHeight = $('#thangs-list').height()
if $(document).width() < 1050
$('#thangs-list').height(oldHeight - thangsHeaderHeight - 40)
else
$('#thangs-list').height(oldHeight - thangsHeaderHeight - 80)
$('#all-thangs').collapse 'show'
$('#add-thangs-column').collapse 'show'
undo: (e) ->
if not @editThangView then @thangsTreema.undo() else @editThangView.undo()
@ -163,7 +152,7 @@ module.exports = class ThangsTabView extends CocoView
oldHeight = $('#thangs-list').height()
$('#thangs-list').height(oldHeight - thangsHeaderHeight)
if data.thangs?.length
@$el.find('#randomize-button').hide()
@$el.find('.generate-terrain-button').hide()
initSurface: ->
surfaceCanvas = $('canvas#surface', @$el)
@ -178,7 +167,17 @@ module.exports = class ThangsTabView extends CocoView
}
@surface.playing = false
@surface.setWorld @world
@surface.camera.zoomTo({x: 262, y: -164}, 1.66, 0)
@centerCamera()
centerCamera: ->
[width, height] = @world.size()
width = Math.max width, 80
height = Math.max height, 68
{left, top, right, bottom} = @world.getBounds()
center = x: left + width / 2, y: bottom + height / 2
sup = @surface.camera.worldToSurface center
zoom = 0.94 * 92.4 / width # Zoom 1.0 lets us see 92.4 meters.
@surface.camera.zoomTo(sup, zoom, 0)
destroy: ->
@selectAddThangType null
@ -240,8 +239,17 @@ module.exports = class ThangsTabView extends CocoView
@thangsBatch = []
nonRandomThangs = (thang for thang in @thangsTreema.get('') when not /Random/.test thang.id)
@thangsTreema.set '', nonRandomThangs
listening = {}
for thang in e.thangs
@selectAddThangType thang.id
# kind of a hack to get the walls to show up correctly when they load.
# might also fix other thangs who need to show up looking a certain way based on thang type components
unless @addThangType.isFullyLoaded() or listening[@addThangType.cid]
listening[@addThangType.cid] = true
@listenToOnce @addThangType, 'build-complete', @onThangsChanged
@addThang @addThangType, thang.pos, true
@batchInsert()
@selectAddThangType null
@ -279,7 +287,7 @@ module.exports = class ThangsTabView extends CocoView
selectAddThang: (e, forceDeselect=false) =>
return if e? and $(e.target).closest('#thang-search').length # Ignore if you're trying to search thangs
return unless (e? and $(e.target).closest('#editor-level-thangs-tab-view').length) or key.isPressed('esc') or forceDeselect
return unless (e? and $(e.target).closest('#thangs-tab-view').length) or key.isPressed('esc') or forceDeselect
if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event
return true if target.attr('id') is 'surface'
target = target.closest('.add-thang-palette-icon')
@ -397,7 +405,7 @@ module.exports = class ThangsTabView extends CocoView
onThangsChanged: (e) =>
@level.set 'thangs', @thangsTreema.data
return if @editThangView
serializedLevel = @level.serialize @supermodel
serializedLevel = @level.serialize @supermodel, null, true
try
@world.loadFromLevel serializedLevel, false
catch error
@ -405,7 +413,7 @@ module.exports = class ThangsTabView extends CocoView
thang.isSelectable = not thang.isLand for thang in @world.thangs # let us select walls and such
@surface?.setWorld @world
@selectAddThangType @addThangType, @cloneSourceThang if @addThangType # make another addThang sprite, since the World just refreshed
# update selection, since the thangs have been remade
if @selectedExtantThang
@selectedExtantSprite = @surface.spriteBoss.sprites[@selectedExtantThang.id]
@ -426,18 +434,18 @@ module.exports = class ThangsTabView extends CocoView
@thangsBatch = []
addThang: (thangType, pos, batchInsert=false) ->
@$el.find('#randomize-button').hide()
@$el.find('.generate-terrain-button').hide()
if batchInsert
if thangType.get('name') is 'Hero Placeholder'
thangID = 'Hero Placeholder'
return if @level.get('type') isnt 'hero' or @thangsTreema.get "id=#{thangID}"
return if @level.get('type', true) isnt 'hero' or @thangsTreema.get "id=#{thangID}"
else
thangID = "Random #{thangType.get('name')} #{@thangsBatch.length}"
else
thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
if @cloneSourceThang
components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
else if @level.get('type') is 'hero'
else if @level.get('type', true) is 'hero'
components = [] # Load them all from default ThangType Components
else
components = _.cloneDeep thangType.get('components') ? []
@ -458,7 +466,8 @@ module.exports = class ThangsTabView extends CocoView
thangData = @thangsTreema.get "id=#{e.thangID}"
@editThangView = new LevelThangEditView thangData: thangData, level: @level, world: @world, supermodel: @supermodel # supermodel needed for checkForMissingSystems
@insertSubView @editThangView
@$el.find('.thangs-column').hide()
@$el.find('>').hide()
@editThangView.$el.show()
Backbone.Mediator.publish 'editor:view-switched', {}
onLevelThangEdited: (e) ->
@ -469,7 +478,7 @@ module.exports = class ThangsTabView extends CocoView
@removeSubView @editThangView
@editThangView = null
@onThangsChanged()
@$el.find('.thangs-column').show()
@$el.find('>').show()
preventDefaultContextMenu: (e) ->
return unless $(e.target).closest('#canvas-wrapper').length
@ -493,11 +502,10 @@ module.exports = class ThangsTabView extends CocoView
@selectAddThangType @selectedExtantThang.spriteName, @selectedExtantThang
toggleThangsContainer: (e) ->
$('#all-thangs').toggle()
$('#all-thangs').toggleClass('hide')
toggleThangsPalette: (e) ->
$('#add-thangs-column').toggle()
@onWindowResize e
$('#add-thangs-view').toggleClass('hide')
class ThangsNode extends TreemaNode.nodeMap.array
valueClass: 'treema-array-replacement'
@ -526,11 +534,8 @@ class ThangNode extends TreemaObjectNode
s = "#{data.thangType}"
if isObjectID s
unless name = ThangNode.thangNameMap[s]
thangType = _.find @settings.supermodel.getModels(ThangType), (m) -> m.get('original') is s and m.get('kind')
thangType = _.find @settings.supermodel.getModels(ThangType), (m) -> m.get('original') is s
name = ThangNode.thangNameMap[s] = thangType.get 'name'
ThangNode.thangKindMap[s] = thangType.get 'kind'
kind = ThangNode.thangKindMap[s]
@$el.addClass "treema-#{kind}"
s = name
s += ' - ' + data.id if data.id isnt s
if pos

View file

@ -136,6 +136,7 @@ module.exports = class ThangTypeColorsTabView extends CocoView
onColorGroupsChanged: =>
@thangType.set('colorGroups', @colorGroups.data)
Backbone.Mediator.publish 'editor:thang-type-color-groups-changed', colorGroups: @colorGroups.data
onColorGroupSelected: (e, selected) =>
@$el.find('#color-group-settings').toggle selected.length > 0

View file

@ -44,6 +44,7 @@ module.exports = class ThangTypeEditView extends RootView
'keyup .play-with-level-input': 'onPlayLevelKeyUp'
subscriptions:
'editor:thang-type-color-groups-changed': 'onColorGroupsChanged'
'editor:save-new-version': 'saveNewThangType'
# init / render
@ -102,6 +103,11 @@ module.exports = class ThangTypeEditView extends RootView
onComponentsChanged: (components) =>
@thangType.set 'components', components
onColorGroupsChanged: (e) ->
@temporarilyIgnoringChanges = true
@treema.set 'colorGroups', e.colorGroups
@temporarilyIgnoringChanges = false
makeDot: (color) ->
circle = new createjs.Shape()
circle.graphics.beginFill(color).beginStroke('black').drawCircle(0, 0, 5)
@ -383,6 +389,7 @@ module.exports = class ThangTypeEditView extends RootView
@lastKind = data.kind
pushChangesToPreview: =>
return if @temporarilyIgnoringChanges
# TODO: This doesn't delete old Treema keys you deleted
for key, value of @treema.data
@thangType.set(key, value)