Hi Bartosz,
To be clear, it sounds like you are trying to represent each text character (i.e. 0-9) with a pre-made 3D model instead of using Text Shapes to build a model from text. Correct?
Here are instructions on how you can accomplish this. A demo of the final result can be found here.
Step 0: Create Assets & Get Asset Ids
First, upload the 3D assets for each character (i.e. 3D models representing 0 - 9).
Then, create an empty placeholder model (i.e. create a Model asset on Threekit with no nodes).
Finally, get the ID of each asset, which can be retrieved from the URL of the asset detail page. We will need these later.
Step 1: Setup Anchors
In the parent asset (i.e. the asset we’re configuring), import four (i.e. one for each character) models. These will be used as anchors for the character models. It does not matter what models are imported or where they are placed. Those properties will be controlled by Asset Rules. However, it would be easiest to import 1, 2, 3, & 4 as a memory aid.
Step 2: Create Attributes
Create 4 Part Reference attributes (one for each character) and a String attribute (for the text input).
Step 3: Create Rule to Set Models
Create a rule with no conditions (i.e. one that always fires) and add actions to set each Anchor Node (i.e. the models we imported in Step 1) to it’s corresponding attribute.
Step 4: Create Rules to Update Placement (optional)
We may want to move the Anchors (change the transform) depending on how many characters are entered. For example, if the user enters 20 instead of 2020, we would want the letters aligned in the center instead of the first 2 anchor positions.
To do this, we create one rule for each character length that controls where each anchor is placed. NOTE: This can be done with a script as well and that may be the preferred approach if there were many characters.
Each rule should have conditions that detect how many Anchors have been set (i.e. the number of characters) and actions that set the position to each Anchor.
Here is a finished rule
To set the position, create an Set Property
Action
Set the Translation property of the Anchor
Step 5: Add Configuration Script
Now that we have the rules setup, we need to add a script that will set the Anchors according to the text input. This can be done by adding a Custom Script action to the rule that always fires.
Here is a script to use as a template.
// Store the assetId for each number in an array
const numberAssets = [
"8a1b066f-ce4a-44d0-a4d8-80aeddf9001d",
"ce1b3943-00d7-4017-a592-9dc3bfb97473",
"eb261263-f999-4985-ba18-d0ca2a12f7cd",
"742a0517-82ba-49d7-9c75-ebbd49276cde",
"89c861e9-4af1-4bb2-8ebd-9f6b4fe92ad5",
"4987fcbb-dbc3-4d10-abb8-387b701f3404",
"cfa295ec-b4e0-4056-bd08-aed2ac612ea4",
"48630611-c9ac-4cbc-81ba-013d361bffae",
"9e01787f-c13f-4718-a790-8061c446b60d",
"8cb83b35-9995-475b-b104-fc92608a5e2a",
];
// Use the Placeholder Model to set Anchors w/no value.
const placeholder = { assetId: "1f4eaa40-a788-4773-b1a5-30a04e0f7463" };
const anchorReset = {
Anchor1: placeholder,
Anchor2: placeholder,
Anchor3: placeholder,
Anchor4: placeholder,
};
let player;
async function onChange() {
if (!player)
if (/(preview|admin).threekit.com$/gi.test(window?.location?.origin))
// Find player on platform
player = window.api._store.getIn(["player", "players"]).first().api;
else if (window.player)
// Find player on embed
player = window.player;
else return console.warn("Cannot find player");
// Get the configurator
if (!window.configurator)
window.configurator = await player.getConfigurator();
// Only fire if the Text has changed
const nextConfig = window.configurator.getConfiguration();
if (window.prevConfig?.Text === nextConfig.Text) return;
window.prevConfig = nextConfig;
const update = nextConfig.Text.split("")
.map((int) => numberAssets[int]) // Map the input character to the assetId
.map((assetId, index) => ({ [`Anchor${index + 1}`]: { assetId } })) // Create the config updates
.reduce(
(acc, cur) => ({ ...acc, ...cur }), // Reduce attribute values to a single object
anchorReset // Use anchorReset as the initial value to ensure empty Anchors are cleared
);
return window.configurator.setConfiguration(update);
}
// onChange is an async function, meaning it returns a Promise
// Returning this to the config script ensures other rules are fired w/a consistent order of operations
return onChange();
On Embed: Assign Player to Window
The script needs to access the Player API. On initialization, assign the player to the window.
window
.threekitPlayer({
assetId: "00000000-0000-0000-0000-000000000000",
authToken: "00000000-0000-0000-0000-000000000000",
el: document.getElementById("player-el"),
})
.then((player) => {
window.player = player;
});