Canvas Nasal API

From FlightGear wiki
Revision as of 18:03, 16 August 2017 by Necolatis (talk | contribs) (→‎setStrokeLineCap: Added CaptBs images of canvas stroke join/cap)
Jump to navigation Jump to search


Canvas consist of a class with various nestable classes (elements).

See inside the current (Git) API here.

For the Canvas GUI API see Canvas GUI API

Canvas

For constructor see: Initialize a Canvas

addPlacement

Note  It is possible to place a canvas on models in the scene. Tom has not tested if it also works for MP/AI aircraft but it should. The placement in scenery objects needs a different placement type to select also the model it should be placed on. For scenery objects a special placement exists:
var placement = { "module-id": _module_id, type: "scenery-object", <normal placement parameters like eg. node> }

'_module_id' is a special variable which is only set in scenery object <load> handlers.[1]

See: Place a Canvas

setColorBackground

Parameters: (r, g, b, a)

Fills the background of the entire canvas with the supplied color.

createGroup

Parameters: ()

Parameters: (name)

Returns: Group

Create a new group under this Canvas. Supplying name is optional.

getPath

Parameters: ()

?

del

Parameters: ()

Deletes this Canvas.

wrapCanvas

Parameters: ()

?

get

Parameters: (name)

Returns: Canvas

Returns the canvas with the specified name.

parsesvg

Parameters: (group, file)

Parameters: (group, file, font-mapper)

See: SVG inside a Canvas

Element

Note that in each element there are 2 transformation matrices. The first will be applied first, then the second.

set

Parameters: (key, value)

Key = "z-index":

Default value = 0

Integer value indicates the explicit Z sort order, highest on top. If this is not set, elements that are added later gets drawn on top. Notice that if you have for example two paths inside their own groups, and you want to order those paths in relation to each other, its on their groups you should call this method, not on the paths themselves.

FG 2.10.0.3: Elements added after z-index has been set will overrule it. (fix is in GIT)

update

Parameters: ()

Normally an element gets updated in the next frame. Calling this will make it update in the current frame. Note that visibility methods do get updated in the current frame.

getVisible

Parameters: ()

Returns: visible

Returns 0 if not visible, 1 if visible.

setVisible

Parameters: ()

Parameters: (visible)

Sets if this element should be visible. 0 sets it not visible, 1 visible. No parameters sets it visible.

show

Parameters: ()

Sets the element visible.

hide

Parameters: ()

Sets the element not visible.

toggleVisibility

Parameters: ()

Toggles if element should be visible.

setGeoPosition

Parameters: (lat, lon)

Sets the geographic coordinates for a map element. Parent element must be of type "map".

Example: setGeoPosition(37.615223, -122.389978)

Places element at San Francisco International Airport.

createTransform

createTransform creates a new matrix on top of the existing matrix stack. A while ago I've added an example for a HUD built using the Canvas to the wiki: http://wiki.flightgear.org/Canvas_HUD It doesn't use SVG but manually creates everything instead. As loading an SVG should basically do the same than handcrafting icons there shouldn't be much of a difference.

Parameters: ()

Parameters: ([a, b, c, d, e, f])

Return: The new (second) transform

Creates a new (second) transformation matrix for this element. No parameters will create a default identity matrix transform. Otherwise supply a 6 element vector for the matrix:

a b c
d e f
0 0 1

You should probably change the order of creating the transforms for pitch and roll as normally one would rotate first and then move according to roll and then move according to pitch up and down. Keep in mind that rotations always happens around the origin of the local coordinate frame of the object being rotated. For a rotation around another point you would need to move the object first until the center coincides with the local origin then rotate and afterwards move back. Instead of applying three transformations there exists a shortcut to pass the center of rotation as second argument to setRotation.

To further shorten the code an especially to allow rotating objects imported from SVG there exists setRotation also for canvas Elements (not only Transformation) and additionally setCenter which instead of passing the center as an argument sets the center which is being used while calling setRotation on this element. setCenter only affects setRotation of this not object but not for any matrix added with createTransform. If you set the center of rotation in Inkscape (switch to rotate mode and drag the cross to the center of rotation) it is automatically loaded with setCenter so you just need to call setRotation and automatically get a rotation around the correct center.

You don't need to care about tf[0] being reserved as it only reserves the index 0 and doesn't affect anything if not used. createTransform creates a new matrix with the next unused index starting at 1 (0 is reserved). If you later call setRotation directly on an element a new Transform will be created but this time using tf[0] to ensure it is applied before all other matrices and therefore rotating the object around its own center before being moved around.

For the HUD I'd set the rotation center correctly inside Inkscape and later on just call ladder.setRotation to rotate for changes in the roll angle. Afterwards create a Transform and use setTranslate for changes in pitch angle.

setTranslation

Parameters: (x, y)

Translates the element. The translation is set on the second transform.

setRotation

Parameters: (x, y)

Rotates the element around the center. The rotation is set on the first transform.

setRotation really just combines a rotation with two translations -> translate(-center[0], -center[1]) * rotate * translate(center[0], center[1])

You can also have a look in the property browser and check the bounding box (/canvas/by-index/texture[i]/[group[j]+]/path[j]/bounding-box) and use its coordinates to determine the correct center of rotation.

setScale

Parameters: (x, y)

Scales the element. The scale is set on the second transform.

getScale

Parameters: ()

Return: 2 element vector [x,y]

Returns the scale of this element.

setColorFill

Parameters: (r, g, b)

Parameters: (r, g, b, a)

Sets the color/alpha to be used as fill value. If you do not want the element to be filled, do not call this method.

getBoundingBox

Parameters: ()

Returns: [minX, minY, maxX, maxY]

Returns the bounds of the element.

updateCenter

Parameters: ()

Sets the center to be the center of the boundingbox in relation to the elements position in its parent.

setCenter

Parameters: (x, y)

Sets the center of the element that is used for rotation.

getCenter

Parameters: ()

Gets the center of the element.

Group

Inherits from Element.

set

Parameters: (key, value)

key = "clip"

Note
Cquote1.png Scaling or any other type of transformation or changing the coordinates of individual points is definitely more efficient than clipping (which requires to change the OpenGL clip planes for every rendered object with a different clipping rectangle).
— TheTom (Feb 21st, 2016). Re: Space Shuttle.
(powered by Instant-Cquotes)
Cquote2.png


Makes a clipping bounds for the group, only what is inside the clipping bounds will be shown.

It uses same coordinate format as Clipping

Example: my_grp.set("clip", "rect(62px, 587px, 262px, 437px)"); # top,right,bottom,left

key = "clip-frame"

Sets the coordinate system to be used for clip coordinates.

Can be canvas.Element.GLOBAL (the default value), canvas.Element.PARENT or canvas.Element.LOCAL

Notice that if set to local or parent and there is a rotation is play, the clipping wont rotate properly, it will move around and scale instead.

key = "font"

Sets the default font.

Example: my_group.set("font", "LiberationFonts/LiberationMono-Regular.ttf");

key = "stroke"

?

key = "fill"

?

setDouble

Parameters: (key, value)

key = "character-aspect-ration"

?

key = "character-size"

?

createChild

Parameters: (type)

Parameters: (type, name)

Returns: Element

Creates a child element under this Group. Name can be supplied. Type can be "text", "group", "path", "image", "map". Return an Element of the particular type specified.

createChildren

Parameters: (type, count)

Returns: [Element]

Creates a number of child elements under this Group. Return a vector of Elements of the particular type specified.

getChildren

Parameters: ()

Returns: [Element]

Returns all the child elements of this group.

getElementById

Parameters: (name)

Returns: Element

Returns the first found child element with the specified name.

removeAllChildren

Parameters: ()

Removes all the child elements from this group.

Text

Inherits from Element.

enableUpdate

Enables the updateText() method for a text element.


setText

Parameters: (text)

Sets the text to be displayed.

updateText

Parameters: (text)

The setText method internally writes the text string into a property node. If the method is run inside an update loop (as usually done for displays), setText writes the property regardless of whether the text has actually changed in the last update cycle. For complicated displays, this may cause a lot of unnecessary property I/O slowing down the simulation.

To improve this, updateText() keeps a Nasal variable record of the last text that has been written and writes the property only if the text has changed. Since this record needs to be allocated, the method requires to call enableUpdate() once before using it.

Note also that updateText() and setText() should not be both used on the same text element (updateText() will not register any changes made to the property string by any other means).


setAlignment

Parameters: (alignment)

Sets how the text should be aligned with its position.

Full list:

  • left-top
  • left-center
  • left-bottom
  • center-top
  • center-center
  • center-bottom
  • right-top
  • right-center
  • right-bottom
  • left-baseline
  • center-baseline
  • right-baseline
  • left-bottom-baseline
  • center-bottom-baseline
  • right-bottom-baseline

setFontSize

Parameters: (size, aspectRatio)

Sets the size and aspectRatio of the font. AspectRatio is the Ratio between character height and width. Default aspectRatio is 1.

setFont

Parameters: (fontName)

Sets the font to be used. See $FG_ROOT/Fonts for list of fonts.

setDrawMode

Parameters: (mode)

Sets the drawing mode. You can use the values below and add those you need.

Text.TEXT: Draws the text

Text.BOUNDINGBOX: Draws the boundingbox

Text.FILLEDBOUNDINGBOX: Draws the filled boundingbox

Text.ALIGNMENT: Draws a cross where the element position is

Example: my_text.setDrawMode(Text.TEXT + Text.BOUNDINGBOX);

setPadding

?

setMaxWidth

?

setColor

Parameters: (r, g, b)

Parameters: (r, g, b, a)

Sets the color the text should be drawn in.

setColorFill

Parameters: (r, g, b)

Parameters: (r, g, b, a)

Sets the color the text background should be drawn in.

Path

Inherits from Element.

A path is similar to drawing with a pen on paper. The move and moveTo methods represent lifting the pen from the paper and moving to a new position. The drawing methods like lineTo would then be seen as starting from the current position of the pen. Therefore offcouse the order the methods is called in, is important.

pop_front

Parameters: ()

Remove first segment

pop_back

Parameters: ()

Remove last segment

getNumSegments

Parameters: ()

Get the number of segments

reset

Parameters: ()

Remove all existing path data

moveTo

Parameters: (x, y)

Moves the position to an new absolute position.

move

Parameters: (x, y)

Moves the position to a new relative position from the current.

lineTo

Parameters: (x, y)

Draws a line to specified position.

line

Parameters: (x, y)

Draws a line to specified relative position.

horizTo

Parameters: (x)

Draws a horizontal line to specified position.

horiz

Parameters: (x)

Draws a horizontal line to specified relative position.

vertTo

Parameters: (y)

Draws a vertical line to specified position.

vert

Parameters: (y)

Draws a vertical line to specified relative position.

quadTo

Parameters: (x0, y0, x1, y1)

Draws quadratic Bézier curve.

quad

Parameters: (x0, y0, x1, y1)

Draws quadratic Bézier curve. Relative coordinates.

squadTo

Parameters: (x, y)

Draws smooth quadratic Bézier curve.

squad

Parameters: (x, y)

Draws smooth quadratic Bézier curve. Relative coordinates.

cubicTo

Parameters: (x0, y0, x1, y1, x2, y2)

Draws cubic Bézier curve.

cubic

Parameters: (x0, y0, x1, y1, x2, y2)

Draws cubic Bézier curve. Relative coordinates.

scubicTo

Parameters: (x, y, x2, y2)

Add a smooth cubic Bézier curve

scubic

Parameters: (x, y)

Add a smooth cubic Bézier curve. Relative coordinates.

rect

Parameters: (x, y, w, h, cfg = nil)

cfg: Optional settings (eg. {"border-top-radius": 5}, {"border-bottom-radius": 5}, {"border-radius": 5}, {"border-bottom-right-radius": 5} or {"border-left-radius": 5})

Add a (rounded) rectangle to the path

arcSmallCCWTo

arcSmallCCW

arcSmallCWTo

arcSmallCW

Parameters: (xRadius, yRadius,0,xEnd,yEnd)

Draws an arc with the specified radii, up to the specified end point. The end point is relative to the starting point.

To draw half a circle with radius 20 around the origin:

.moveTo(-20,0)
.arcSmallCW(20,20,0,40,0);

To draw a circle with radius 20 around the origin:

.moveTo(-20,0)
.arcSmallCW(20,20,0,40,0)
.arcSmallCW(20,20,0,-40,0);

arcLargeCCWTo

arcLargeCCW

arcLargeCWTo

arcLargeCW

Drawing arcs examples :

Canvas arc draw examples
	var fpv = group.createChild("group", "FPV");

        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,255,1)")
        .moveTo(100, 100).arcSmallCCW(50, 50, 0,  50, 50);
        fpv.createChild("path").setStrokeLineWidth(4) .set("stroke", "rgba(255,0,255,1)")
        .moveTo(300, 100).arcSmallCCW(50, 50, 0,  100, 0);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,255,1)")
        .moveTo(500, 100).arcSmallCCW(50, 50, 0,  50, -50);

        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(55,0,255,1)")
        .moveTo(100, 300).arcSmallCW(50, 50, 0,  50, 50);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(55,0,255,1)")
        .moveTo(300, 300).arcSmallCW(50, 50, 0,  100, 0);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(55,0,255,1)")
        .moveTo(500, 300).arcSmallCW(50, 50, 0,  50, -50);

        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(100, 500).arcLargeCCW(50, 50, 0,  50, 50);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(300, 500).arcLargeCCW(50, 50, 0,  100, 0);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(500, 500).arcLargeCCW(50, 50, 0,  50, -50);

        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(100, 500).arcLargeCCW(50, 50, 0,  50, 50);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(300, 500).arcLargeCCW(50, 50, 0,  100, 0);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(500, 500).arcLargeCCW(50, 50, 0,  50, -50);

        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(100, 700).arcLargeCW(50, 50, 0,  50, 50);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,55,1)")
        .moveTo(300, 700).arcLargeCW(50, 50, 0,  100, 0);
        fpv.createChild("path").setStrokeLineWidth(4).set("stroke", "rgba(255,0,5

close

Parameters: ()

Close the path (implicit lineTo to first point of path)

setColor

Parameters: (r, g, b)

Parameters: (r, g, b, a)

Sets the color of the drawn path

setColorFill

Parameters: (r, g, b)

Parameters: (r, g, b, a)

Calling this will make the path get filled in the specified color. For example if you draw a 'V' and fill it, the fill area will be a triangle inside the 'V'.

setStrokeLineWidth

Parameters: (width)

The width of the path.

setStrokeLineJoin

Parameters: (type)

Set stroke linejoin. Type can be "miter", "round" or "bevel". Canvas stroke join

setStrokeLineCap

Parameters: (type)

Caps the path. Type can be "butt", "round" or "square".

Canvas stroke cap

setStrokeDashArray

Parameters: (pattern)

Make dashed path. Pattern is a vector of alternating dash and gap lengths. Lines drawn will follow this pattern.

Example: my_path.setStrokeDashArray([10, 20, 10, 20, 10]);

setData

Parameters: (cmds, points)

Re-sets the data structure for a plot. cmds is an array containing the draw commands (integers, but they can be referenced via canvas.Path.VG_LINE_TO or canvas.Path.VG_MOVE_TO etc.) and points an array containing the associated points to which the curve is to be drawn in the form [x1, y1, x2, y2,...].


Example: my_path.setData([2, 4], [10, 20, 10, 40]);

setDataGeo

Parameters: (cmds, points) ?

addSegment

Parameters: (cmd, coords...)

Add a path segment

addSegmentGeo

Parameters: (cmd, coords...) ?

Map

Inherits from Element.

See: Canvas Maps and Canvas Map API

Image

Inherits from Element.

See: Canvas Image