mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 15:48:11 -05:00
Refactored and improved the ThangComponentsEditView and ThangComponentConfigView. Still some things to do.
This commit is contained in:
parent
9a1dd412c9
commit
6cac2371c1
25 changed files with 597 additions and 584 deletions
|
@ -3,7 +3,7 @@ c = require './../schemas'
|
|||
module.exports = ThangComponentSchema = c.object {
|
||||
title: 'Component'
|
||||
description: 'Configuration for a Component that this Thang uses.'
|
||||
format: 'thang-component'
|
||||
format: 'component-reference'
|
||||
required: ['original', 'majorVersion']
|
||||
'default':
|
||||
majorVersion: 0
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#component-config-column-view
|
||||
h3
|
||||
float: left
|
||||
#add-remove-button
|
||||
float: right
|
||||
margin: 5px
|
||||
#description
|
||||
clear: both
|
||||
|
||||
.treema
|
||||
position: absolute
|
||||
left: 5px
|
||||
right: 5px
|
||||
top: 90px
|
||||
bottom: 0
|
||||
overflow: scroll
|
|
@ -0,0 +1 @@
|
|||
//.thang-component-config-view
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#extant-components-column
|
||||
left: 0
|
||||
width: 20%
|
||||
width: 300px
|
||||
|
||||
.treema
|
||||
position: absolute
|
||||
|
@ -28,27 +28,24 @@
|
|||
right: 10px
|
||||
bottom: 0
|
||||
overflow: scroll
|
||||
|
||||
.dependent
|
||||
background-color: rgba(128, 64, 255, 0.10)
|
||||
|
||||
#add-component-column
|
||||
right: 0
|
||||
width: 20%
|
||||
|
||||
.treema
|
||||
position: absolute
|
||||
top: 75px
|
||||
left: 10px
|
||||
right: 0px
|
||||
bottom: 0
|
||||
overflow: scroll
|
||||
|
||||
.treema-row
|
||||
line-height: 24px
|
||||
.add-button
|
||||
margin-left: 10px
|
||||
|
||||
#component-config-column-view
|
||||
#thang-components-config-column
|
||||
border-left: 1px solid black
|
||||
border-right: 1px solid black
|
||||
right: 20%
|
||||
left: 20%
|
||||
right: 0
|
||||
left: 300px
|
||||
min-width: 600px
|
||||
|
||||
h3
|
||||
margin-left: 20px
|
||||
|
||||
#thang-component-configs
|
||||
position: absolute
|
||||
top: 80px
|
||||
bottom: 0
|
||||
right: 0
|
||||
left: 20px
|
||||
overflow: scroll
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
#editor-level-view
|
||||
&, #level-editor-top-nav
|
||||
// min-width: 1024px
|
||||
|
||||
a
|
||||
font-family: helvetica, arial, sans serif
|
||||
.editor
|
||||
h1, h2, h3, h4, h5, h6, a
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important
|
||||
|
||||
position: absolute
|
||||
top: 0px
|
||||
|
@ -48,7 +45,7 @@
|
|||
border-radius: 0
|
||||
.navbar-right
|
||||
// not sure why bootstrap puts a big negative margin in, but this overrides it
|
||||
margin-right: 10px
|
||||
margin-right: 10px !important
|
||||
float: right
|
||||
|
||||
.dropdown-menu
|
||||
|
@ -130,9 +127,7 @@
|
|||
margin-top: -10px
|
||||
padding-top: 10px
|
||||
|
||||
// keeps the editor tabs a certain height
|
||||
|
||||
#level-editor-tabs
|
||||
#level-editor-tabs, #thang-type-edit-view .tab-content
|
||||
position: absolute
|
||||
left: 15px
|
||||
right: 15px
|
|
@ -1,85 +0,0 @@
|
|||
#editor-thang-type-edit-view
|
||||
#save-button, #revert-button
|
||||
float: right
|
||||
margin-right: 20px
|
||||
|
||||
#portrait
|
||||
float: right
|
||||
|
||||
.main-area
|
||||
padding: 5px
|
||||
& > div.slider-cell
|
||||
margin-right: 5px
|
||||
float: right
|
||||
.file-controls
|
||||
float: left
|
||||
position: relative
|
||||
top: 5px
|
||||
left: 5px
|
||||
button
|
||||
margin-left: 5px
|
||||
select
|
||||
position: relative
|
||||
top: 5px
|
||||
input
|
||||
display: none
|
||||
|
||||
.slider-cell
|
||||
margin: 5px 0
|
||||
float: left
|
||||
width: 120px
|
||||
|
||||
.selector
|
||||
display: inline-block
|
||||
width: 100px
|
||||
position: relative
|
||||
top: 3px
|
||||
|
||||
#marker-button, #end-button
|
||||
float: right
|
||||
margin-right: 10px
|
||||
position: relative
|
||||
top: 15px
|
||||
|
||||
#canvas
|
||||
float: right
|
||||
width: 400px
|
||||
border: 1px solid blue
|
||||
background-color: lightgray
|
||||
|
||||
#settings-col
|
||||
float: left
|
||||
width: 550px
|
||||
|
||||
.treema-row img
|
||||
max-width: 100%
|
||||
|
||||
#thang-type-treema
|
||||
height: 400px
|
||||
overflow: scroll
|
||||
box-sizing: border-box
|
||||
|
||||
|
||||
#thang-components-edit-view
|
||||
position: absolute
|
||||
top: 200px
|
||||
bottom: 0
|
||||
|
||||
.treema-root
|
||||
background-color: white
|
||||
border-radius: 4px
|
||||
|
||||
|
||||
|
||||
#spritesheets
|
||||
border: 1px solid green
|
||||
max-width: 100%
|
||||
max-height: 600px
|
||||
overflow: scroll
|
||||
clear: both
|
||||
box-sizing: border-box
|
||||
margin-bottom: 20px
|
||||
canvas
|
||||
background: darkseagreen
|
||||
margin: 2px
|
||||
|
92
app/styles/editor/thang/thang-type-edit-view.sass
Normal file
92
app/styles/editor/thang/thang-type-edit-view.sass
Normal file
|
@ -0,0 +1,92 @@
|
|||
#thang-type-edit-view
|
||||
#portrait
|
||||
float: left
|
||||
margin: 5px
|
||||
width: 100px
|
||||
height: 100px
|
||||
|
||||
#settings-col
|
||||
width: 560px
|
||||
position: absolute
|
||||
left: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
|
||||
.file-controls
|
||||
float: left
|
||||
position: relative
|
||||
top: 5px
|
||||
left: 5px
|
||||
button
|
||||
margin-left: 5px
|
||||
input
|
||||
display: none
|
||||
|
||||
.treema-row img
|
||||
max-width: 100%
|
||||
|
||||
.treema-root
|
||||
overflow: scroll
|
||||
box-sizing: border-box
|
||||
position: absolute
|
||||
top: 160px
|
||||
bottom: 20px
|
||||
right: 20px
|
||||
left: 20px
|
||||
|
||||
#display-col
|
||||
position: absolute
|
||||
width: 440px
|
||||
left: 580px
|
||||
top: 0
|
||||
bottom: 0
|
||||
overflow: hidden
|
||||
|
||||
& > div.slider-cell
|
||||
margin-right: 5px
|
||||
|
||||
canvas
|
||||
width: 400px
|
||||
border: 1px solid blue
|
||||
background-color: lightgray
|
||||
|
||||
select
|
||||
margin-top: 10px
|
||||
|
||||
#marker-button, #end-button
|
||||
margin: 10px 10px 10px 0
|
||||
|
||||
.slider-cell
|
||||
margin: 5px 0
|
||||
width: 195px
|
||||
float: left
|
||||
|
||||
.selector
|
||||
display: inline-block
|
||||
width: 180px
|
||||
position: relative
|
||||
top: 3px
|
||||
|
||||
|
||||
#thang-components-edit-view
|
||||
position: absolute
|
||||
top: 0px
|
||||
bottom: 0
|
||||
|
||||
.treema-root
|
||||
background-color: white
|
||||
border-radius: 4px
|
||||
|
||||
|
||||
|
||||
#spritesheets
|
||||
position: absolute
|
||||
top: 0
|
||||
bottom: 0
|
||||
left: 0
|
||||
right: 0
|
||||
border: 1px solid green
|
||||
overflow: scroll
|
||||
canvas
|
||||
background: darkseagreen
|
||||
|
|
@ -10,9 +10,6 @@
|
|||
&, & > div.ace_editor
|
||||
width: 100%
|
||||
|
||||
& > div.ace_editor
|
||||
height: 400px
|
||||
|
||||
.treema-markdown.treema-display, .treema-coffee.treema-display, .treema-javascript.treema-display
|
||||
width: 100%
|
||||
border: 3px inset rgba(0, 100, 100, 0.2)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
h3= component.name
|
||||
//button.btn#add-remove-button Add Component
|
||||
p#description= component.description
|
||||
.treema
|
||||
//p#other-props
|
||||
// strong Other Config Properties:
|
||||
// for prop in configProperties
|
||||
// a(title=prop.description)= prop.name
|
|
@ -1,11 +0,0 @@
|
|||
#extant-components-column.column
|
||||
h3 Components
|
||||
p Click then press delete to remove.
|
||||
.treema
|
||||
|
||||
#component-config-column-view.column
|
||||
|
||||
#add-component-column.column
|
||||
h3 Add Components
|
||||
p Click then press enter to add.
|
||||
.treema
|
|
@ -0,0 +1,7 @@
|
|||
.panel.panel-default
|
||||
.panel-heading
|
||||
strong.panel-title= component.name
|
||||
em.spl.spr (#{component.system})
|
||||
span#description= component.description
|
||||
.panel-body
|
||||
.treema
|
|
@ -0,0 +1,9 @@
|
|||
#extant-components-column.column
|
||||
h3 Components
|
||||
p Click then press delete to remove.
|
||||
.treema
|
||||
|
||||
.column#thang-components-config-column
|
||||
h3 Component Configurations
|
||||
#thang-component-configs
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
div
|
||||
ol.breadcrumb
|
||||
li
|
||||
a(href="/editor", data-i18n="editor.main_title") CodeCombat Editors
|
||||
li
|
||||
a(href="/editor/thang", data-i18n="editor.thang_title") Thang Editor
|
||||
li.active
|
||||
| #{thangType.attributes.name}
|
||||
|
||||
img#portrait.img-thumbnail
|
||||
|
||||
button.btn.btn-secondary#history-button(data-i18n="general.version_history") Version History
|
||||
button.btn.btn-primary#save-button(data-i18n="common.save", disabled=authorized === true ? undefined : "true") Save
|
||||
button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert
|
||||
|
||||
h3 Edit Thang Type: "#{thangType.attributes.name}"
|
||||
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(href="#editor-thang-main-tab-view", data-toggle="tab") Main
|
||||
li
|
||||
a(href="#editor-thang-components-tab-view", data-toggle="tab") Components
|
||||
li
|
||||
a(href="#editor-thang-spritesheets-view", data-toggle="tab") Spritesheets
|
||||
li
|
||||
a(href="#editor-thang-colors-tab-view", data-toggle="tab")#color-tab Colors
|
||||
li
|
||||
a(href="#editor-thang-patches-view", data-toggle="tab")#patches-tab Patches
|
||||
|
||||
div.tab-content
|
||||
div.tab-pane#editor-thang-colors-tab-view
|
||||
|
||||
div.tab-pane#editor-thang-main-tab-view.active
|
||||
|
||||
div.main-area.well
|
||||
div.file-controls
|
||||
select#animations-select
|
||||
for animation in animations
|
||||
option #{animation}
|
||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#upload-button
|
||||
i.icon-upload
|
||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#clear-button
|
||||
i.icon-remove
|
||||
input#real-upload-button(type="file")
|
||||
|
||||
button.btn.btn-small.btn-primary#marker-button
|
||||
i.icon-map-marker
|
||||
|
||||
button.btn.btn-small.btn-primary#end-button
|
||||
i.icon-stop
|
||||
|
||||
div.slider-cell
|
||||
| Rotation:
|
||||
span.rotation-label
|
||||
.selector#rotation-slider
|
||||
div.slider-cell
|
||||
| Scale:
|
||||
span.scale-label
|
||||
.selector#scale-slider
|
||||
div.slider-cell
|
||||
| Resolution:
|
||||
span.resolution-label 4.0x
|
||||
.selector#resolution-slider
|
||||
div.slider-cell
|
||||
| Health:
|
||||
span.health-label 10hp
|
||||
.selector#health-slider
|
||||
|
||||
.clearfix
|
||||
|
||||
div#settings-col
|
||||
div#thang-type-treema
|
||||
|
||||
canvas#canvas(width="400", height="400")
|
||||
|
||||
.clearfix
|
||||
|
||||
div.tab-pane#editor-thang-components-tab-view
|
||||
|
||||
#thang-components-edit-view
|
||||
|
||||
div.tab-pane#editor-thang-spritesheets-view
|
||||
|
||||
div#spritesheets
|
||||
|
||||
div.tab-pane#editor-thang-patches-view
|
||||
|
||||
div.patches-view
|
||||
|
||||
div#error-view
|
||||
|
||||
.clearfix
|
124
app/templates/editor/thang/thang-type-edit-view.jade
Normal file
124
app/templates/editor/thang/thang-type-edit-view.jade
Normal file
|
@ -0,0 +1,124 @@
|
|||
extends /templates/base
|
||||
block header
|
||||
if thangType.loading
|
||||
nav.navbar.navbar-default(role='navigation')#thang-editor-top-nav
|
||||
.container-fluid
|
||||
ul.nav.navbar-nav
|
||||
li
|
||||
a(href="/editor/thang")
|
||||
span.glyphicon-home.glyphicon
|
||||
else
|
||||
nav.navbar.navbar-default(role='navigation')#thang-editor-top-nav
|
||||
ul.nav.navbar-nav
|
||||
li
|
||||
a(href="/editor/thang")
|
||||
span.glyphicon-home.glyphicon
|
||||
ul.nav.navbar-nav.nav-tabs
|
||||
li.active
|
||||
a(href="#editor-thang-main-tab-view", data-toggle="tab") Main
|
||||
li
|
||||
a(href="#editor-thang-components-tab-view", data-toggle="tab") Components
|
||||
li
|
||||
a(href="#editor-thang-spritesheets-view", data-toggle="tab") Spritesheets
|
||||
li
|
||||
a(href="#editor-thang-colors-tab-view", data-toggle="tab")#color-tab Colors
|
||||
li
|
||||
a(href="#editor-thang-patches-view", data-toggle="tab")#patches-tab
|
||||
span(data-i18n="resources.patches").spr Patches
|
||||
- var patches = thangType.get('patches')
|
||||
if patches && patches.length
|
||||
span.badge= patches.length
|
||||
|
||||
.navbar-header
|
||||
span.navbar-brand #{thangType.attributes.name}
|
||||
|
||||
ul.nav.navbar-nav.navbar-right
|
||||
if authorized
|
||||
li#save-button
|
||||
a
|
||||
span.glyphicon-floppy-disk.glyphicon
|
||||
li.dropdown
|
||||
a(data-toggle='dropdown')
|
||||
span.glyphicon-chevron-down.glyphicon
|
||||
ul.dropdown-menu
|
||||
li.dropdown-header Actions
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert
|
||||
li.divider
|
||||
li.dropdown-header Info
|
||||
li#history-button
|
||||
a(href='#', data-i18n="general.version_history") Version History
|
||||
li.divider
|
||||
li.dropdown-header Help
|
||||
li
|
||||
a(href='https://github.com/codecombat/codecombat/wiki/Artisan-Home', data-i18n="editor.wiki", target="_blank") Wiki
|
||||
li
|
||||
a(href='http://www.hipchat.com/g3plnOKqa', data-i18n="editor.live_chat", target="_blank") Live Chat
|
||||
li
|
||||
a(href='http://discourse.codecombat.com/category/artisan', data-i18n="nav.forum", target="_blank") Forum
|
||||
li
|
||||
a(data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Email
|
||||
|
||||
block outer_content
|
||||
.outer-content
|
||||
div.tab-content
|
||||
div.tab-pane#editor-thang-colors-tab-view
|
||||
div.tab-pane#editor-thang-main-tab-view.active
|
||||
div#settings-col.well
|
||||
img#portrait.img-thumbnail
|
||||
div.file-controls
|
||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-info#upload-button
|
||||
span.glyphicon.glyphicon-upload
|
||||
span.spl Upload Animation
|
||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-danger#clear-button
|
||||
span.glyphicon.glyphicon-remove
|
||||
span.spl Clear Data
|
||||
input#real-upload-button(type="file")
|
||||
div#thang-type-treema
|
||||
.clearfix
|
||||
div#display-col.well
|
||||
canvas#canvas(width="400", height="400")
|
||||
select#animations-select.form-control
|
||||
for animation in animations
|
||||
option #{animation}
|
||||
div
|
||||
button.btn.btn-small.btn-primary#marker-button
|
||||
i.icon-map-marker
|
||||
span.spl Markers
|
||||
button.btn.btn-small.btn-primary#end-button
|
||||
i.icon-stop
|
||||
span.spl Stop
|
||||
div.slider-cell
|
||||
| Rotation:
|
||||
span.rotation-label
|
||||
.selector#rotation-slider
|
||||
div.slider-cell
|
||||
| Scale:
|
||||
span.scale-label
|
||||
.selector#scale-slider
|
||||
div.slider-cell
|
||||
| Resolution:
|
||||
span.resolution-label 4.0x
|
||||
.selector#resolution-slider
|
||||
div.slider-cell
|
||||
| Health:
|
||||
span.health-label 10hp
|
||||
.selector#health-slider
|
||||
|
||||
div.tab-pane#editor-thang-components-tab-view
|
||||
#thang-components-edit-view
|
||||
div.tab-pane#editor-thang-spritesheets-view
|
||||
div#spritesheets
|
||||
div.tab-pane#editor-thang-patches-view
|
||||
div.patches-view
|
||||
div#error-view
|
||||
.clearfix
|
||||
block footer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -225,14 +225,8 @@ class CodeTreema extends TreemaNode.nodeMap.ace
|
|||
super(valEl)
|
||||
if not @schema.aceMode and mode = codeLanguages[@keyForParent]
|
||||
@editor.getSession().setMode mode
|
||||
@editor.on('change', @onEditorChange)
|
||||
valEl
|
||||
|
||||
onEditorChange: =>
|
||||
@saveChanges()
|
||||
@flushChanges()
|
||||
@getRoot().broadcastChanges()
|
||||
|
||||
class CoffeeTreema extends CodeTreema
|
||||
constructor: ->
|
||||
super(arguments...)
|
||||
|
@ -307,27 +301,20 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
input = valEl.find('input')
|
||||
input.focus().keyup @search
|
||||
input.attr('placeholder', @formatDocument(@data)) if @data
|
||||
|
||||
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=true"
|
||||
|
||||
search: =>
|
||||
term = @getValEl().find('input').val()
|
||||
return if term is @lastTerm
|
||||
|
||||
# HACK while search is broken
|
||||
if @collection
|
||||
@lastTerm = term
|
||||
@searchCallback()
|
||||
return
|
||||
|
||||
@getSearchResultsEl().empty() if @lastTerm and not term
|
||||
return unless term
|
||||
@lastTerm = term
|
||||
@getSearchResultsEl().empty().append('Searching')
|
||||
@collection = new LatestVersionCollection([], model: @model)
|
||||
|
||||
# HACK while search is broken
|
||||
# @collection.url = "#{@url}?term=#{term}&project=true"
|
||||
@collection.url = "#{@url}?term=#{''}&project=true"
|
||||
|
||||
@collection.url = @buildSearchURL(term)
|
||||
@collection.fetch()
|
||||
@collection.once 'sync', @searchCallback, @
|
||||
|
||||
|
@ -338,10 +325,6 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
row = $('<div></div>').addClass('treema-search-result-row')
|
||||
text = @formatDocument(model)
|
||||
continue unless text?
|
||||
|
||||
# HACK while search is broken
|
||||
continue unless text.toLowerCase().indexOf(@lastTerm.toLowerCase()) >= 0
|
||||
|
||||
row.addClass('treema-search-selected') if first
|
||||
first = false
|
||||
row.text(text)
|
||||
|
@ -353,10 +336,11 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
|
||||
getSearchResultsEl: -> @getValEl().find('.treema-search-results')
|
||||
getSelectedResultEl: -> @getValEl().find('.treema-search-selected')
|
||||
|
||||
modelToString: (model) -> model.get('name')
|
||||
|
||||
formatDocument: (docOrModel) ->
|
||||
doc = docOrModel.attributes or docOrModel
|
||||
return doc.name if doc.name?
|
||||
return @modelToString(docOrModel) if docOrModel instanceof CocoModel
|
||||
return 'Unknown' unless @settings.supermodel?
|
||||
m = CocoModel.getReferencedModel(@data, @schema)
|
||||
urlGoingFor = m.url()
|
||||
|
@ -366,7 +350,7 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
m.url = -> urlGoingFor
|
||||
@settings.supermodel.registerModel(m)
|
||||
return 'Unknown' unless m
|
||||
return m.get('name')
|
||||
return @modelToString(m)
|
||||
|
||||
saveChanges: ->
|
||||
selected = @getSelectedResultEl()
|
||||
|
@ -379,10 +363,12 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
@instance = fullValue
|
||||
|
||||
onDownArrowPressed: (e) ->
|
||||
return super(arguments...) unless @isEditing()
|
||||
@navigateSearch(1)
|
||||
e.preventDefault()
|
||||
|
||||
onUpArrowPressed: (e) ->
|
||||
return super(arguments...) unless @isEditing()
|
||||
e.preventDefault()
|
||||
@navigateSearch(-1)
|
||||
|
||||
|
@ -410,7 +396,14 @@ class LatestVersionReferenceNode extends TreemaNode
|
|||
return if @data?
|
||||
selected = @getSelectedResultEl()
|
||||
return not selected.length
|
||||
|
||||
|
||||
class LevelComponentReferenceNode extends LatestVersionReferenceNode
|
||||
# HACK: this list of properties is needed by the thang components edit view and config views.
|
||||
# need a better way to specify this, or keep the search models from bleeding into those
|
||||
# supermodels.
|
||||
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=name,system,original,version,dependencies,configSchema,description"
|
||||
modelToString: (model) -> model.get('system') + '.' + model.get('name')
|
||||
canEdit: -> not @data.original # only allow editing if the row's data hasn't been set yet
|
||||
|
||||
LatestVersionReferenceNode.prototype.search = _.debounce(LatestVersionReferenceNode.prototype.search, 200)
|
||||
|
||||
|
@ -431,6 +424,7 @@ module.exports.setup = ->
|
|||
TreemaNode.setNodeSubclass('javascript', JavaScriptTreema)
|
||||
TreemaNode.setNodeSubclass('image-file', ImageFileTreema)
|
||||
TreemaNode.setNodeSubclass('latest-version-reference', LatestVersionReferenceNode)
|
||||
TreemaNode.setNodeSubclass('component-reference', LevelComponentReferenceNode)
|
||||
TreemaNode.setNodeSubclass('i18n', InternationalizationNode)
|
||||
TreemaNode.setNodeSubclass('sound-file', SoundFileTreema)
|
||||
TreemaNode.setNodeSubclass 'slug-props', SlugPropsObject
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/editor/components/config'
|
||||
template = require 'templates/editor/components/thang-component-config-view'
|
||||
|
||||
Level = require 'models/Level'
|
||||
LevelComponent = require 'models/LevelComponent'
|
||||
nodes = require '../level/treema_nodes'
|
||||
|
||||
module.exports = class ThangComponentConfigView extends CocoView
|
||||
id: 'component-config-column-view'
|
||||
className: 'thang-component-config-view'
|
||||
template: template
|
||||
className: 'column'
|
||||
changed: false
|
||||
|
||||
events:
|
||||
'click .treema-shortened': -> console.log 'clicked treema root'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
@ -17,12 +19,11 @@ module.exports = class ThangComponentConfigView extends CocoView
|
|||
@config = options.config or {}
|
||||
@world = options.world
|
||||
@level = options.level
|
||||
@editing = options.editing
|
||||
@callback = options.callback
|
||||
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
context.component = @component
|
||||
context.component = @component.attributes
|
||||
context.configProperties = []
|
||||
context
|
||||
|
||||
|
@ -38,7 +39,7 @@ module.exports = class ThangComponentConfigView extends CocoView
|
|||
superteams = _.union(teams, superteams)
|
||||
treemaOptions =
|
||||
supermodel: @supermodel
|
||||
schema: @component.configSchema
|
||||
schema: @component.attributes.configSchema
|
||||
data: _.cloneDeep @config
|
||||
callbacks: {change: @onConfigEdited}
|
||||
world: @world
|
||||
|
@ -58,16 +59,16 @@ module.exports = class ThangComponentConfigView extends CocoView
|
|||
'seconds': nodes.SecondsNode
|
||||
'speed': nodes.SpeedNode
|
||||
'acceleration': nodes.AccelerationNode
|
||||
treemaOptions.readOnly = not @editing
|
||||
|
||||
@editThangTreema = @$el.find('.treema').treema treemaOptions
|
||||
@editThangTreema.build()
|
||||
@editThangTreema.open(2)
|
||||
@hideLoading()
|
||||
if _.isEqual(@config, {}) and not @editThangTreema.canAddChild()
|
||||
@$el.find('.panel-body').hide()
|
||||
|
||||
onConfigEdited: =>
|
||||
@changed = true
|
||||
@callback?(@data())
|
||||
@trigger 'changed', { component: @component, config: @data() }
|
||||
|
||||
undo: ->
|
||||
@editThangTreema.undo()
|
||||
|
|
|
@ -1,284 +0,0 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/editor/components/main'
|
||||
|
||||
Level = require 'models/Level'
|
||||
LevelComponent = require 'models/LevelComponent'
|
||||
LevelSystem = require 'models/LevelSystem'
|
||||
ComponentsCollection = require 'collections/ComponentsCollection'
|
||||
ComponentConfigView = require './ThangComponentConfigView'
|
||||
|
||||
module.exports = class ThangComponentEditView extends CocoView
|
||||
id: 'thang-components-edit-view'
|
||||
template: template
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@components = options.components or []
|
||||
@world = options.world
|
||||
@level = options.level
|
||||
@callback = options.callback
|
||||
@componentCollection = @supermodel.loadCollection(new ComponentsCollection(), 'components').model
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
return unless @supermodel.finished()
|
||||
@buildExtantComponentTreema()
|
||||
@buildAddComponentTreema()
|
||||
|
||||
buildExtantComponentTreema: ->
|
||||
level = new Level()
|
||||
treemaOptions =
|
||||
supermodel: @supermodel
|
||||
schema: level.schema().properties.thangs.items.properties.components
|
||||
data: _.cloneDeep @components
|
||||
callbacks: {select: @onSelectExtantComponent, change: @onChangeExtantComponents}
|
||||
noSortable: true
|
||||
nodeClasses:
|
||||
'thang-components-array': ThangComponentsArrayNode
|
||||
'thang-component': ThangComponentNode
|
||||
|
||||
@extantComponentsTreema = @$el.find('#extant-components-column .treema').treema treemaOptions
|
||||
@extantComponentsTreema.build()
|
||||
@$el.find('#extant-components-column .treema').droppable({
|
||||
drop: =>
|
||||
@onAddComponentEnterPressed @selectedRow
|
||||
})
|
||||
|
||||
buildAddComponentTreema: ->
|
||||
return unless @componentCollection and @extantComponentsTreema
|
||||
extantComponents = @extantComponentsTreema.data
|
||||
componentsUsedCount = extantComponents.length
|
||||
return if @lastComponentsUsedCount is componentsUsedCount
|
||||
@lastComponentsUsedCount = componentsUsedCount
|
||||
components = (m.attributes for m in @componentCollection.models)
|
||||
_.remove components, (comp) =>
|
||||
_.find extantComponents, {original: comp.original} # already have this one added
|
||||
components = _.sortBy components, (comp) -> comp.system + '.' + comp.name
|
||||
|
||||
treemaOptions =
|
||||
supermodel: @supermodel
|
||||
schema: {type: 'array', items: LevelComponent.schema}
|
||||
data: ($.extend(true, {}, c) for c in components)
|
||||
callbacks: {
|
||||
select: @onSelectAddableComponent
|
||||
enter: @onAddComponentEnterPressed
|
||||
dblclick: @onAddComponentDoubleClicked
|
||||
mouseenter: @onAddComponentMouseEnter
|
||||
mouseleave: @onAddComponentMouseLeave
|
||||
}
|
||||
readOnly: true
|
||||
noSortable: true
|
||||
nodeClasses:
|
||||
'array': ComponentArrayNode
|
||||
'object': ComponentNode
|
||||
# I have no idea why it's not building in the Thang Editor unless I defer
|
||||
_.defer (=>
|
||||
@addComponentsTreema = @$el.find('#add-component-column .treema').treema treemaOptions
|
||||
@addComponentsTreema.build()
|
||||
@$el.find('#add-component-column .treema-node').draggable({
|
||||
revert: 'invalid'
|
||||
helper: 'clone'
|
||||
appendTo: 'body'
|
||||
start: (e) ->
|
||||
# Hack to ensure dragged treema node is selected
|
||||
$(@).trigger('click') unless $(@).hasClass 'treema-selected'
|
||||
})
|
||||
@hideLoading()
|
||||
), 500
|
||||
|
||||
onSelectAddableComponent: (e, selected) =>
|
||||
@extantComponentsTreema.deselectAll()
|
||||
@onComponentSelected(selected, false)
|
||||
|
||||
onSelectExtantComponent: (e, selected) =>
|
||||
return if @updatingFromConfig
|
||||
@addComponentsTreema.deselectAll()
|
||||
@onComponentSelected(selected, true)
|
||||
|
||||
onComponentSelected: (selected, extant=true) ->
|
||||
return if @alreadySaving # handle infinite loops
|
||||
@alreadySaving = true
|
||||
@closeExistingView()
|
||||
@alreadySaving = false
|
||||
|
||||
return unless selected.length
|
||||
|
||||
# select dependencies.
|
||||
node = selected[0]
|
||||
original = node.data.original
|
||||
|
||||
toRemoveTreema = []
|
||||
dependent_class = 'treema-dependent'
|
||||
try
|
||||
for index, child of @extantComponentsTreema.childrenTreemas
|
||||
$(child.$el).removeClass(dependent_class)
|
||||
|
||||
for index, child of @extantComponentsTreema.childrenTreemas
|
||||
if child.data.original == original # Here we assume that the treemas are sorted by their dependency.
|
||||
break
|
||||
|
||||
dep_originals = (d.original for d in child.component.attributes.dependencies)
|
||||
for dep_original in dep_originals
|
||||
if original == dep_original
|
||||
toRemoveTreema.push child
|
||||
|
||||
for dep_treema in toRemoveTreema
|
||||
dep_treema.toggleSelect()
|
||||
$(dep_treema.$el).addClass(dependent_class)
|
||||
|
||||
catch error
|
||||
console.error error
|
||||
|
||||
return unless selected.length
|
||||
row = selected[0]
|
||||
@selectedRow = row
|
||||
component = row.component?.attributes or row.data
|
||||
config = if extant then row.data?.config else {}
|
||||
@configView = new ComponentConfigView({
|
||||
supermodel: @supermodel
|
||||
level: @level
|
||||
world: @world
|
||||
config: config
|
||||
component: component
|
||||
editing: extant
|
||||
callback: @onComponentConfigChanged
|
||||
})
|
||||
@insertSubView @configView
|
||||
|
||||
closeExistingView: ->
|
||||
return unless @configView
|
||||
data = @configView.data()
|
||||
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
||||
@removeSubView @configView
|
||||
@configView = null
|
||||
|
||||
onComponentConfigChanged: (data) =>
|
||||
@updatingFromConfig = true
|
||||
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
||||
@updatingFromConfig = false
|
||||
|
||||
onChangeExtantComponents: =>
|
||||
@buildAddComponentTreema()
|
||||
@reportChanges()
|
||||
|
||||
onAddComponentEnterPressed: (node) =>
|
||||
if extantSystems
|
||||
extantSystems =
|
||||
(@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems')
|
||||
requireSystem = node.data.system.toLowerCase()
|
||||
|
||||
if requireSystem not in extantSystems
|
||||
warn_element = 'Component <b>' + node.data.name + '</b> requires system <b>' + requireSystem + '</b> which is currently not specified in this level.'
|
||||
noty({
|
||||
text: warn_element,
|
||||
layout: 'bottomLeft',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
id = node.data._id
|
||||
comp = _.find @componentCollection.models, id: id
|
||||
unless comp
|
||||
return console.error 'Couldn\'t find component for id', id, 'out of', @components.models
|
||||
# Add all dependencies, recursively, unless we already have them
|
||||
toAdd = comp.getDependencies(@componentCollection.models)
|
||||
_.remove toAdd, (c1) =>
|
||||
_.find @extantComponentsTreema.data, (c2) ->
|
||||
c2.original is c1.get('original')
|
||||
for c in toAdd.concat [comp]
|
||||
@extantComponentsTreema.insert '/', {
|
||||
original: c.get('original') ? id
|
||||
majorVersion: c.get('version').major ? 0
|
||||
}
|
||||
|
||||
# reselect newly added child treema in the extantComponentsTreema
|
||||
for index, treema of @extantComponentsTreema.childrenTreemas
|
||||
if treema.component.id is id
|
||||
_.defer =>
|
||||
treema.select()
|
||||
@onSelectExtantComponent({}, [treema])
|
||||
return
|
||||
|
||||
onAddComponentDoubleClicked: (e, treema) =>
|
||||
@onAddComponentEnterPressed treema
|
||||
|
||||
onAddComponentMouseEnter: (e, treema) ->
|
||||
treema.$el.find('.add-button').show()
|
||||
|
||||
onAddComponentMouseLeave: (e, treema) ->
|
||||
treema.$el.find('.add-button').hide()
|
||||
return
|
||||
|
||||
reportChanges: ->
|
||||
@callback?($.extend(true, [], @extantComponentsTreema.data))
|
||||
|
||||
undo: ->
|
||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.undo() else @configView.undo()
|
||||
|
||||
redo: ->
|
||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.redo() else @configView.redo()
|
||||
|
||||
class ThangComponentsArrayNode extends TreemaArrayNode
|
||||
valueClass: 'treema-thang-components-array'
|
||||
editable: false
|
||||
sort: true
|
||||
canAddChild: -> false
|
||||
|
||||
sortFunction: (a, b) =>
|
||||
a = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, a.original, a.majorVersion)
|
||||
b = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, b.original, b.majorVersion)
|
||||
return 1 if a.attributes.system > b.attributes.system
|
||||
return -1 if a.attributes.system < b.attributes.system
|
||||
return 1 if a.name > b.name
|
||||
return -1 if a.name < b.name
|
||||
return 0
|
||||
|
||||
class ThangComponentNode extends TreemaObjectNode
|
||||
valueClass: 'treema-thang-component'
|
||||
collection: false
|
||||
|
||||
constructor: ->
|
||||
super(arguments...)
|
||||
@grabDBComponent()
|
||||
|
||||
grabDBComponent: ->
|
||||
@component = @settings.supermodel.getModelByOriginalAndMajorVersion LevelComponent, @data.original, @data.majorVersion
|
||||
console.error 'Couldn\'t find comp for', @data.original, @data.majorVersion, 'from models', @settings.supermodel.models unless @component
|
||||
|
||||
buildValueForDisplay: (valEl) ->
|
||||
return super valEl unless @data.original and @component
|
||||
s = @component.get('system') + '.' + @component.get('name')
|
||||
@buildValueForDisplaySimply valEl, s
|
||||
|
||||
class ComponentArrayNode extends TreemaArrayNode
|
||||
editable: false
|
||||
sort: true
|
||||
canAddChild: -> false
|
||||
|
||||
sortFunction: (a, b) =>
|
||||
return 1 if a.system > b.system
|
||||
return -1 if a.system < b.system
|
||||
return 1 if a.name > b.name
|
||||
return -1 if a.name < b.name
|
||||
return 0
|
||||
|
||||
class ComponentNode extends TreemaObjectNode
|
||||
valueClass: 'treema-component'
|
||||
addButtonTemplate: '<button type="button" class="add-button btn btn-default btn-xs"><span class="glyphicon glyphicon-plus"></span></button>'
|
||||
collection: false
|
||||
|
||||
build: ->
|
||||
super()
|
||||
@$el.find('> .treema-row').append @addButtonTemplate
|
||||
addButton = @$el.find('.add-button')
|
||||
addButton.hide()
|
||||
addButton.click =>
|
||||
@callbacks.enter?(@)
|
||||
@$el
|
||||
|
||||
buildValueForDisplay: (valEl) ->
|
||||
s = @data.system + '.' + @data.name
|
||||
@buildValueForDisplaySimply valEl, s
|
||||
|
||||
onEnterPressed: (args...) ->
|
||||
super(args...)
|
||||
@callbacks.enter?(@)
|
282
app/views/editor/component/ThangComponentsEditView.coffee
Normal file
282
app/views/editor/component/ThangComponentsEditView.coffee
Normal file
|
@ -0,0 +1,282 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/editor/components/thang-components-edit-view'
|
||||
|
||||
Level = require 'models/Level'
|
||||
LevelComponent = require 'models/LevelComponent'
|
||||
LevelSystem = require 'models/LevelSystem'
|
||||
ComponentsCollection = require 'collections/ComponentsCollection'
|
||||
ThangComponentConfigView = require './ThangComponentConfigView'
|
||||
|
||||
module.exports = class ThangComponentsEditView extends CocoView
|
||||
id: 'thang-components-edit-view'
|
||||
template: template
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@components = options.components or []
|
||||
@components = $.extend true, [], @components # just to be sure
|
||||
@lastComponentLength = @components.length
|
||||
@world = options.world
|
||||
@level = options.level
|
||||
@callback = options.callback # TODO: Switch to 'trigger'
|
||||
@loadComponents(@components)
|
||||
|
||||
loadComponents: (components) ->
|
||||
for componentRef in components
|
||||
levelComponent = new LevelComponent()
|
||||
url = "/db/level.component/#{componentRef.original}/version/#{componentRef.majorVersion}"
|
||||
levelComponent.setURL(url)
|
||||
resource = @supermodel.loadModel levelComponent, 'component'
|
||||
@listenToOnce resource, 'loaded', ->
|
||||
return if @handlingChange
|
||||
if @supermodel.finished()
|
||||
@handlingChange = true
|
||||
@onComponentsAdded()
|
||||
@handlingChange = false
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
return unless @supermodel.finished()
|
||||
@buildExtantComponentsTreema()
|
||||
@addThangComponentConfigViews()
|
||||
|
||||
buildExtantComponentsTreema: ->
|
||||
treemaOptions =
|
||||
supermodel: @supermodel
|
||||
schema: Level.schema.properties.thangs.items.properties.components
|
||||
data: $.extend true, [], @components
|
||||
callbacks: {select: @onSelectComponent, change: @onComponentsTreemaChanged}
|
||||
noSortable: true
|
||||
nodeClasses:
|
||||
'thang-components-array': ThangComponentsArrayNode
|
||||
|
||||
@extantComponentsTreema = @$el.find('#extant-components-column .treema').treema treemaOptions
|
||||
@extantComponentsTreema.build()
|
||||
|
||||
onComponentsTreemaChanged: =>
|
||||
return if @handlingChange
|
||||
@handlingChange = true
|
||||
componentMap = {}
|
||||
for component in @components
|
||||
componentMap[component.original] = component
|
||||
|
||||
newComponentsList = []
|
||||
for component in @extantComponentsTreema.data
|
||||
newComponentsList.push(componentMap[component.original] or component)
|
||||
@components = newComponentsList
|
||||
|
||||
# update the components list here
|
||||
@onComponentsChanged()
|
||||
@handlingChange = false
|
||||
|
||||
onComponentsChanged: =>
|
||||
# happens whenever the list of components changed, one way or another
|
||||
# * if the treema gets changed
|
||||
# * if components are added externally, like by a modal
|
||||
# * if a dependency loads and is added to the list
|
||||
|
||||
# TODO: Disallow editing components in the list, otherwise this system breaks.
|
||||
|
||||
if @components.length < @lastComponentLength
|
||||
@onComponentsRemoved()
|
||||
else
|
||||
@onComponentsAdded()
|
||||
|
||||
@lastComponentLength = @components.length
|
||||
|
||||
onComponentsRemoved: ->
|
||||
componentMap = {}
|
||||
for component in @components
|
||||
componentMap[component.original] = component
|
||||
|
||||
# Deleting components missing dependencies.
|
||||
while true
|
||||
removedSomething = false
|
||||
for componentRef in _.values(componentMap)
|
||||
componentModel = @supermodel.getModelByOriginalAndMajorVersion(
|
||||
LevelComponent, componentRef.original, componentRef.majorVersion)
|
||||
for dependency in componentModel.get('dependencies') or []
|
||||
if not componentMap[dependency.original]
|
||||
delete componentMap[componentRef.original]
|
||||
component = @supermodel.getModelByOriginal(
|
||||
LevelComponent, componentRef.original)
|
||||
noty {
|
||||
text: "Removed dependent component: #{component.get('name')}"
|
||||
layout: 'topCenter'
|
||||
timeout: 5000
|
||||
type: 'information'
|
||||
}
|
||||
removedSomething = true
|
||||
break if removedSomething
|
||||
break unless removedSomething
|
||||
|
||||
@components = _.values(componentMap)
|
||||
|
||||
# Delete individual component config views that are no longer included.
|
||||
for subview in _.values(@subviews)
|
||||
continue unless subview instanceof ThangComponentConfigView
|
||||
if not componentMap[subview.component.get('original')]
|
||||
@removeSubView(subview)
|
||||
|
||||
@updateComponentsList()
|
||||
@reportChanges()
|
||||
|
||||
updateComponentsList: ->
|
||||
@extantComponentsTreema?.set('/', $.extend(true, [], @components))
|
||||
|
||||
onComponentsAdded: ->
|
||||
componentMap = {}
|
||||
for component in @components
|
||||
componentMap[component.original] = component
|
||||
|
||||
# Go through the map, adding missing dependencies.
|
||||
while true
|
||||
addedSomething = false
|
||||
for componentRef in _.values(componentMap)
|
||||
componentModel = @supermodel.getModelByOriginalAndMajorVersion(
|
||||
LevelComponent, componentRef.original, componentRef.majorVersion)
|
||||
for dependency in componentModel.get('dependencies') or []
|
||||
if not componentMap[dependency.original]
|
||||
component = @supermodel.getModelByOriginalAndMajorVersion(
|
||||
LevelComponent, dependency.original, dependency.majorVersion)
|
||||
if not component
|
||||
@loadComponents([dependency])
|
||||
# will run onComponentsAdded once more when the model loads
|
||||
else
|
||||
addedSomething = true
|
||||
noty {
|
||||
text: "Added dependency: #{component.get('name')}"
|
||||
layout: 'topCenter'
|
||||
timeout: 5000
|
||||
type: 'information'
|
||||
}
|
||||
componentMap[dependency.original] = dependency
|
||||
@components.push dependency
|
||||
break unless addedSomething
|
||||
|
||||
|
||||
# Sort the component list, reorder the component config views
|
||||
@updateComponentsList()
|
||||
@addThangComponentConfigViews()
|
||||
@reportChanges()
|
||||
|
||||
addThangComponentConfigViews: ->
|
||||
# Detach all component config views temporarily.
|
||||
componentConfigViews = {}
|
||||
for subview in _.values(@subviews)
|
||||
continue unless subview instanceof ThangComponentConfigView
|
||||
componentConfigViews[subview.component.get('original')] = subview
|
||||
subview.$el.detach()
|
||||
|
||||
# Put back config views into the DOM based on the component list ordering,
|
||||
# adding and registering new ones as needed.
|
||||
configsEl = @$el.find('#thang-component-configs')
|
||||
for componentRef in @extantComponentsTreema.data
|
||||
subview = componentConfigViews[componentRef.original]
|
||||
if not subview
|
||||
subview = @makeThangComponentConfigView(componentRef)
|
||||
continue unless subview
|
||||
@registerSubView(subview)
|
||||
configsEl.append(subview.$el)
|
||||
|
||||
makeThangComponentConfigView: (thangComponent) ->
|
||||
component = @supermodel.getModelByOriginal(LevelComponent, thangComponent.original)
|
||||
return unless component
|
||||
config = thangComponent.config ? {}
|
||||
configView = new ThangComponentConfigView({
|
||||
supermodel: @supermodel
|
||||
level: @level
|
||||
world: @world
|
||||
config: config
|
||||
component: component
|
||||
})
|
||||
configView.render()
|
||||
@listenTo configView, 'changed', @onConfigChanged
|
||||
configView
|
||||
|
||||
onConfigChanged: (e) ->
|
||||
for thangComponent in @components
|
||||
if thangComponent.original is e.component.get('original')
|
||||
thangComponent.config = e.config
|
||||
@reportChanges()
|
||||
|
||||
onSelectComponent: (e, nodes) =>
|
||||
@extantComponentsTreema.$el.find('.dependent').removeClass('dependent')
|
||||
return unless nodes.length is 1
|
||||
|
||||
# find dependent components
|
||||
dependents = {}
|
||||
dependents[nodes[0].data.original] = true
|
||||
componentsToCheck = [nodes[0].data.original]
|
||||
while componentsToCheck.length
|
||||
componentOriginal = componentsToCheck.pop()
|
||||
for otherComponentRef in @components
|
||||
continue if otherComponentRef.original is componentOriginal
|
||||
continue if dependents[otherComponentRef.original]
|
||||
otherComponent = @supermodel.getModelByOriginal(LevelComponent, otherComponentRef.original)
|
||||
for dependency in otherComponent.get('dependencies')
|
||||
if dependents[dependency.original]
|
||||
dependents[otherComponentRef.original] = true
|
||||
componentsToCheck.push otherComponentRef.original
|
||||
|
||||
# highlight them
|
||||
for child in _.values(@extantComponentsTreema.childrenTreemas)
|
||||
if dependents[child.data.original]
|
||||
child.$el.addClass('dependent')
|
||||
|
||||
# scroll to the config
|
||||
for subview in _.values(@subviews)
|
||||
continue unless subview instanceof ThangComponentConfigView
|
||||
if subview.component.get('original') is nodes[0].data.original
|
||||
subview.$el[0].scrollIntoView()
|
||||
break
|
||||
|
||||
onComponentConfigChanged: (data) =>
|
||||
@updatingFromConfig = true
|
||||
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
||||
@updatingFromConfig = false
|
||||
|
||||
onChangeExtantComponents: =>
|
||||
@buildAddComponentTreema()
|
||||
@reportChanges()
|
||||
|
||||
onAddComponentEnterPressed: (node) =>
|
||||
# TODO: Incorporate this logic when adding components
|
||||
if extantSystems
|
||||
extantSystems =
|
||||
(@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems')
|
||||
requireSystem = node.data.system.toLowerCase()
|
||||
|
||||
if requireSystem not in extantSystems
|
||||
warn_element = 'Component <b>' + node.data.name + '</b> requires system <b>' + requireSystem + '</b> which is currently not specified in this level.'
|
||||
noty({
|
||||
text: warn_element,
|
||||
layout: 'bottomLeft',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
reportChanges: ->
|
||||
@callback?($.extend(true, [], @components))
|
||||
|
||||
# TODO: Fix these.
|
||||
undo: ->
|
||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.undo() else @configView.undo()
|
||||
|
||||
redo: ->
|
||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.redo() else @configView.redo()
|
||||
|
||||
class ThangComponentsArrayNode extends TreemaArrayNode
|
||||
valueClass: 'treema-thang-components-array'
|
||||
sort: true
|
||||
|
||||
sortFunction: (a, b) =>
|
||||
a = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, a.original, a.majorVersion)
|
||||
b = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, b.original, b.majorVersion)
|
||||
return 0 if not (a or b)
|
||||
return 1 if not b
|
||||
return -1 if not a
|
||||
return 1 if a.attributes.system > b.attributes.system
|
||||
return -1 if a.attributes.system < b.attributes.system
|
||||
return 1 if a.name > b.name
|
||||
return -1 if a.name < b.name
|
||||
return 0
|
|
@ -20,6 +20,7 @@ ComponentDocsView = require 'views/docs/ComponentDocumentationView'
|
|||
|
||||
module.exports = class LevelEditView extends RootView
|
||||
id: 'editor-level-view'
|
||||
className: 'editor'
|
||||
template: template
|
||||
cache: false
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/editor/level/thang/edit'
|
||||
ThangComponentEditView = require 'views/editor/component/ThangComponentEditView'
|
||||
ThangComponentsEditView = require 'views/editor/component/ThangComponentsEditView'
|
||||
ThangType = require 'models/ThangType'
|
||||
|
||||
module.exports = class LevelThangEditView extends CocoView
|
||||
###
|
||||
In the level editor, is the bar at the top when editing a single thang.
|
||||
Everything below is part of the ThangComponentEditView, which is shared with the
|
||||
Everything below is part of the ThangComponentsEditView, which is shared with the
|
||||
ThangType editor view.
|
||||
###
|
||||
|
||||
|
@ -43,7 +43,7 @@ module.exports = class LevelThangEditView extends CocoView
|
|||
world: @world
|
||||
callback: @onComponentsChanged
|
||||
|
||||
@thangComponentEditView = new ThangComponentEditView options
|
||||
@thangComponentEditView = new ThangComponentsEditView options
|
||||
@insertSubView @thangComponentEditView
|
||||
thangTypeNames = (m.get('name') for m in @supermodel.getModels ThangType)
|
||||
input = @$el.find('#thang-type-link input').autocomplete(source: thangTypeNames, minLength: 0, delay: 0, autoFocus: true)
|
||||
|
|
|
@ -6,17 +6,18 @@ Camera = require 'lib/surface/Camera'
|
|||
DocumentFiles = require 'collections/DocumentFiles'
|
||||
|
||||
RootView = require 'views/kinds/RootView'
|
||||
ThangComponentEditView = require 'views/editor/component/ThangComponentEditView'
|
||||
ThangComponentsEditView = require 'views/editor/component/ThangComponentsEditView'
|
||||
ThangTypeVersionsModal = require './ThangTypeVersionsModal'
|
||||
ThangTypeColorsTabView = require './ThangTypeColorsTabView'
|
||||
PatchesView = require 'views/editor/PatchesView'
|
||||
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
||||
template = require 'templates/editor/thang/edit'
|
||||
template = require 'templates/editor/thang/thang-type-edit-view'
|
||||
|
||||
CENTER = {x: 200, y: 300}
|
||||
|
||||
module.exports = class ThangTypeEditView extends RootView
|
||||
id: 'editor-thang-type-edit-view'
|
||||
id: 'thang-type-edit-view'
|
||||
className: 'editor'
|
||||
template: template
|
||||
startsLoading: true
|
||||
resolution: 4
|
||||
|
@ -49,7 +50,6 @@ module.exports = class ThangTypeEditView extends RootView
|
|||
@thangType = @supermodel.loadModel(@thangType, 'thang').model
|
||||
@thangType.saveBackups = true
|
||||
@listenToOnce @thangType, 'sync', ->
|
||||
console.log 'files for?', @thangType.id, @thangType.get 'name'
|
||||
@files = @supermodel.loadCollection(new DocumentFiles(@thangType), 'files').model
|
||||
@refreshAnimation = _.debounce @refreshAnimation, 500
|
||||
|
||||
|
@ -82,7 +82,7 @@ module.exports = class ThangTypeEditView extends RootView
|
|||
components: @thangType.get('components') ? []
|
||||
supermodel: @supermodel
|
||||
callback: @onComponentsChanged
|
||||
@thangComponentEditView = new ThangComponentEditView options
|
||||
@thangComponentEditView = new ThangComponentsEditView options
|
||||
@insertSubView @thangComponentEditView
|
||||
|
||||
onComponentsChanged: (components) =>
|
||||
|
|
|
@ -86,6 +86,8 @@ module.exports = class CocoView extends Backbone.View
|
|||
|
||||
render: ->
|
||||
return @ unless me
|
||||
view.destroy() for id, view of @subviews
|
||||
@subviews = {}
|
||||
super()
|
||||
return @template if _.isString(@template)
|
||||
@$el.html @template(@getRenderData())
|
||||
|
@ -248,17 +250,29 @@ module.exports = class CocoView extends Backbone.View
|
|||
# Subviews
|
||||
|
||||
insertSubView: (view, elToReplace=null) ->
|
||||
key = view.id or (view.constructor.name+classCount++)
|
||||
key = _.string.underscored(key) # handy for autocomplete in dev console
|
||||
# used to insert views with ids
|
||||
key = @makeSubViewKey(view)
|
||||
@subviews[key].destroy() if key of @subviews
|
||||
elToReplace ?= @$el.find('#'+view.id)
|
||||
elToReplace.after(view.el).remove()
|
||||
view.parent = @
|
||||
@registerSubView(view, key)
|
||||
view.render()
|
||||
view.afterInsert()
|
||||
view
|
||||
|
||||
registerSubView: (view, key) ->
|
||||
# used to register views which are custom inserted into the view,
|
||||
# like views where you add multiple instances of them
|
||||
key = @makeSubViewKey(view)
|
||||
view.parent = @
|
||||
view.parentKey = key
|
||||
@subviews[key] = view
|
||||
view
|
||||
|
||||
makeSubViewKey: (view) ->
|
||||
key = view.id or (view.constructor.name+classCount++)
|
||||
key = _.string.underscored(key) # handy for autocomplete in dev console
|
||||
key
|
||||
|
||||
removeSubView: (view) ->
|
||||
view.$el.empty()
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"jsondiffpatch": "~0.1.5",
|
||||
"nanoscroller": "~0.8.0",
|
||||
"jquery.tablesorter": "~2.15.13",
|
||||
"treema": "~0.0.9",
|
||||
"treema": "~0.0.12",
|
||||
"bootstrap": "~3.1.1",
|
||||
"validated-backbone-mediator": "~0.1.3",
|
||||
"jquery.browser": "~0.0.6",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
describe 'require', ->
|
||||
it 'has no modules that error when you import them', ->
|
||||
modules = window.require.list();
|
||||
modules = window.require.list()
|
||||
for module in modules
|
||||
try
|
||||
require(module)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
module.exports.sendTestResponses = (responseMap) ->
|
||||
|
Loading…
Reference in a new issue