A card in Croquet Microverse is defined as a declarative specification. The specification can be serialized into JSON and transmitted or stored, and then can be loaded into a different Croquet Microverse world, used to start a new world.
A specification can be also used to rebuild an existing card without losing identity. This allows you to interactively build up a world while exploring different alternatives quickly.
For example, we have a 3D model of a car with a behavior that makes the car drivable:
It is defined as:
translation: [10, -1.672, -11],
rotation: [0, 0, 0, 1],
layers: ["pointer"],
type: "3d",
behaviorModules: ["Drive"],
multiuser: true,
name: "porsche",
dataLocation: "...",
dataRotation: [-0.7071067811865475, 0, 0, 0.7071067811865476],
In the following, we describe the properties and how they interact with each other. You can see examples in the files in the worlds
directory, and also some behaviors use the specification to create a new card dynamically with the call to createCard()
.
A card is specified by a JSONable set of properties. The properties specify
- where the card is spatially situated
- how it interacts with the user pointer interaction
- how it looks
- what user-defined behavior it has
- data specific to user-defined behaviors.
We group these properties into four categories, "spatial", "pointer", "visual", and "code"/"card data".
translation
spatial
Array<number, number, number>|undefined
Specifies the xyz coodinates of the card. It defaults to [0, 0, 0] when not specified.
scale
spatial
Array<number, number, number>|undefined
Specifies the scale in xyz axes of the card. It defaults to [1, 1, 1] when not specified.
rotation
spatial
Array<number, number, number, number?>|undefined
Specifies the rotation of the card. If the Array has three elements, it is interpreted as an euler angle. If the array has four elements, it is interpreted as a quaternion. It defaults to [0, 0, 0, 1] (no rotation) when not specified.
dataTranslation
spatial
Array<number, number, number>|undefined
A 3D model loaded as part of a card may have its own offset. You can use dataTranslation as a "one time" fix to translate the 3D model when loading.
Specifies the xyz coordinates of the translation for the loaded model. It defaults to [0, 0, 0] when not specified.
dataScale
spatial
Array<number, number, number>|undefined
A 3D model loaded as part of a card may have its own scale. You can use dataScale as a "one time" fix to scale the 3D model when loading.
Specifies the xyz scale of the loaded model. It defaults to [1, 1, 1] when not specified. If you load 3D model interactively by dragging and dropping from your OS, Croquet Microverse adjusts this value so that the card has a reasonably sized 3D model. You can specify this value to fix the automatic scaling.
dataRotation
spatial
Array<number, number, number, number?>|undefined
A 3D model loaded as part of a card may have a rotation that does not match with the orientation of the card. You can use dataRotation as a "one time" fix to rotate the 3D model when loading.
Specifies the rotation of the loaded model. If the Array has three elements, it is interpreted as an euler angle. If the array has four elements, it is interpreted as aquaternion. It defaults to [0, 0, 0, 1] (no rotation) when not speficied.
parent
spatial
string|CardActor|undefined
This property sets up the display scene hierarchy. Special care is taken when an actual CardActor is passed in, and also during an initialization the interpretation of the value changes. See more information on the parent
property below.
layers
pointer
type Layers = "walk"|"pointer"|"lighting"|"portal"
Array<Layers>|undefined
It is an array of "walk", "pointer", "lighting", and future extensions. If the value contains "walk", the avatar uses the "find floor" mechanism to keep its y coordinates. If the value contains "pointer", user interaction via the pointing device takes this object into account. It defaults to ["pointer"]
.
multiuser
pointer
boolean
Specifies whether the card automatically locks other users out when one user is interacting. It defaults to true
.
type
visual
type Type ="2d"|"3d"|"lighting"|"object"|"code"
Type|undefined
When it is "2d", it creates a 2d flat object and enables optional texture specification (see texture related properties below).
When it is "3d, it loads an 3D data from dataLocation
.
When it is "text", the card becomes a text area.
When it is "code", it creates a text area but has some more functionality to support in world code editing.
When it is "object" or undefined
, custom behavior code is expected to set the cards' visual appearance.
dataLocation
visual
string|undefined
The value is interpreted as URL, fragment of URL, Croquet Data ID or undefined
It contains the location of SVG or 3d model data. It is a URL, either full URL or a relative path from the application, or Croquet Data ID.
If you drag and drop a file to create a card, you can open the Property Sheet by Ctrl+tap, and check the value of dataLocation for its Data ID.
width
and height
visual
type Meter=number
Meter|undefined
The width and height of the card with "2d" as its type. The values are interpreted as "meters".
Both default to 1.
depth
visual
type Meter=number
Meter|undefined
When the cards "type" is "2d", depth is used to specify the amount of extrusion. It defaults to 0.05 (in meters).
cornerRadius
visual
type Meter=number
Meter|undefined
When the cards "type" is "2d", cornerRadius
specifies the radius of the rounded corner. It defaults to 0 (in meters).
color
visual
Type Color=number
Color|undefined
When the "type" is "2d", the value is used for the surface of the 2D card. The value is also available from a behavior and typically used to specify the color of the generated Three.js materials.
When the "type" is "text" or "code", the value specifies the text color.
frameColor
visual
Type Color=number
Color|undefined
When the "type" is "2d", the value is used for the edge of the 2D card.
shadow
visual
boolean|undefined
It specifies whether the created object should cast shadow or not. It defaults to true
.
textureType
visual
Type TextureType = "image"|"canvas"
TextureType|undefined
When it is "image", it loads an image data from textureLocation
and creates Texture of Three.js.
When it is "canvas", it creates a DOM canvas and binds it to CanvasTexture of Three.js.
When it is undefined, it does not allocate a texture
The created texture is assigned to this.texture
property of the CardPawn
.
textureLocation
visual
string|undefined
URL, fragment of URL, Croquet Data ID or undefined
It contains the location of an image data. It is a URL, either full URL or a relative path from the application, or Croquet Data ID.
If you drag and drop an image to create a card, you can open the Property Sheet by Ctrl+tap, and check the value of textureLocation
for its Data ID.
textureWidth
and textureHeight
visual
type Pixels=number
Pixels|undefined
Those values specify the texture's size in pixels, when the type
is "2d".
They default to 512.
fullBright
visual
boolean
When type is "2d", it specifies whether the texture is rendered without regarding to lighting.
singleSided
visual
boolean
When type is "3d", it specifies whether the model should be rendered the both sides of the geometry.
placeholder
visual
boolean
Put a simple Three.js object while loading a (large) 3D model. When the model loading is finished the placeholder will be removed automatically.
placeholderSize
visual
Array<number, number, number>
Specifies the size of the placeholder object.
placeholderColor
visual
type Color=number
Color|undefined
Specifies the color of the placeholder object.
placeholderOffset
visual
Array<number, number, number>
Specifies the position of the placeholder object.
textScale
visual
number|undefined
When the card's type is "code" or "text", "textScale" specifies the scaling factor between the pixel-based font size and "meters". Typically font metric is specified in a range such as 20 to 50, while the dimension of a 3D objects corresponds to meters. When undefined, it defaults to 0.025.
noDismissButton
visual
boolean
When the card's type is "code" or "text", "noDismissButton" specifies whether the text field gets the dismiss button. It defaults to false.
readOnly
visual
boolean
When the card's type is "code" or "text", "readOnly" specifies whether the text field can be edited or not.It defaults to false.
backgroundColor
visual
nubmer
When the card's type is "code" or "text", "backgroundColor" specifies the color of the text field. The color
specifies the color of the characters.
autoResize
visual
boolean
When the card's type is "code" or "text", "autoResize" specifies whether the text field should resize itself to show entire text contents. It defaults to false.
singleLine
visual
boolean
When the card's type is "code" or "text", "singleLine" specifies whether the text field should wrap when the content exceeds the specified width
. It defaults to false.
margins
visual
let Pixels=number
{left<Pixels>, top<Pixels>, right<Pixels>, bottom<Pixels>}
When the card's type is "code" or "text", "margins" specifies the margins of the text field.
behaviorModules
code
Array|undefined
Specifies the names of behavior modules.
className
code
string
Specifies the names of a subclass of CardActor
to be instantiated. While being obsoleted you can create a subclass of the CardActor
and CardPawn
to create an application. When specified, className
decides which JavaScript class is to be instantiated as the card.
name
code
string
When specified the Three.js object created for this card will get the name
property with this value. It can be used from behavior code.
noSave
code
boolean
When true, the card is not stored in the persistent data.
The parent
property is used differently depending on the context. In the world file (such as default.js
), you sometimes want to specify hierarchical cards. As a shorthand, you can specify the Constants.DefaultCards with a simple
id` field and refer to it from subsequent cards:
Constants.DefaultCards = [
{
card: {
name: "bitcointracker",
...
behaviorModules: ["Elected", "BitcoinTracker"],
},
id: "main",
},
{
card: {
name:"bitlogo",
parent: "main",
...
behaviorModules: ["BitLogo"]
}
},
{
card: {
name:"bar graph",
...
parent: "main",
behaviorModules: ["BarGraph"],
}
}
]
The name main
is local with in the list, and when DefaultCards
is processed, the (temporary) name main
is used to make the last two cards be children of the first.
When a card is created from a program, you can use the createCard
method of a CardActor
:
labelCard = this.createCard({
name: item.label,
className: "TextFieldActor",
translation: [0, 0, 0],
parent: this,
type: "text",
margins: {left: 8, top: 0, right: 16, bottom: 0},
readOnly: true,
singleLine: true,
autoResize: true,
noDismissButton: true,
runs: [{text: item.label}],
behaviorModules: ["MenuItem"],
width: 1,
textScale: 0.0020,
height: 0.15,
noSave: true,
fullBright: true,
backgroundColor: item.selected ? 0x606060 : 0xFFFFFF
});
For convenience, you can pass in an object as the value for parent
in this case.
As long as a value can be serialized in JSON, you can specify a new property in the card specification with any property name. You can use the value from a behavior you attach to the card. Such a value is stored in the actor's property called _cardData
. A behavior for the CardActor can read and write the value by accessing this._cardData.foo
, and a behavior for the CardPawn can read the value by accessing this.actor._cardData.foo
.
A behavior can create a property on the model directly, namely to execute something like this.foo = 42
. this is fine but the value will not be stored in the persistent data; so when you run the new session with a new version of Croquet Microverse, such a value will not be carried over. Choose to store the value in _cardData
if you want to carry a value over to a new session from persistent data, or store it directly in the actor when that is not necessary.
Copyright (c) 2022 Croquet Corporation