Several improvements to hover debugging.

This commit is contained in:
Nick Winter 2014-01-24 13:03:04 -08:00
parent 9b9df12ea0
commit 6fa38bd889
8 changed files with 969 additions and 22 deletions

File diff suppressed because one or more lines are too long

View file

@ -114,4 +114,7 @@ class Rectangle
@deserialize: (o, world, classMap) ->
new Rectangle o.x, o.y, o.w, o.h, o.r
serializeForAether: -> @serialize()
@deserializeFromAether: (o) -> @deserialize o
module.exports = Rectangle

View file

@ -158,6 +158,9 @@ module.exports = class Thang
t[prop] = val
t
serializeForAether: ->
{CN: @constructor.className, id: @id}
getSpriteOptions: ->
colorConfigs = @world?.getTeamColors() or {}
options = {}

View file

@ -119,4 +119,7 @@ class Vector
@deserialize: (o, world, classMap) ->
new Vector o.x, o.y, o.z
serializeForAether: -> @serialize()
@deserializeFromAether: (o) -> @deserialize o
module.exports = Vector

View file

@ -61,9 +61,9 @@
.executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
position: absolute
.executing
background-color: rgba(216, 255, 255, 0.55)
background-color: rgba(216, 255, 255, 0.85)
.executed
background-color: rgba(216, 255, 255, 0.25)
background-color: rgba(200, 200, 255, 0.25)
.problem-marker-info
background-color: rgba(96, 63, 84, 0.25)
.problem-marker-warning

View file

@ -1,16 +1,25 @@
View = require 'views/kinds/CocoView'
template = require 'templates/play/level/tome/spell_debug'
Range = ace.require("ace/range").Range
TokenIterator = ace.require("ace/token_iterator").TokenIterator
serializedClasses =
Thang: require "lib/world/thang"
Vector: require "lib/world/vector"
Rectangle: require "lib/world/rectangle"
module.exports = class DebugView extends View
className: 'spell-debug-view'
template: template
subscriptions: {}
subscriptions:
'god:new-world-created': 'onNewWorld'
events: {}
constructor: (options) ->
super options
@ace = options.ace
@thang = options.thang
@variableStates = {}
afterRender: ->
@ -23,29 +32,44 @@ module.exports = class DebugView extends View
onMouseMove: (e) =>
pos = e.getDocumentPosition()
column = pos.column
until column < 0
if token = e.editor.session.getTokenAt pos.row, column
break if token.type is 'identifier'
column = token.start - 1
else
--column
if token?.type is 'identifier' and token.value of @variableStates
@variable = token.value
it = new TokenIterator e.editor.session, pos.row, pos.column
isIdentifier = (t) -> t and (t.type is 'identifier' or t.value is 'this')
while it.getCurrentTokenRow() is pos.row and not isIdentifier(token = it.getCurrentToken())
it.stepBackward()
break unless token
if isIdentifier token
# This could be a property access, like "enemy.target.pos" or "this.spawnedRectangles".
# We have to realize this and dig into the nesting of the objects.
start = it.getCurrentTokenColumn()
[chain, start, end] = [[token.value], start, start + token.value.length]
while it.getCurrentTokenRow() is pos.row
it.stepBackward()
break unless it.getCurrentToken()?.value is "."
it.stepBackward()
token = null # If we're doing a complex access like this.getEnemies().length, then length isn't a valid var.
break unless isIdentifier(prev = it.getCurrentToken())
token = prev
start = it.getCurrentTokenColumn()
chain.unshift token.value
if token and (token.value of @variableStates or token.value is "this")
@variableChain = chain
@pos = {left: e.domEvent.offsetX + 50, top: e.domEvent.offsetY + 50}
@markerRange = new Range pos.row, token.start, pos.row, token.start + token.value.length
@markerRange = new Range pos.row, start, pos.row, end
else
@variable = @markerRange = null
@variableChain = @markerRange = null
@update()
onMouseOut: (e) =>
@variable = @markerRange = null
@variableChain = @markerRange = null
@update()
onNewWorld: (e) ->
@thang = @options.thang = e.world.thangMap[@thang.id] if @thang
update: ->
if @variable
value = @variableStates[@variable]
@$el.find("code").text "#{@variable}: #{value}"
if @variableChain
{key, value} = @deserializeVariableChain @variableChain
@$el.find("code").text "#{key}: #{value}"
@$el.show().css(@pos)
else
@$el.hide()
@ -58,6 +82,28 @@ module.exports = class DebugView extends View
if @markerRange
@marker = @ace.getSession().addMarker @markerRange, "ace_bracket", "text"
deserializeVariableChain: (chain) ->
keys = []
for prop, i in chain
if prop is "this"
value = @thang
else
value = (if i is 0 then @variableStates else value)[prop]
keys.push prop
break unless value
if theClass = serializedClasses[value.CN]
if value.CN is "Thang"
thang = @thang.world.thangMap[value.id]
value = thang or "<Thang #{value.id} (non-existent)>"
else
value = theClass.deserializeFromAether(value)
if value and not _.isString value
if value.constructor?.className is "Thang"
value = "<#{value.spriteName} - #{value.id}, #{if value.pos then value.pos.toString() else 'non-physical'}>"
else
value = value.toString()
key: keys.join("."), value: value
destroy: ->
super()
@ace?.removeEventListener "mousemove", @onMouseMove

View file

@ -51,7 +51,6 @@ module.exports = class SpellView extends View
else
# needs to happen after the code generating this view is complete
setTimeout @onLoaded, 1
@createDebugView()
createACE: ->
# Test themes and settings here: http://ace.ajax.org/build/kitchen-sink.html
@ -157,7 +156,7 @@ module.exports = class SpellView extends View
@eventsSuppressed = false # Now that the initial change is in, we can start running any changed code
createDebugView: ->
@debugView = new SpellDebugView ace: @ace
@debugView = new SpellDebugView ace: @ace, thang: @thang
@$el.append @debugView.render().$el.hide()
createToolbarView: ->
@ -175,6 +174,8 @@ module.exports = class SpellView extends View
return if thang.id is @thang?.id
@thang = thang
@spellThang = @spell.thangs[@thang.id]
@createDebugView() unless @debugView
@debugView.thang = @thang
@updateAether false, true
@highlightCurrentLine()

View file

@ -32,7 +32,7 @@
"firepad": "~0.1.2",
"marked": "~0.3.0",
"moment": "~2.5.0",
"aether": "~0.0.5",
"aether": "~0.0.7",
"underscore.string": "~2.3.3",
"firebase": "~1.0.2"
},