Full-screen playback during real-time mode.

This commit is contained in:
Nick Winter 2014-08-23 13:54:52 -07:00
parent f2adb7ec7f
commit c79541f669
7 changed files with 91 additions and 12 deletions

View file

@ -196,7 +196,8 @@ module.exports = class LevelBus extends Bus
onNewGoalStates: ({goalStates})->
state = @session.get 'state'
unless utils.kindaEqual state.goalStates, goalStates # Only save when goals really change
unless utils.kindaEqual state.goalStates, goalStates # Only save when goals really change
# TODO: this log doesn't capture when null-status goals are being set during world streaming. Where can they be coming from?
return console.error("Somehow trying to save null goal states!", goalStates) if _.find(goalStates, (gs) -> not gs.status)
state.goalStates = goalStates
@session.set 'state', state

View file

@ -67,6 +67,8 @@ module.exports = Surface = class Surface extends CocoClass
'level-set-letterbox': 'onSetLetterbox'
'application:idle-changed': 'onIdleChanged'
'camera:zoom-updated': 'onZoomUpdated'
'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
shortcuts:
'ctrl+\\, ⌘+\\': 'onToggleDebug'
@ -82,7 +84,7 @@ module.exports = Surface = class Surface extends CocoClass
@options = _.extend(@options, givenOptions) if givenOptions
@initEasel()
@initAudio()
@onResize = _.debounce @onResize, 500
@onResize = _.debounce @onResize, 250
$(window).on 'resize', @onResize
if @world.ended
_.defer => @setWorld @world
@ -367,7 +369,8 @@ module.exports = Surface = class Surface extends CocoClass
@setWorld event.world
@onFrameChanged(true)
if @playing and (ffToFrame = Math.min(event.firstChangedFrame, @frameBeforeCast, event.world.frames.length)) and ffToFrame > @currentFrame
fastForwardBuffer = 2 # Make sure that real-time playback doesn't need to buffer more than this many seconds.
if @playing and (ffToFrame = Math.min(event.firstChangedFrame, @frameBeforeCast, event.world.frames.length)) and ffToFrame > @currentFrame + fastForwardBuffer * @world.frameRate
@fastForwardingToFrame = ffToFrame
@fastForwardingSpeed = Math.max 4, 4 * 90 / (@world.maxTotalFrames * @world.dt)
@ -402,8 +405,17 @@ module.exports = Surface = class Surface extends CocoClass
onResize: (e) =>
oldWidth = parseInt @canvas.attr('width'), 10
oldHeight = parseInt @canvas.attr('height'), 10
newWidth = @canvas.width()
newHeight = @canvas.height()
aspectRatio = oldWidth / oldHeight
pageWidth = $('#page-container').width() - 17 # 17px nano scroll bar
if @realTime
pageHeight = $('#page-container').height() - $('#control-bar-view').outerHeight() - $('#playback-view').outerHeight()
newWidth = Math.min pageWidth, pageHeight * aspectRatio
newHeight = newWidth / aspectRatio
else
newWidth = 0.55 * pageWidth
newHeight = newWidth / aspectRatio
@canvas.width newWidth
@canvas.height newHeight
return unless newWidth > 0 and newHeight > 0
#if InstallTrigger? # Firefox rendering performance goes down as canvas size goes up
# newWidth = Math.min 924, newWidth
@ -600,6 +612,15 @@ module.exports = Surface = class Surface extends CocoClass
++@totalFramesDrawn
@stage.update e
# Real-time playback
onRealTimePlaybackStarted: (e) ->
@realTime = true
@onResize()
onRealTimePlaybackEnded: (e) ->
@realTime = false
@onResize()
# paths - TODO: move to SpriteBoss? but only update on frame drawing instead of on every frame update?
updatePaths: ->

View file

@ -105,6 +105,14 @@ module.exports =
'playback:manually-scrubbed':
{} # TODO schema
'playback:real-time-playback-started':
type: 'object'
additionalProperties: false
'playback:real-time-playback-ended':
type: 'object'
additionalProperties: false
'change:editor-config':
{} # TODO schema

View file

@ -10,6 +10,28 @@ body.is-playing
margin: 0 auto
@include user-select(none)
&.real-time
// Hmm, somehow the #page-container is cutting us off by ~17px on the right, looks a bit off.
#canvas-wrapper
width: 100%
canvas#surface
margin: 0 auto
#control-bar-view, #playback-view
width: 100%
#code-area, #thang-hud, #goals-view
display: none
visibility: hidden
#gold-view
right: 1%
#control-bar-view .title
left: 0
width: 100%
text-align: center
.level-content
margin: 0px auto
.level-content
position: relative
@ -17,12 +39,13 @@ body.is-playing
width: 55%
position: relative
overflow: hidden
@include transition(0.5s ease-out)
canvas#surface
background-color: #333
width: 100%
display: block
z-index: 1
@include transition(0.5s ease-out)
min-width: 1024px
position: relative

View file

@ -19,11 +19,11 @@
.title
position: absolute
display: inline-block
margin-left: 50%
right: 0
color: #BEBEBE
line-height: 15px
left: 0
width: 100%
text-align: center
max-width: 1920px
margin: 0 auto

View file

@ -24,6 +24,7 @@ module.exports = class LevelPlaybackView extends CocoView
'god:new-world-created': 'onNewWorld'
'god:streaming-world-updated': 'onNewWorld' # Maybe?
'level-set-letterbox': 'onSetLetterbox'
'tome:cast-spells': 'onTomeCast'
events:
'click #debug-toggle': 'onToggleDebug'
@ -151,10 +152,19 @@ module.exports = class LevelPlaybackView extends CocoView
@$el.find('#music-button').toggleClass('music-on', me.get('music'))
onSetLetterbox: (e) ->
buttons = @$el.find '#play-button, .scrubber-handle'
buttons.css 'visibility', if e.on then 'hidden' else 'visible'
@togglePlaybackControls !e.on
@disabled = e.on
togglePlaybackControls: (to) ->
buttons = @$el.find '#play-button, .scrubber-handle'
buttons.css 'visibility', if to then 'visible' else 'hidden'
onTomeCast: (e) ->
return unless e.realTime
@realTime = true
@togglePlaybackControls false
Backbone.Mediator.publish 'playback:real-time-playback-started', {}
onWindowResize: (s...) =>
@barWidth = $('.progress', @$el).width()
@ -276,11 +286,16 @@ module.exports = class LevelPlaybackView extends CocoView
updateProgress: (progress, world) ->
if world.frames.length isnt @lastLoadedFrameCount
@updateBarWidth world.frames.length, world.maxTotalFrames, world.dt
@worldCompletelyLoaded = world.frames.length is world.totalFrames
$('.scrubber .progress-bar', @$el).css('width', "#{progress * 100}%")
updatePlayButton: (progress) ->
if progress >= 0.99 and @lastProgress < 0.99
if @worldCompletelyLoaded and progress >= 0.99 and @lastProgress < 0.99
$('#play-button').removeClass('playing').removeClass('paused').addClass('ended')
if @realTime
@realTime = false
@togglePlaybackControls true
Backbone.Mediator.publish 'playback:real-time-playback-ended', {}
if progress < 0.99 and @lastProgress >= 0.99
b = $('#play-button').removeClass('ended')
if @playing then b.addClass('playing') else b.addClass('paused')
@ -326,7 +341,7 @@ module.exports = class LevelPlaybackView extends CocoView
return if @shouldIgnore()
Backbone.Mediator.publish 'level-set-time', ratio: ratio, scrubDuration: duration
shouldIgnore: -> return @disabled
shouldIgnore: -> return @disabled or @realTime
onTogglePlay: (e) ->
e?.preventDefault()

View file

@ -64,6 +64,8 @@ module.exports = class PlayLevelView extends RootView
'level:set-team': 'setTeam'
'level:started': 'onLevelStarted'
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
events:
'click #level-done-button': 'onDonePressed'
@ -513,6 +515,15 @@ module.exports = class PlayLevelView extends RootView
continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
AudioPlayer.preloadSoundReference sound
# Real-time playback
onRealTimePlaybackStarted: (e) ->
@$el.addClass 'real-time'
@onWindowResize()
onRealTimePlaybackEnded: (e) ->
@$el.removeClass 'real-time'
@onWindowResize()
destroy: ->
@levelLoader?.destroy()
@surface?.destroy()