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"],
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".
Many properties have types of three-element array for (x, y, z) vector, or four-element array for a quaternion.
type Vector3 = [<number>, <number, <number>]
type Quaternion = [<number>, <number, <number>, <number>]
Also, typically a rotation type can take an Euler angle. Namely, if a three-element array is specified for rotation it is interpreted as an Euler angle. So the "Rotation" type can be represented as follows and the value is intepretered based on the length of the array.
type Euler = [<number>, <number, <number>]
type Rotation = Quaternion|Euler
translation
spatial
Vector3|undefined
Specifies the xyz coodinates of the card. It defaults to [0, 0, 0] when not specified.
scale
spatial
Vector3|undefined
Specifies the scale in xyz axes of the card. It defaults to [1, 1, 1] when not specified.
rotation
spatial
Rotation|undefined
Specifies the rotation of the card. It defaults to [0, 0, 0, 1] (unit rotation) when not specified.
dataTranslation
spatial
Vector3|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
Vector3|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
Rotation|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. 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.
spawn
spatial
"default":string
This is a special property whose only supported value is "default". If there is a card with this value, the translation and the rotation of the card is used as the "spawn point" of the world for an newly joining avatar.
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"]
.
type
visual
"2d"|"3d"|"lighting"|"object"|"code"
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.
hidden
visual
boolean|undefined
The value specifies whether the root of the Three.js objects for the card to have the visible
flag set or not. The value defaults to false (that is the visible flag to be true).
When the hidden flag is true, the card also stops responding pointer events.
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- or alt-click and then click on the property sheet icon to 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.
alphaTest
visual
number|undefined
When the "type" is "2d" and "textureType" is "image", and "alphaTest" is defined, the value is used for the alphaTest property of the resulting material for the image. This is useful when you need to show a transparent PNG in the world.
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- or alt-click and then click on the property sheet icon to 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.
flatten
visual
boolean
When type is "3d", and the value is true, the system tries its best to remove the nested Object3D structure and merge meshes with the same texture.
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
Vector3
Specifies the size of the placeholder object.
placeholderColor
visual
type Color=number
Color|undefined
Specifies the color of the placeholder object.
placeholderOffset
visual
Vector3
Specifies the position of the placeholder object.
avatarParts
visual
boolean|undefined
The avatar can apply a special visibility treatment for a card that is attached to it; so that objects don't occulude the user's view. The avatarParts flag enables the visibility changes. (e.g., the name tag above the avatar's head has this flag.)
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.
loadSynchronously
visual
boolean?
When there is a card with type "2d" or "3d" and with the property "loadSynchronously" set to be true, and also the SynchrnousCardLoader behavior module is attached to a card in the system, the system sends synchronousLoadCardsStarted and allSynnchronousCardsLoaded events. See the details in behaviors/default/synchronousLoad.js
for more details.
toneMappingExposure
visual
number
When specified for a light, the default implementation of lights uses the value to set the toneMappingExposure property of THREE.js renderer to control the brightness of the over all scene. The system uses 1.4 as default.
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. Currently all children of a card with noSave
also need to have the flag set explicitly.
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