2014-07-17 20:16:32 -04:00
|
|
|
RootView = require 'views/kinds/RootView'
|
2014-01-03 13:32:13 -05:00
|
|
|
template = require 'templates/editor/level/edit'
|
|
|
|
Level = require 'models/Level'
|
|
|
|
LevelSystem = require 'models/LevelSystem'
|
|
|
|
World = require 'lib/world/world'
|
|
|
|
DocumentFiles = require 'collections/DocumentFiles'
|
2014-04-25 19:14:05 -04:00
|
|
|
LevelLoader = require 'lib/LevelLoader'
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-07-23 10:02:45 -04:00
|
|
|
ThangsTabView = require './thangs/ThangsTabView'
|
|
|
|
SettingsTabView = require './settings/SettingsTabView'
|
|
|
|
ScriptsTabView = require './scripts/ScriptsTabView'
|
|
|
|
ComponentsTabView = require './components/ComponentsTabView'
|
|
|
|
SystemsTabView = require './systems/SystemsTabView'
|
|
|
|
SaveLevelModal = require './modals/SaveLevelModal'
|
2014-08-13 14:36:00 -04:00
|
|
|
ForkModal = require 'views/editor/ForkModal'
|
2014-07-23 10:02:45 -04:00
|
|
|
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
|
|
|
PatchesView = require 'views/editor/PatchesView'
|
2014-08-08 11:14:57 -04:00
|
|
|
RelatedAchievementsView = require 'views/editor/level/RelatedAchievementsView'
|
2014-07-23 10:02:45 -04:00
|
|
|
VersionHistoryView = require './modals/LevelVersionsModal'
|
2014-08-29 01:32:55 -04:00
|
|
|
ComponentsDocumentationView = require 'views/docs/ComponentsDocumentationView'
|
|
|
|
SystemsDocumentationView = require 'views/docs/SystemsDocumentationView'
|
2014-08-31 02:04:45 -04:00
|
|
|
LevelFeedbackView = require 'views/editor/level/LevelFeedbackView'
|
2014-08-30 17:30:53 -04:00
|
|
|
storage = require 'lib/storage'
|
2014-07-23 10:02:45 -04:00
|
|
|
|
|
|
|
module.exports = class LevelEditView extends RootView
|
2014-06-30 22:16:26 -04:00
|
|
|
id: 'editor-level-view'
|
2014-08-07 21:49:39 -04:00
|
|
|
className: 'editor'
|
2014-01-03 13:32:13 -05:00
|
|
|
template: template
|
|
|
|
cache: false
|
|
|
|
|
|
|
|
events:
|
|
|
|
'click #play-button': 'onPlayLevel'
|
2014-07-05 16:54:41 -04:00
|
|
|
'click .play-with-team-button': 'onPlayLevel'
|
2014-07-14 11:40:36 -04:00
|
|
|
'click .play-with-team-parent': 'onPlayLevelTeamSelect'
|
2014-01-03 13:32:13 -05:00
|
|
|
'click #commit-level-start-button': 'startCommittingLevel'
|
2014-08-13 14:36:00 -04:00
|
|
|
'click #fork-start-button': 'startForking'
|
2014-04-17 14:29:12 -04:00
|
|
|
'click #level-history-button': 'showVersionHistory'
|
2014-07-24 15:36:41 -04:00
|
|
|
'click #undo-button': 'onUndo'
|
2014-08-10 20:03:39 -04:00
|
|
|
'mouseenter #undo-button': 'showUndoDescription'
|
2014-07-24 15:36:41 -04:00
|
|
|
'click #redo-button': 'onRedo'
|
2014-08-10 20:03:39 -04:00
|
|
|
'mouseenter #redo-button': 'showRedoDescription'
|
2014-04-12 11:48:49 -04:00
|
|
|
'click #patches-tab': -> @patchesView.load()
|
2014-08-04 16:21:42 -04:00
|
|
|
'click #components-tab': -> @subviews.editor_level_components_tab_view.refreshLevelThangsTreema @level.get('thangs')
|
2014-04-17 16:37:08 -04:00
|
|
|
'click #level-patch-button': 'startPatchingLevel'
|
2014-04-17 14:35:09 -04:00
|
|
|
'click #level-watch-button': 'toggleWatchLevel'
|
2014-04-22 20:56:41 -04:00
|
|
|
'click #pop-level-i18n-button': -> @level.populateI18N()
|
2014-08-29 01:32:55 -04:00
|
|
|
'click a[href="#editor-level-documentation"]': 'onClickDocumentationTab'
|
2014-04-21 15:15:22 -04:00
|
|
|
'mouseup .nav-tabs > li a': 'toggleTab'
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
constructor: (options, @levelID) ->
|
|
|
|
super options
|
2014-01-26 17:46:25 -05:00
|
|
|
@supermodel.shouldSaveBackups = (model) ->
|
2014-07-17 18:50:29 -04:00
|
|
|
model.constructor.className in ['Level', 'LevelComponent', 'LevelSystem', 'ThangType']
|
2014-08-25 18:39:47 -04:00
|
|
|
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, headless: true
|
2014-04-25 22:11:32 -04:00
|
|
|
@level = @levelLoader.level
|
2014-04-25 19:14:05 -04:00
|
|
|
@files = new DocumentFiles(@levelLoader.level)
|
2014-04-26 15:54:03 -04:00
|
|
|
@supermodel.loadCollection(@files, 'file_names')
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
showLoading: ($el) ->
|
2014-04-25 19:14:05 -04:00
|
|
|
$el ?= @$el.find('.outer-content')
|
2014-01-03 13:32:13 -05:00
|
|
|
super($el)
|
|
|
|
|
2014-04-25 22:11:32 -04:00
|
|
|
onLoaded: ->
|
|
|
|
_.defer =>
|
|
|
|
@world = @levelLoader.world
|
|
|
|
@render()
|
|
|
|
|
2014-02-11 17:58:45 -05:00
|
|
|
getRenderData: (context={}) ->
|
2014-01-03 13:32:13 -05:00
|
|
|
context = super(context)
|
|
|
|
context.level = @level
|
2014-03-03 14:41:35 -05:00
|
|
|
context.authorized = me.isAdmin() or @level.hasWriteAccess(me)
|
2014-03-04 05:24:38 -05:00
|
|
|
context.anonymous = me.get('anonymous')
|
2014-08-30 17:30:53 -04:00
|
|
|
context.recentlyPlayedOpponents = storage.load('recently-played-matches')?[@levelID] ? []
|
2014-01-03 13:32:13 -05:00
|
|
|
context
|
|
|
|
|
|
|
|
afterRender: ->
|
|
|
|
super()
|
2014-04-25 19:14:05 -04:00
|
|
|
return unless @supermodel.finished()
|
2014-01-30 19:36:36 -05:00
|
|
|
@$el.find('a[data-toggle="tab"]').on 'shown.bs.tab', (e) =>
|
2014-08-31 02:04:45 -04:00
|
|
|
Backbone.Mediator.publish 'editor:view-switched', {targetURL: $(e.target).attr('href')}
|
2014-08-04 16:21:42 -04:00
|
|
|
@insertSubView new ThangsTabView world: @world, supermodel: @supermodel, level: @level
|
|
|
|
@insertSubView new SettingsTabView supermodel: @supermodel
|
|
|
|
@insertSubView new ScriptsTabView world: @world, supermodel: @supermodel, files: @files
|
|
|
|
@insertSubView new ComponentsTabView supermodel: @supermodel
|
2014-09-18 18:26:06 -04:00
|
|
|
@insertSubView new SystemsTabView supermodel: @supermodel, world: @world
|
2014-08-08 11:14:57 -04:00
|
|
|
@insertSubView new RelatedAchievementsView supermodel: @supermodel, level: @level
|
2014-08-31 02:04:45 -04:00
|
|
|
@insertSubView new ComponentsDocumentationView lazy: true # Don't give it the supermodel, it'll pollute it!
|
|
|
|
@insertSubView new SystemsDocumentationView lazy: true # Don't give it the supermodel, it'll pollute it!
|
|
|
|
@insertSubView new LevelFeedbackView level: @level
|
2014-08-04 16:21:42 -04:00
|
|
|
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'editor:level-loaded', level: @level
|
2014-04-12 11:48:49 -04:00
|
|
|
@showReadOnly() if me.get('anonymous')
|
|
|
|
@patchesView = @insertSubView(new PatchesView(@level), @$el.find('.patches-view'))
|
2014-07-03 20:41:34 -04:00
|
|
|
@listenTo @patchesView, 'accepted-patch', -> location.reload()
|
2014-04-17 14:35:09 -04:00
|
|
|
@$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching()
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-07-14 11:40:36 -04:00
|
|
|
onPlayLevelTeamSelect: (e) ->
|
|
|
|
if @childWindow and not @childWindow.closed
|
|
|
|
# We already have a child window open, so we don't need to ask for a team; we'll use its existing team.
|
|
|
|
e.stopImmediatePropagation()
|
|
|
|
@onPlayLevel e
|
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
onPlayLevel: (e) ->
|
2014-07-05 16:54:41 -04:00
|
|
|
team = $(e.target).data('team')
|
2014-08-30 17:30:53 -04:00
|
|
|
opponentSessionID = $(e.target).data('opponent')
|
2014-01-03 13:32:13 -05:00
|
|
|
sendLevel = =>
|
2014-08-27 15:24:03 -04:00
|
|
|
@childWindow.Backbone.Mediator.publish 'level:reload-from-data', level: @level, supermodel: @supermodel
|
2014-01-03 13:32:13 -05:00
|
|
|
if @childWindow and not @childWindow.closed
|
|
|
|
# Reset the LevelView's world, but leave the rest of the state alone
|
|
|
|
sendLevel()
|
|
|
|
else
|
|
|
|
# Create a new Window with a blank LevelView
|
2014-06-30 22:16:26 -04:00
|
|
|
scratchLevelID = @level.get('slug') + '?dev=true'
|
2014-07-05 16:54:41 -04:00
|
|
|
scratchLevelID += "&team=#{team}" if team
|
2014-08-30 17:30:53 -04:00
|
|
|
scratchLevelID += "&opponent=#{opponentSessionID}" if opponentSessionID
|
2014-08-10 20:47:18 -04:00
|
|
|
if me.get('name') is 'Nick'
|
2014-07-19 23:26:13 -04:00
|
|
|
@childWindow = window.open("/play/level/#{scratchLevelID}", 'child_window', 'width=2560,height=1080,left=0,top=-1600,location=1,menubar=1,scrollbars=1,status=0,titlebar=1,toolbar=1', true)
|
|
|
|
else
|
|
|
|
@childWindow = window.open("/play/level/#{scratchLevelID}", 'child_window', 'width=1024,height=560,left=10,top=10,location=0,menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0', true)
|
2014-01-03 13:32:13 -05:00
|
|
|
@childWindow.onPlayLevelViewLoaded = (e) => sendLevel() # still a hack
|
|
|
|
@childWindow.focus()
|
|
|
|
|
2014-07-24 15:36:41 -04:00
|
|
|
onUndo: ->
|
2014-08-12 21:26:03 -04:00
|
|
|
TreemaNode.getLastTreemaWithFocus()?.undo()
|
2014-07-24 15:36:41 -04:00
|
|
|
|
|
|
|
onRedo: ->
|
2014-08-12 21:26:03 -04:00
|
|
|
TreemaNode.getLastTreemaWithFocus()?.redo()
|
2014-07-24 15:36:41 -04:00
|
|
|
|
2014-08-10 20:03:39 -04:00
|
|
|
showUndoDescription: ->
|
2014-08-12 21:26:03 -04:00
|
|
|
undoDescription = TreemaNode.getLastTreemaWithFocus().getUndoDescription()
|
|
|
|
@$el.find('#undo-button').attr('title', 'Undo ' + undoDescription + ' (Ctrl+Z)')
|
2014-08-10 20:03:39 -04:00
|
|
|
|
|
|
|
showRedoDescription: ->
|
2014-08-12 21:26:03 -04:00
|
|
|
redoDescription = TreemaNode.getLastTreemaWithFocus().getRedoDescription()
|
|
|
|
@$el.find('#redo-button').attr('title', 'Redo ' + redoDescription + ' (Ctrl+Shift+Z)')
|
2014-07-24 15:36:41 -04:00
|
|
|
|
|
|
|
getCurrentView: ->
|
2014-09-02 19:58:34 -04:00
|
|
|
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)]
|
2014-07-24 15:36:41 -04:00
|
|
|
|
2014-04-12 11:48:49 -04:00
|
|
|
startPatchingLevel: (e) ->
|
2014-06-30 22:16:26 -04:00
|
|
|
@openModalView new SaveVersionModal({model: @level})
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'editor:view-switched', {}
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
startCommittingLevel: (e) ->
|
2014-07-23 10:02:45 -04:00
|
|
|
@openModalView new SaveLevelModal level: @level, supermodel: @supermodel
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'editor:view-switched', {}
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-08-13 14:36:00 -04:00
|
|
|
startForking: (e) ->
|
|
|
|
@openModalView new ForkModal model: @level, editorPath: 'level'
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'editor:view-switched', {}
|
2014-03-10 07:16:08 -04:00
|
|
|
|
|
|
|
showVersionHistory: (e) ->
|
2014-06-30 22:16:26 -04:00
|
|
|
versionHistoryView = new VersionHistoryView level: @level, @levelID
|
2014-03-10 07:16:08 -04:00
|
|
|
@openModalView versionHistoryView
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'editor:view-switched', {}
|
2014-04-15 18:09:36 -04:00
|
|
|
|
|
|
|
toggleWatchLevel: ->
|
2014-04-17 14:35:09 -04:00
|
|
|
button = @$el.find('#level-watch-button')
|
2014-04-15 18:09:36 -04:00
|
|
|
@level.watch(button.find('.watch').is(':visible'))
|
2014-04-15 18:18:57 -04:00
|
|
|
button.find('> span').toggleClass('secret')
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-04-21 15:15:22 -04:00
|
|
|
toggleTab: (e) ->
|
2014-05-24 02:11:28 -04:00
|
|
|
@renderScrollbar()
|
2014-04-21 15:15:22 -04:00
|
|
|
return unless $(document).width() <= 800
|
|
|
|
li = $(e.target).closest('li')
|
|
|
|
if li.hasClass('active')
|
|
|
|
li.parent().find('li').show()
|
|
|
|
else
|
|
|
|
li.parent().find('li').hide()
|
|
|
|
li.show()
|
|
|
|
console.log li.hasClass('active')
|
2014-08-29 01:32:55 -04:00
|
|
|
|
|
|
|
onClickDocumentationTab: (e) ->
|
|
|
|
# It's either too late at night or something is going on with Bootstrap nested tabs, so we do the click instead of using .active.
|
|
|
|
return if @initializedDocs
|
|
|
|
@initializedDocs = true
|
|
|
|
@$el.find('a[href="#components-documentation-view"]').click()
|