Spell palette entries now using property docs from components.
This commit is contained in:
parent
b7be08ac19
commit
dc8c4394e1
8 changed files with 122 additions and 134 deletions
app
lib/world
templates/play/level/tome
views/play/level/tome
server
|
@ -689,109 +689,3 @@ D.spawnedRectangles = class SpawnedRectangles extends Doc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
D.pow = class Pow extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns `base` to the `exponent` power, that is, <code>base<sup>exponent</sup></code>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
example: ->
|
|
||||||
"""
|
|
||||||
Math.pow(7, 2); // returns 49
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[
|
|
||||||
new Arg "base", "number", "7", "The base number."
|
|
||||||
new Arg "exponent", "number", "2", "The exponent used to raise the `base`."
|
|
||||||
]
|
|
||||||
|
|
||||||
D.sqrt = class Sqrt extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns the square root of a non-negative number. Equivalent to `Math.pow(x, 0.5)`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
example: ->
|
|
||||||
"""
|
|
||||||
Math.sqrt(49); // returns 7
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[new Arg "x", "number", "49", ""]
|
|
||||||
|
|
||||||
D.sin = class Sin extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns the sine of a number (between -1 and 1).
|
|
||||||
"""
|
|
||||||
|
|
||||||
example: ->
|
|
||||||
"""
|
|
||||||
Math.sin(Math.PI / 4); // returns √2
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[new Arg "x", "number", "Math.PI / 2", "A number in radians."]
|
|
||||||
|
|
||||||
D.cos = class Cos extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns the cosine of a number (between -1 and 1).
|
|
||||||
"""
|
|
||||||
|
|
||||||
example: ->
|
|
||||||
"""
|
|
||||||
Math.cos(3 * Math.PI / 4); // returns -√2
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[new Arg "x", "number", "Math.PI / 2", "A number in radians."]
|
|
||||||
|
|
||||||
D.tan = class Tan extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns the tangent of a number (between -1 and 1).
|
|
||||||
"""
|
|
||||||
|
|
||||||
example: ->
|
|
||||||
"""
|
|
||||||
Math.tan(Math.PI / 4); // returns 0.9999999999999999
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[new Arg "x", "number", "Math.PI / 2", "A number in radians."]
|
|
||||||
|
|
||||||
D.atan2 = class Atan2 extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns the arctangent of the quotient of its arguments--a numeric value between -π and π representing the counterclockwise angle theta of an (x, y) point and the positive X axis.
|
|
||||||
"""
|
|
||||||
|
|
||||||
args: ->
|
|
||||||
[
|
|
||||||
new Arg "y", "number", "90", ""
|
|
||||||
new Arg "x", "number", "15", ""
|
|
||||||
]
|
|
||||||
|
|
||||||
D.PI = class PI extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
The ratio of the circumference of a circle to its diameter, approximately 3.14159.
|
|
||||||
"""
|
|
||||||
|
|
||||||
D.random = class Random extends Doc
|
|
||||||
owner: "Math"
|
|
||||||
doc: ->
|
|
||||||
"""
|
|
||||||
Returns a random number x such that 0 <= x < 1.
|
|
||||||
"""
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
// Later we'll put the crazy HTML from docs.coffee in here as jade
|
span= doc.title
|
|
@ -0,0 +1,37 @@
|
||||||
|
h4
|
||||||
|
span= doc.shortName
|
||||||
|
| -
|
||||||
|
code.prop-type= doc.type == 'function' && doc.owner == 'this' ? 'method' : doc.type
|
||||||
|
if doc.type != 'function'
|
||||||
|
| (read-only)
|
||||||
|
|
||||||
|
.description!= markedWithImages(doc.description || 'Still undocumented, sorry.')
|
||||||
|
|
||||||
|
if doc.type == 'function'
|
||||||
|
p.example
|
||||||
|
strong Example:
|
||||||
|
div
|
||||||
|
code= doc.owner + '.' + doc.name + '(' + argumentExamples.join(', ') + ');'
|
||||||
|
else
|
||||||
|
p.value
|
||||||
|
strong Current Value:
|
||||||
|
code.current-value(data-prop=doc.name)= value
|
||||||
|
|
||||||
|
if doc.args && doc.args.length
|
||||||
|
p.args
|
||||||
|
strong Parameters:
|
||||||
|
for arg in doc.args
|
||||||
|
div
|
||||||
|
code= arg.name
|
||||||
|
| :
|
||||||
|
code= arg.type
|
||||||
|
if arg.example
|
||||||
|
| (ex:
|
||||||
|
code= arg.example
|
||||||
|
| )
|
||||||
|
if arg.description
|
||||||
|
div!= markedWithImages(arg.description)
|
||||||
|
if arg.default
|
||||||
|
div
|
||||||
|
em Default value:
|
||||||
|
code= arg.default
|
|
@ -1,8 +1,17 @@
|
||||||
View = require 'views/kinds/CocoView'
|
View = require 'views/kinds/CocoView'
|
||||||
template = require 'templates/play/level/tome/spell_palette_entry'
|
template = require 'templates/play/level/tome/spell_palette_entry'
|
||||||
|
popoverTemplate = require 'templates/play/level/tome/spell_palette_entry_popover'
|
||||||
{me} = require 'lib/auth'
|
{me} = require 'lib/auth'
|
||||||
filters = require 'lib/image_filter'
|
filters = require 'lib/image_filter'
|
||||||
Docs = require 'lib/world/docs'
|
Docs = require 'lib/world/docs'
|
||||||
|
{downTheChain} = require 'lib/world/world_utils'
|
||||||
|
|
||||||
|
# If we use marked somewhere else, we'll have to make sure to preserve options
|
||||||
|
marked.setOptions {gfm: true, sanitize: false, smartLists: true, breaks: true}
|
||||||
|
|
||||||
|
markedWithImages = (s) ->
|
||||||
|
s = s.replace /!\[(.*?)\]\((.+)? (\d+) (\d+) ?(.*?)?\)/g, '<img src="/images/docs/$2" alt="$1" title="$1" style="width: $3px; height: $4px;" class="$5"></img>' # setting width/height attrs doesn't prevent flickering, but inline css does
|
||||||
|
marked(s)
|
||||||
|
|
||||||
module.exports = class SpellPaletteEntryView extends View
|
module.exports = class SpellPaletteEntryView extends View
|
||||||
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
|
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
|
||||||
|
@ -20,41 +29,79 @@ module.exports = class SpellPaletteEntryView extends View
|
||||||
super options
|
super options
|
||||||
@thang = options.thang
|
@thang = options.thang
|
||||||
@doc = options.doc
|
@doc = options.doc
|
||||||
@shortenize = options.shortenize
|
if _.isString @doc
|
||||||
|
@doc = name: @doc, type: typeof @thang[@doc]
|
||||||
|
@doc.owner ?= 'this'
|
||||||
|
if options.isSnippet
|
||||||
|
@doc.type = 'snippet'
|
||||||
|
@doc.shortName = @doc.name
|
||||||
|
else
|
||||||
|
suffix = if @doc.type is 'function' then '()' else ''
|
||||||
|
@doc.shortName = "#{@doc.owner}.#{@doc.name}#{suffix};"
|
||||||
|
if @doc.owner is 'this'
|
||||||
|
@doc.shorterName = "#{@doc.name}#{suffix}"
|
||||||
|
else
|
||||||
|
@doc.shorterName = @doc.shortName.replace ';', ''
|
||||||
|
@doc.title = if options.shortenize then @doc.shorterName else @doc.shortName
|
||||||
|
|
||||||
|
getRenderData: ->
|
||||||
|
c = super()
|
||||||
|
c.doc = @doc
|
||||||
|
c
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
super()
|
||||||
text = if @shortenize then @doc.shorterName else @doc.shortName
|
@$el.addClass(@doc.type)
|
||||||
@$el.text(text).addClass(@doc.type)
|
@$el.popover(
|
||||||
@$el.attr('title', @doc.title()).popover(
|
|
||||||
animation: true
|
animation: true
|
||||||
html: true
|
html: true
|
||||||
placement: 'top'
|
placement: 'top'
|
||||||
trigger: 'hover'
|
trigger: 'hover'
|
||||||
content: @doc.html()
|
content: @formatPopover()
|
||||||
container: @$el.parent().parent().parent()
|
container: @$el.parent().parent().parent()
|
||||||
)
|
)
|
||||||
@$el.on 'show.bs.popover', =>
|
@$el.on 'show.bs.popover', =>
|
||||||
# New, good event
|
Backbone.Mediator.publish 'tome:palette-hovered', thang: @thang, prop: @doc.name
|
||||||
Backbone.Mediator.publish 'tome:palette-hovered', thang: @thang, prop: @doc.prop
|
|
||||||
# Bad, old one for old scripts (TODO)
|
formatPopover: ->
|
||||||
Backbone.Mediator.publish 'editor:palette-hovered', thang: @thang, prop: @doc.prop
|
content = popoverTemplate doc: @doc, value: @formatValue(), marked: marked, markedWithImages: markedWithImages, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? [])
|
||||||
|
owner = if @doc.owner is 'this' then @thang else window[@doc.owner]
|
||||||
|
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
|
||||||
|
|
||||||
|
formatValue: (v) ->
|
||||||
|
return '<Function>' if @doc.type is 'function'
|
||||||
|
unless v?
|
||||||
|
if @doc.owner is 'this'
|
||||||
|
v = @thang[@doc.name]
|
||||||
|
else
|
||||||
|
v = window[@doc.owner][@doc.name]
|
||||||
|
if @type is 'number' and not isNaN v
|
||||||
|
if v == Math.round v
|
||||||
|
return v
|
||||||
|
return v.toFixed 2
|
||||||
|
if _.isString v
|
||||||
|
return "\"#{v}\""
|
||||||
|
if v?.id
|
||||||
|
return v.id
|
||||||
|
if v?.name
|
||||||
|
return v.name
|
||||||
|
if _.isArray v
|
||||||
|
return '[' + (@formatValue v2 for v2 in v).join(', ') + ']'
|
||||||
|
v
|
||||||
|
|
||||||
onMouseOver: (e) ->
|
onMouseOver: (e) ->
|
||||||
# Make sure the doc has the updated Thang so it can regenerate its prop value
|
# Make sure the doc has the updated Thang so it can regenerate its prop value
|
||||||
@doc.thang = @thang
|
@$el.data('bs.popover').options.content = @formatPopover()
|
||||||
@$el.data('bs.popover').options.content = @doc.html()
|
|
||||||
@$el.popover('setContent')
|
@$el.popover('setContent')
|
||||||
|
|
||||||
onClick: (e) ->
|
onClick: (e) ->
|
||||||
Backbone.Mediator.publish 'tome:palette-clicked', thang: @thang, prop: @doc.prop
|
Backbone.Mediator.publish 'tome:palette-clicked', thang: @thang, prop: @doc.name
|
||||||
|
|
||||||
onFrameChanged: (e) ->
|
onFrameChanged: (e) ->
|
||||||
return unless e.selectedThang?.id is @thang.id
|
return unless e.selectedThang?.id is @thang.id
|
||||||
@options.thang = @thang = e.selectedThang # Update our thang to the current version
|
@options.thang = @thang = e.selectedThang # Update our thang to the current version
|
||||||
@options.doc = @doc = Docs.getDocsFor(@thang, [@doc.prop])[0]
|
@$el.find("code.current-value").text(@formatValue())
|
||||||
@$el.find("code.current-value").text(@doc.formatValue()) # Don't call any functions. (?? What does this mean?)
|
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@$el.off()
|
@$el.off()
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -4,6 +4,7 @@ template = require 'templates/play/level/tome/spell_palette'
|
||||||
filters = require 'lib/image_filter'
|
filters = require 'lib/image_filter'
|
||||||
Docs = require 'lib/world/docs'
|
Docs = require 'lib/world/docs'
|
||||||
SpellPaletteEntryView = require './spell_palette_entry_view'
|
SpellPaletteEntryView = require './spell_palette_entry_view'
|
||||||
|
LevelComponent = require 'models/LevelComponent'
|
||||||
|
|
||||||
module.exports = class SpellPaletteView extends View
|
module.exports = class SpellPaletteView extends View
|
||||||
id: 'spell-palette-view'
|
id: 'spell-palette-view'
|
||||||
|
@ -24,13 +25,19 @@ module.exports = class SpellPaletteView extends View
|
||||||
@createPalette()
|
@createPalette()
|
||||||
|
|
||||||
createPalette: ->
|
createPalette: ->
|
||||||
docs = Docs.getDocsFor @thang, @thang.programmableProperties
|
lcs = @supermodel.getModels LevelComponent
|
||||||
docs = docs.concat Docs.getDocsFor(@thang, @thang.programmableSnippets, true)
|
allDocs = {}
|
||||||
shortenize = docs.length > 6
|
allDocs[doc.name] = doc for doc in (lc.get('propertyDocumentation') ? []) for lc in lcs
|
||||||
@entries = (@addEntry doc, shortenize for doc in docs)
|
|
||||||
|
|
||||||
addEntry: (doc, shortenize) ->
|
props = @thang.programmableProperties ? []
|
||||||
entry = new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize
|
snippets = @thang.programmableSnippets ? []
|
||||||
|
shortenize = props.length + snippets.length > 6
|
||||||
|
@entries = []
|
||||||
|
@entries.push @addEntry(allDocs[prop] ? prop, shortenize) for prop in props
|
||||||
|
@entries.push @addEntry(allDocs[prop] ? prop, shortenize, true) for prop in snippets
|
||||||
|
|
||||||
|
addEntry: (doc, shortenize, isSnippet=false) ->
|
||||||
|
entry = new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize, isSnippet: isSnippet
|
||||||
@$el.find('.properties').append entry.el
|
@$el.find('.properties').append entry.el
|
||||||
entry.render() # Render after appending so that we can access parent container for popover
|
entry.render() # Render after appending so that we can access parent container for popover
|
||||||
entry
|
entry
|
||||||
|
|
|
@ -175,7 +175,7 @@ module.exports = class TomeView extends View
|
||||||
@spellView?.setThang thang
|
@spellView?.setThang thang
|
||||||
@spellTabView?.setThang thang
|
@spellTabView?.setThang thang
|
||||||
if @spellPaletteView?.thang isnt thang
|
if @spellPaletteView?.thang isnt thang
|
||||||
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang
|
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel
|
||||||
@spellPaletteView.toggleControls {}, spell.view.controlsEnabled # TODO: know when palette should have been disabled but didn't exist
|
@spellPaletteView.toggleControls {}, spell.view.controlsEnabled # TODO: know when palette should have been disabled but didn't exist
|
||||||
|
|
||||||
reloadAllCode: ->
|
reloadAllCode: ->
|
||||||
|
|
|
@ -31,12 +31,12 @@ me.sound = (props) ->
|
||||||
obj = _.cloneDeep(SoundSchema)
|
obj = _.cloneDeep(SoundSchema)
|
||||||
obj.properties[prop] = props[prop] for prop of props
|
obj.properties[prop] = props[prop] for prop of props
|
||||||
obj
|
obj
|
||||||
|
|
||||||
ColorConfigSchema = me.object { format: 'color-sound' },
|
ColorConfigSchema = me.object { format: 'color-sound' },
|
||||||
hue: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
hue: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
||||||
saturation: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
saturation: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
||||||
lightness: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
lightness: { format: 'range', type: 'number', minimum: 0, maximum: 1 }
|
||||||
|
|
||||||
me.colorConfig = (props) ->
|
me.colorConfig = (props) ->
|
||||||
obj = _.cloneDeep(ColorConfigSchema)
|
obj = _.cloneDeep(ColorConfigSchema)
|
||||||
obj.properties[prop] = props[prop] for prop of props
|
obj.properties[prop] = props[prop] for prop of props
|
||||||
|
@ -131,6 +131,8 @@ me.getLanguagesObject = -> return Language
|
||||||
|
|
||||||
me.classNamePattern = "^[A-Z][A-Za-z0-9]*$" # starts with capital letter; just letters and numbers
|
me.classNamePattern = "^[A-Z][A-Za-z0-9]*$" # starts with capital letter; just letters and numbers
|
||||||
me.identifierPattern = "^[a-z][A-Za-z0-9]*$" # starts with lowercase letter; just letters and numbers
|
me.identifierPattern = "^[a-z][A-Za-z0-9]*$" # starts with lowercase letter; just letters and numbers
|
||||||
|
me.constantPattern = "^[A-Z0-9_]+$" # just uppercase letters, underscores, and numbers
|
||||||
|
me.identifierOrConstantPattern = "^([a-z][A-Za-z0-9]*|[A-Z0-9_]+)$"
|
||||||
|
|
||||||
me.FunctionArgumentSchema = me.object {
|
me.FunctionArgumentSchema = me.object {
|
||||||
title: "Function Argument",
|
title: "Function Argument",
|
||||||
|
@ -147,7 +149,7 @@ me.FunctionArgumentSchema = me.object {
|
||||||
# not actual JS types, just whatever they describe...
|
# not actual JS types, just whatever they describe...
|
||||||
type: me.shortString(title: "Type", description: "Intended type of the argument.")
|
type: me.shortString(title: "Type", description: "Intended type of the argument.")
|
||||||
example: me.shortString(title: "Example", description: "Example value for the argument.")
|
example: me.shortString(title: "Example", description: "Example value for the argument.")
|
||||||
description: {type: 'string', description: "Description of the argument.", maxLength: 1000}
|
description: {title: "Description", type: 'string', description: "Description of the argument.", maxLength: 1000}
|
||||||
"default":
|
"default":
|
||||||
title: "Default"
|
title: "Default"
|
||||||
description: "Default value of the argument. (Your code should set this.)"
|
description: "Default value of the argument. (Your code should set this.)"
|
||||||
|
|
|
@ -23,11 +23,12 @@ PropertyDocumentationSchema = c.object {
|
||||||
description: "This Component provides a 'foo' property to satisfy all one's foobar needs. Use it wisely."
|
description: "This Component provides a 'foo' property to satisfy all one's foobar needs. Use it wisely."
|
||||||
required: ['name', 'type', 'description']
|
required: ['name', 'type', 'description']
|
||||||
},
|
},
|
||||||
name: {type: 'string', pattern: c.identifierPattern, title: "Name", description: "Name of the property."}
|
name: {type: 'string', pattern: c.identifierOrConstantPattern, title: "Name", description: "Name of the property."}
|
||||||
# not actual JS types, just whatever they describe...
|
# not actual JS types, just whatever they describe...
|
||||||
type: c.shortString(title: "Type", description: "Intended type of the property.")
|
type: c.shortString(title: "Type", description: "Intended type of the property.")
|
||||||
description: {type: 'string', description: "Description of the property.", maxLength: 1000}
|
description: {title: "Description", type: 'string', description: "Description of the property.", maxLength: 1000}
|
||||||
args: c.array {title: "Arguments", description: "If this property has type 'function', then provide documentation for any function arguments."}, c.FunctionArgumentSchema
|
args: c.array {title: "Arguments", description: "If this property has type 'function', then provide documentation for any function arguments."}, c.FunctionArgumentSchema
|
||||||
|
owner: {title: "Owner", type: 'string', description: 'Owner of the property, like "this" or "Math".'}
|
||||||
|
|
||||||
DependencySchema = c.object {
|
DependencySchema = c.object {
|
||||||
title: "Component Dependency"
|
title: "Component Dependency"
|
||||||
|
|
Reference in a new issue