<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.figuramc.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Riftlight</id>
	<title>FiguraMC - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.figuramc.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Riftlight"/>
	<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php/Special:Contributions/Riftlight"/>
	<updated>2026-05-29T17:15:39Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=847</id>
		<title>Tutorials/Persisting-Variables</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=847"/>
		<updated>2025-02-23T19:29:27Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Fix init ping, and add clarifying comment regarding it&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Avatars can use the [[ConfigAPI]] to make their variables persist across reloads. This can be used for things such as saving settings across avatars or saving information about an avatar&#039;s state. &lt;br /&gt;
&lt;br /&gt;
To begin with, create a config file. This can be done with either a script or a /figura run command; it&#039;s safest to use a script in an IDE to have syntax highlighting and avoid errors. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- All keys must be strings!&lt;br /&gt;
config:save(&amp;quot;pantsColor&amp;quot;, vec(0.5, 0.8, 0.1))&lt;br /&gt;
config:save(&amp;quot;hatVisible&amp;quot;, true)&lt;br /&gt;
config:save(&amp;quot;legLength&amp;quot;, 5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Run this script by selecting the avatar it&#039;s under. Once it&#039;s run, check the existence of the &amp;lt;code&amp;gt;variablePersistence.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;figura/config&amp;lt;/code&amp;gt;. If it&#039;s there, that code can be deleted. Next, make some code to read the data in that file when the script is loaded. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- The &amp;quot;or (value)&amp;quot; syntax sets the default value if the config:load is nil&lt;br /&gt;
local hatVisible = config:load(&amp;quot;hatVisible&amp;quot;) or true&lt;br /&gt;
local legLength = config:load(&amp;quot;legLength&amp;quot;) or 1&lt;br /&gt;
local pantsColor = config:load(&amp;quot;pantsColor&amp;quot;) or vec(0.9, 0.1, 0.9)&lt;br /&gt;
&lt;br /&gt;
function pings.updateFromConfig(hat, leg, pants)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(hat)&lt;br /&gt;
&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, leg, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, leg, 1)&lt;br /&gt;
    &lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function events.entity_init()&lt;br /&gt;
    pings.updateFromConfig(hatVisible, legLength, pantsColor)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;You&#039;ll notice we call the ping in entity_init. Since this will not be called for people who only later load the avatar, you should also sync pings every so often in a tick event. Finally, make some code that updates the config when you change values.&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- The host:isHost() checks are not necessary, but they help explicitly show that their content is host-only&lt;br /&gt;
function pings.toggleHat(state)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(state)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;hatVisible&amp;quot;, state)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.scaleLegs(scale)&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, scale, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, scale, 1)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;legLength&amp;quot;, scale)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.colorPants(rgb)&lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;pantsColor&amp;quot;, rgb)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=830</id>
		<title>Tutorials/Persisting-Variables</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=830"/>
		<updated>2025-01-07T01:13:43Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Clarify host:isHost checks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Avatars can use the [[ConfigAPI]] to make their variables persist across reloads. This can be used for things such as saving settings across avatars or saving information about an avatar&#039;s state. &lt;br /&gt;
&lt;br /&gt;
To begin with, create a config file. This can be done with either a script or a /figura run command; it&#039;s safest to use a script in an IDE to have syntax highlighting and avoid errors. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- All keys must be strings!&lt;br /&gt;
config:save(&amp;quot;pantsColor&amp;quot;, vec(0.5, 0.8, 0.1))&lt;br /&gt;
config:save(&amp;quot;hatVisible&amp;quot;, true)&lt;br /&gt;
config:save(&amp;quot;legLength&amp;quot;, 5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Run this script by selecting the avatar it&#039;s under. Once it&#039;s run, check the existence of the &amp;lt;code&amp;gt;variablePersistence.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;figura/config&amp;lt;/code&amp;gt;. If it&#039;s there, that code can be deleted. Next, make some code to read the data in that file when the script is loaded. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- The &amp;quot;or (value)&amp;quot; syntax sets the default value if the config:load is nil&lt;br /&gt;
local hatVisible = config:load(&amp;quot;hatVisible&amp;quot;) or true&lt;br /&gt;
local legLength = config:load(&amp;quot;legLength&amp;quot;) or 1&lt;br /&gt;
local pantsColor = config:load(&amp;quot;pantsColor&amp;quot;) or vec(0.9, 0.1, 0.9)&lt;br /&gt;
&lt;br /&gt;
function pings.updateFromConfig(hat, leg, pants)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(hat)&lt;br /&gt;
&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, leg, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, leg, 1)&lt;br /&gt;
    &lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
pings.updateFromConfig(hatVisible, legLength, pantsColor)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Finally, make some code that updates the config when you change values.&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- The host:isHost() checks are not necessary, but they help explicitly show that their content is host-only&lt;br /&gt;
function pings.toggleHat(state)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(state)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;hatVisible&amp;quot;, state)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.scaleLegs(scale)&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, scale, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, scale, 1)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;legLength&amp;quot;, scale)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.colorPants(rgb)&lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;pantsColor&amp;quot;, rgb)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=386</id>
		<title>ConfigAPI</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=386"/>
		<updated>2024-09-29T00:17:47Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Remove tutorial in favor of putting it at Tutorials/Persisting-Variables&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Host only|kind=API}}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ConfigAPI&amp;lt;/code&amp;gt; allows storing and loading data between reloads of your avatar.&lt;br /&gt;
&lt;br /&gt;
ConfigAPI is available as the global &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
== Data types ==&lt;br /&gt;
Only some data types are supported by ConfigAPI. All other data types will be converted to {{type|nil}}. The supported data types are:&lt;br /&gt;
* {{type|nil}}&lt;br /&gt;
* {{type|boolean}}&lt;br /&gt;
* {{type|string}}&lt;br /&gt;
* {{type|number}}&lt;br /&gt;
* {{type|table}}&lt;br /&gt;
* all types of {{type|Vector}}&lt;br /&gt;
* all types of {{type|Matrix}}&lt;br /&gt;
== ConfigAPI methods ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration switching ===&lt;br /&gt;
&lt;br /&gt;
==== setName ====&lt;br /&gt;
----&lt;br /&gt;
Also available as &amp;lt;code&amp;gt;ConfigAPI:name&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sets the name of the configuration file to read and write data to. By default, the name of the configuration file is the same as the name of the currently loaded avatar.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setName(name {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;my_config_file_name&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== getName ====&lt;br /&gt;
----&lt;br /&gt;
Returns the name of the active configuration file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getName()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|string}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print the active configuration file&#039;s name.&lt;br /&gt;
print(config:getName())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading and writing data ===&lt;br /&gt;
==== load ====&lt;br /&gt;
----&lt;br /&gt;
Read a saved value from the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]]) by key and return it.&lt;br /&gt;
If no key is given, return all of the saved keys and values in a table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load(key {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|any|?}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|table}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print all saved values.&lt;br /&gt;
printTable(config:load())&lt;br /&gt;
-- Print one specific value.&lt;br /&gt;
print(config:load(&amp;quot;my_value&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== save ====&lt;br /&gt;
----&lt;br /&gt;
Associate a key with a value in the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]].) Only some types of values are allowed; see [[ConfigAPI#Data Types|Data Types]] for details.&lt;br /&gt;
&lt;br /&gt;
If {{type|nil}} is provided as the value, then the key is removed from the file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;save(key {{type|string}}, value {{type|any|?}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Save a value to be used later.&lt;br /&gt;
config:save(&amp;quot;my_value&amp;quot;, &amp;quot;Figura Wiki&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Navigation ==&lt;br /&gt;
{{Navbox documentation}}&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=385</id>
		<title>Tutorials/Persisting-Variables</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=Tutorials/Persisting-Variables&amp;diff=385"/>
		<updated>2024-09-29T00:17:00Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Move from configapi&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Avatars can use the [[ConfigAPI]] to make their variables persist across reloads. This can be used for things such as saving settings across avatars or saving information about an avatar&#039;s state. &lt;br /&gt;
&lt;br /&gt;
To begin with, create a config file. This can be done with either a script or a /figura run command; it&#039;s safest to use a script in an IDE to have syntax highlighting and avoid errors. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- All keys must be strings!&lt;br /&gt;
config:save(&amp;quot;pantsColor&amp;quot;, vec(0.5, 0.8, 0.1))&lt;br /&gt;
config:save(&amp;quot;hatVisible&amp;quot;, true)&lt;br /&gt;
config:save(&amp;quot;legLength&amp;quot;, 5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Run this script by selecting the avatar it&#039;s under. Once it&#039;s run, check the existence of the &amp;lt;code&amp;gt;variablePersistence.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;figura/config&amp;lt;/code&amp;gt;. If it&#039;s there, that code can be deleted. Next, make some code to read the data in that file when the script is loaded. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- The &amp;quot;or (value)&amp;quot; syntax sets the default value if the config:load is nil&lt;br /&gt;
local hatVisible = config:load(&amp;quot;hatVisible&amp;quot;) or true&lt;br /&gt;
local legLength = config:load(&amp;quot;legLength&amp;quot;) or 1&lt;br /&gt;
local pantsColor = config:load(&amp;quot;pantsColor&amp;quot;) or vec(0.9, 0.1, 0.9)&lt;br /&gt;
&lt;br /&gt;
function pings.updateFromConfig(hat, leg, pants)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(hat)&lt;br /&gt;
&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, leg, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, leg, 1)&lt;br /&gt;
    &lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
pings.updateFromConfig(hatVisible, legLength, pantsColor)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Finally, make some code that updates the config when you change values.&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Check if host:isHost() to ensure that the config:save only runs for the host&lt;br /&gt;
function pings.toggleHat(state)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(state)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;hatVisible&amp;quot;, state)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.scaleLegs(scale)&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, scale, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, scale, 1)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;legLength&amp;quot;, scale)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.colorPants(rgb)&lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;pantsColor&amp;quot;, rgb)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=379</id>
		<title>ConfigAPI</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=379"/>
		<updated>2024-09-28T21:16:24Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: nil checks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Host only|kind=API}}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ConfigAPI&amp;lt;/code&amp;gt; allows storing and loading data between reloads of your avatar.&lt;br /&gt;
&lt;br /&gt;
ConfigAPI is available as the global &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
== Tutorial ==&lt;br /&gt;
&lt;br /&gt;
To begin with, create a config file. This can be done with either a script or a /figura run command; it&#039;s safest to use a script in an IDE to have syntax highlighting and avoid errors. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- All keys must be strings!&lt;br /&gt;
config:save(&amp;quot;pantsColor&amp;quot;, vec(0.5, 0.8, 0.1))&lt;br /&gt;
config:save(&amp;quot;hatVisible&amp;quot;, true)&lt;br /&gt;
config:save(&amp;quot;legLength&amp;quot;, 5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Run this script by selecting the avatar it&#039;s under. Once it&#039;s run, check the existence of the &amp;lt;code&amp;gt;variablePersistence.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;figura/config&amp;lt;/code&amp;gt;. If it&#039;s there, that code can be deleted. Next, make some code to read the data in that file when the script is loaded. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- The &amp;quot;or (value)&amp;quot; syntax sets the default value if the config:load is nil&lt;br /&gt;
local hatVisible = config:load(&amp;quot;hatVisible&amp;quot;) or true&lt;br /&gt;
local legLength = config:load(&amp;quot;legLength&amp;quot;) or 1&lt;br /&gt;
local pantsColor = config:load(&amp;quot;pantsColor&amp;quot;) or vec(0.9, 0.1, 0.9)&lt;br /&gt;
&lt;br /&gt;
function pings.updateFromConfig(hat, leg, pants)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(hat)&lt;br /&gt;
&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, leg, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, leg, 1)&lt;br /&gt;
    &lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
pings.updateFromConfig(hatVisible, legLength, pantsColor)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Finally, make some code that updates the config when you change values.&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Check if host:isHost() to ensure that the config:save only runs for the host&lt;br /&gt;
function pings.toggleHat(state)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(state)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;hatVisible&amp;quot;, state)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.scaleLegs(scale)&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, scale, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, scale, 1)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;legLength&amp;quot;, scale)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.colorPants(rgb)&lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;pantsColor&amp;quot;, rgb)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Data types ==&lt;br /&gt;
Only some data types are supported by ConfigAPI. All other data types will be converted to {{type|nil}}. The supported data types are:&lt;br /&gt;
* {{type|nil}}&lt;br /&gt;
* {{type|boolean}}&lt;br /&gt;
* {{type|string}}&lt;br /&gt;
* {{type|number}}&lt;br /&gt;
* {{type|table}}&lt;br /&gt;
* all types of {{type|Vector}}&lt;br /&gt;
* all types of {{type|Matrix}}&lt;br /&gt;
== ConfigAPI methods ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration switching ===&lt;br /&gt;
&lt;br /&gt;
==== setName ====&lt;br /&gt;
----&lt;br /&gt;
Also available as &amp;lt;code&amp;gt;ConfigAPI:name&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sets the name of the configuration file to read and write data to. By default, the name of the configuration file is the same as the name of the currently loaded avatar.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setName(name {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;my_config_file_name&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== getName ====&lt;br /&gt;
----&lt;br /&gt;
Returns the name of the active configuration file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getName()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|string}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print the active configuration file&#039;s name.&lt;br /&gt;
print(config:getName())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading and writing data ===&lt;br /&gt;
==== load ====&lt;br /&gt;
----&lt;br /&gt;
Read a saved value from the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]]) by key and return it.&lt;br /&gt;
If no key is given, return all of the saved keys and values in a table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load(key {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|any|?}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|table}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print all saved values.&lt;br /&gt;
printTable(config:load())&lt;br /&gt;
-- Print one specific value.&lt;br /&gt;
print(config:load(&amp;quot;my_value&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== save ====&lt;br /&gt;
----&lt;br /&gt;
Associate a key with a value in the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]].) Only some types of values are allowed; see [[ConfigAPI#Data Types|Data Types]] for details.&lt;br /&gt;
&lt;br /&gt;
If {{type|nil}} is provided as the value, then the key is removed from the file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;save(key {{type|string}}, value {{type|any|?}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Save a value to be used later.&lt;br /&gt;
config:save(&amp;quot;my_value&amp;quot;, &amp;quot;Figura Wiki&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Navigation ==&lt;br /&gt;
{{Navbox documentation}}&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=376</id>
		<title>ConfigAPI</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=ConfigAPI&amp;diff=376"/>
		<updated>2024-09-28T21:09:21Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Add silly little tutorial :3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Host only|kind=API}}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ConfigAPI&amp;lt;/code&amp;gt; allows storing and loading data between reloads of your avatar.&lt;br /&gt;
&lt;br /&gt;
ConfigAPI is available as the global &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
To begin with, create a config file. This can be done with either a script or a /figura run command; it&#039;s safest to use a script in an IDE to have syntax highlighting and avoid errors. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
-- All keys must be strings!&lt;br /&gt;
config:save(&amp;quot;pantsColor&amp;quot;, vec(0.5, 0.8, 0.1))&lt;br /&gt;
config:save(&amp;quot;hatVisible&amp;quot;, true)&lt;br /&gt;
config:save(&amp;quot;legLength&amp;quot;, 5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Run this script by selecting the avatar it&#039;s under. Once it&#039;s run, check the existence of the &amp;lt;code&amp;gt;variablePersistence.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;figura/config&amp;lt;/code&amp;gt;. If it&#039;s there, that code can be deleted. Next, make some code to read the data in that file when the script is loaded. &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;variablePersistence&amp;quot;)&lt;br /&gt;
local hatVisible = config:load(&amp;quot;hatVisible&amp;quot;)&lt;br /&gt;
local legLength = config:load(&amp;quot;legLength&amp;quot;)&lt;br /&gt;
local pantsColor = config:load(&amp;quot;pantsColor&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function pings.updateFromConfig(hat, leg, pants)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(hat)&lt;br /&gt;
&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, leg, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, leg, 1)&lt;br /&gt;
    &lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(pants)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
pings.updateFromConfig(hatVisible, legLength, pantsColor)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Finally, make some code that updates the config when you change values.&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Check if host:isHost() to ensure that the config:save only runs for the host&lt;br /&gt;
function pings.toggleHat(state)&lt;br /&gt;
    models.model.root.Head.Hat:setVisible(state)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;hatVisible&amp;quot;, state)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.scaleLegs(scale)&lt;br /&gt;
    models.model.root.LeftLeg:setScale(1, scale, 1)&lt;br /&gt;
    models.model.root.RightLeg:setScale(1, scale, 1)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;legLength&amp;quot;, scale)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function pings.colorPants(rgb)&lt;br /&gt;
    models.model.root.LeftLeg[&amp;quot;Left Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    models.model.root.RightLeg[&amp;quot;Right Pants&amp;quot;]:setColor(rgb)&lt;br /&gt;
    if host:isHost() then&lt;br /&gt;
        config:save(&amp;quot;pantsColor&amp;quot;, rgb)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Data Types ==&lt;br /&gt;
Only some data types are supported by ConfigAPI. All other data types will be converted to {{type|nil}}. The supported data types are:&lt;br /&gt;
* {{type|nil}}&lt;br /&gt;
* {{type|boolean}}&lt;br /&gt;
* {{type|string}}&lt;br /&gt;
* {{type|number}}&lt;br /&gt;
* {{type|table}}&lt;br /&gt;
* all types of {{type|Vector}}&lt;br /&gt;
* all types of {{type|Matrix}}&lt;br /&gt;
== ConfigAPI Methods ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration Switching ===&lt;br /&gt;
&lt;br /&gt;
==== setName ====&lt;br /&gt;
----&lt;br /&gt;
Also available as &amp;lt;code&amp;gt;ConfigAPI:name&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sets the name of the configuration file to read and write data to. By default, the name of the configuration file is the same as the name of the currently loaded avatar.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setName(name {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
config:setName(&amp;quot;my_config_file_name&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== getName ====&lt;br /&gt;
----&lt;br /&gt;
Returns the name of the active configuration file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getName()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|string}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print the active configuration file&#039;s name.&lt;br /&gt;
print(config:getName())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading and Writing Data ===&lt;br /&gt;
==== load ====&lt;br /&gt;
----&lt;br /&gt;
Read a saved value from the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]]) by key and return it.&lt;br /&gt;
If no key is given, return all of the saved keys and values in a table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load(key {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|any|?}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;load()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|table}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Print all saved values.&lt;br /&gt;
printTable(config:load())&lt;br /&gt;
-- Print one specific value.&lt;br /&gt;
print(config:load(&amp;quot;my_value&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== save ====&lt;br /&gt;
----&lt;br /&gt;
Associate a key with a value in the active configuration file (see [[ConfigAPI#ConfigAPI:setName|setName]].) Only some types of values are allowed; see [[ConfigAPI#Data Types|Data Types]] for details.&lt;br /&gt;
&lt;br /&gt;
If {{type|nil}} is provided as the value, then the key is removed from the file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;save(key {{type|string}}, value {{type|any|?}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ConfigAPI}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Save a value to be used later.&lt;br /&gt;
config:save(&amp;quot;my_value&amp;quot;, &amp;quot;Figura Wiki&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Navigation ==&lt;br /&gt;
{{Navbox documentation}}&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=ModelPart&amp;diff=245</id>
		<title>ModelPart</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=ModelPart&amp;diff=245"/>
		<updated>2024-09-27T03:31:44Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Grammar stuff :smile+1:&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A ModelPart represents a Cube, Mesh, or Group from Blockbench.&lt;br /&gt;
&lt;br /&gt;
Via scripting, ModelParts can be modified dynamically to achieve whatever visuals you need (limited to Minecraft&#039;s rendering engine)&lt;br /&gt;
&lt;br /&gt;
== Accessing ModelParts ==&lt;br /&gt;
&amp;lt;code&amp;gt;models&amp;lt;/code&amp;gt; is the global that acts as the Root of your avatar and is where all ModelParts are stored, either as a child of &amp;lt;code&amp;gt;models&amp;lt;/code&amp;gt;, a child of a child, or further down the tree.&lt;br /&gt;
&lt;br /&gt;
Specifically, &amp;lt;code&amp;gt;models&amp;lt;/code&amp;gt;&#039;s children are Blockbench models. When an avatar is selected, not only are a bbmodel&#039;s Cubes, Meshes, and Groups converted into ModelParts, but the bbmodel file itself is converted into a ModelPart.&lt;br /&gt;
&lt;br /&gt;
To access a child ModelPart from a parent ModelPart, [https://www.lua.org/pil/2.5.html index] the parent using the child&#039;s name as a string.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local bbmodel = models[&amp;quot;model&amp;quot;] -- access the bbmodel &amp;quot;model.bbmodel&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This logic is the same for every single ModelPart. If you want to access a child, index the parent with the child&#039;s name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Fun Fact: models itself is a ModelPart&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below example accesses the Head Group from the [[WikiExampleAvatar]]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models[&amp;quot;model&amp;quot;][&amp;quot;root&amp;quot;][&amp;quot;Head&amp;quot;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If the above seems tedious, Lua provides a shorthand way of indexing with strings. It only works when the string contains no spaces or special characters.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- Below is invalid, as the name contains spaces&lt;br /&gt;
local superMegaAwsomeThing = models.model.root.Super Mega Awsome Thing&lt;br /&gt;
&lt;br /&gt;
-- Super Mega Awsome Thing would need to be indexed with the normal method&lt;br /&gt;
local superMegaAwsomeThing = models.model.root[&amp;quot;Super Mega Awsome Thing&amp;quot;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BBModels within folders ===&lt;br /&gt;
When a bbmodel is within a folder, Figura will actually turn the folder itself into a ModelPart. This can be confusing as ModelParts are the only thing that does this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local folderHead = models.folder.model.root.Head&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ModelPart ParentTypes ==&lt;br /&gt;
In Figura, a ParentType is applied to a ModelPart causing the ModelPart to behave in a predefined way. This behavior includes acting as a vanilla part like the Head or LeftLeg, moving the rendering of special parts like held items, armor, or parrots, and binding the ModelPart to the World instead of the Player.&lt;br /&gt;
&lt;br /&gt;
ParentTypes can either be applied in Blockbench itself or via script.&lt;br /&gt;
=== ParentTypes via BlockBench ===&lt;br /&gt;
To define a ParentType in Blockbench, the name of a Group must begin with a case-sensitive ParentType.&lt;br /&gt;
&lt;br /&gt;
For example, the &amp;lt;code&amp;gt;Head&amp;lt;/code&amp;gt; ParentType causes the ModelPart to move and rotate like the vanilla Head. If you name a Group the following, it will have this ParentType:&lt;br /&gt;
&lt;br /&gt;
* Head&lt;br /&gt;
* HEAD&lt;br /&gt;
* Head2&lt;br /&gt;
* HeadPhones&lt;br /&gt;
&lt;br /&gt;
If you name a group the following, &amp;lt;b&amp;gt;it will not&amp;lt;/b&amp;gt; have the &amp;lt;code&amp;gt;Head&amp;lt;/code&amp;gt; ParentType:&lt;br /&gt;
&lt;br /&gt;
* head    =&amp;gt; &#039;head&#039; is not a valid ParentType. Capitalization matters!&lt;br /&gt;
* BigHead =&amp;gt; Does not begin with ParentType&lt;br /&gt;
* HeAd    =&amp;gt; &#039;HeAd&#039; is not a valid ParentType. Capitalization matters!&lt;br /&gt;
&lt;br /&gt;
Do note that some English words naturally start with a ParentType which can cause unintended behavior!&lt;br /&gt;
&lt;br /&gt;
For example, the word &amp;quot;Guitar&amp;quot;. Seems innocent, right? Well, &amp;quot;Guitar&amp;quot; starts with &amp;quot;Gui&amp;quot;, and &amp;quot;Gui&amp;quot; is an alias for the ParentType &amp;lt;code&amp;gt;Hud&amp;lt;/code&amp;gt;, a ParentType that binds the ModelPart to the Heads Up Display where the hotbar and inventory reside. This causes the ModelPart to not be visible, as &amp;lt;code&amp;gt;Hud&amp;lt;/code&amp;gt; parts have special rules. Be careful!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Note: ParentTypes are sometimes called Keywords by legacy Figura users&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ParentTypes via Script ===&lt;br /&gt;
Calling the &amp;lt;code&amp;gt;setParentType&amp;lt;/code&amp;gt; on &amp;lt;em&amp;gt;any&amp;lt;/em&amp;gt; ModelPart will override it&#039;s ParentType.&lt;br /&gt;
&lt;br /&gt;
Simply [[ModelParts#Accessing_ModelParts|access]] the ModelPart, then call &amp;lt;code&amp;gt;setParentType&amp;lt;/code&amp;gt; on it, passing in the ParentType as a string.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
head:setParentType(&amp;quot;RightArm&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
To remove a ParentType from a ModelPart, call &amp;lt;code&amp;gt;setParentType&amp;lt;/code&amp;gt; with the string &amp;lt;code&amp;gt;&amp;quot;None&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
head:setParentType(&amp;quot;None&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ModelParts &amp;lt;b&amp;gt;do not&amp;lt;/b&amp;gt; remember their original ParentType! If you need a ModelPart&#039;s original ParentType, store it in a variable for later:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
local headParentType = head:getParentType()&lt;br /&gt;
head:setParentType(&amp;quot;None&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== ModelPart Methods ==&lt;br /&gt;
&lt;br /&gt;
=== ModelPart Properties ===&lt;br /&gt;
Read-only properties of a ModelPart&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getName&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the name of this ModelPart. ModelParts can have duplicate names.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getName()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|string}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
print(head:getName()) --&amp;gt; &amp;quot;Head&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getType&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the original type of this ModelPart. Can be &amp;lt;code&amp;gt;Cube&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Mesh&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;. BBModels and folders are considered Groups. Cubes with no texture data are also considered Groups, as with no texture data their face data is stripped.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getType()&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;Cube&amp;quot; | &amp;quot;Mesh&amp;quot; | &amp;quot;Group&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
print(head:getType()) --&amp;gt; &amp;quot;Group&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Child Manipulation ===&lt;br /&gt;
Methods relating to getting other ModelParts and manipulating the ModelPart tree&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getParent&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the parent of this ModelPart, or &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; if this is &amp;lt;code&amp;gt;models&amp;lt;/code&amp;gt; or a loose ModelPart created via script.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getParent()&amp;lt;/code&amp;gt;&lt;br /&gt;
|| {{type|ModelPart}} | {{type|nil}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
print(head:getParent()) --&amp;gt; ModelPart(root)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getChildren&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns an array of all children of this ModelPart&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getChildren()&amp;lt;/code&amp;gt;&lt;br /&gt;
|| {{type|ModelPart|[]}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local root = models.model.root&lt;br /&gt;
print(root:getChildren()) --[[&lt;br /&gt;
ModelPart(Head), &lt;br /&gt;
ModelPart(Body), &lt;br /&gt;
ModelPart(RightArm), &lt;br /&gt;
ModelPart(LeftArm), &lt;br /&gt;
ModelPart(RightLeg), &lt;br /&gt;
ModelPart(LeftLeg),&lt;br /&gt;
]]--&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:isChildOf&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Recursively checks if this child is a decedent of the provided ModelPart.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;isChildOf(part {{type|ModelPart}})&amp;lt;/code&amp;gt;&lt;br /&gt;
|| {{type|boolean}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local model = models.model&lt;br /&gt;
local head = model.root.Head&lt;br /&gt;
print(head:isChildOf(model)) --&amp;gt; true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:copy&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Copies the data of this ModelPart, assigning it a new name, then returning it. The new name has nothing to do with ParentTypes. The children of the copy are references to the original ModelPart&#039;s children. Extra work needs to be done to recursively copy it&#039;s children. The [[ModelPart#ModelPart_addChild|addChild]] method can then be used to add the copy to the ModelPart tree.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy(newName {{type|string}})&amp;lt;/code&amp;gt;&lt;br /&gt;
|| {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
local headCopy = head:copy(&amp;quot;NewHead&amp;quot;)&lt;br /&gt;
print(headCopy) --&amp;gt; ModelPart(NewHead)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- The parentType is copied with the ModelPart&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
local headCopy = head:copy(&amp;quot;NewHead&amp;quot;)&lt;br /&gt;
print(headCopy:getParentType()) --&amp;gt; &amp;quot;Head&amp;quot;&lt;br /&gt;
&lt;br /&gt;
headCopy:setParentType(&amp;quot;None&amp;quot;)&lt;br /&gt;
print(headCopy:getParentType()) --&amp;gt; &amp;quot;None&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setParentType|setParentType]], [[ModelParts#ModelPart:getParentType|getParentType]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Extra work is needed to deep copy a ModelPart&#039;s children as well&lt;br /&gt;
local function deepCopy(model)&lt;br /&gt;
    local copy = model:copy(model:getName())&lt;br /&gt;
    for _, child in pairs(copy:getChildren()) do&lt;br /&gt;
        copy:removeChild(child):addChild(deepCopy(child))&lt;br /&gt;
    end&lt;br /&gt;
    return copy&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
local headCube = head.Head&lt;br /&gt;
&lt;br /&gt;
-- headCopyA contains references to head&#039;s children because it is a shallow copy&lt;br /&gt;
local headCopyA = head:copy(&amp;quot;NewHead&amp;quot;)&lt;br /&gt;
print(headCopyA.Head == headCube) --&amp;gt; true&lt;br /&gt;
&lt;br /&gt;
-- headCopyB contains true copies of head&#039;s children as it was passed through a function that recursively copies children&lt;br /&gt;
local headCopyB = deepCopy(head)&lt;br /&gt;
print(headCopyB.Head == headCube) --&amp;gt; false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:getName|getName]], [[ModelParts#ModelPart:getChildren|getChildren]], [[ModelParts#ModelPart:addChild|addChild]], [[ModelParts#ModelPart:removeChild|removeChild]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:addChild&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Adds the provided ModelPart as one of this ModelPart&#039;s children. Beware of adding a parent of this ModelPart as a child! This method returns this ModelPart for method chaining.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addChild(part {{type|ModelPart}})&amp;lt;/code&amp;gt;&lt;br /&gt;
|| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local root = models.model.root&lt;br /&gt;
local headCopy = root.Head:copy(&amp;quot;NewHead&amp;quot;)&lt;br /&gt;
root:addChild(headCopy)&lt;br /&gt;
headCopy:setPos(10,0,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:copy|copy]], [[ModelParts#ModelPart:setPos|setPos]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:removeChild&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Removes a child from this ModelPart. Takes in the child ModelPart itself. This method returns this ModelPart for method chaining.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;removeChild(partToRemove {{type|ModelPart}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local root = models.model.root&lt;br /&gt;
local head = root.Head&lt;br /&gt;
root:removeChild(head) -- Bye bye Head!&lt;br /&gt;
&lt;br /&gt;
-- Head is still valid and can be re-added later, so long as we keep a variable referencing it.&lt;br /&gt;
print(head) --&amp;gt; ModelPart(Head)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:remove&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Removes this ModelPart from the parent&#039;s child list. Returns self&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;remove()&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
head:remove() -- Bye bye Head!&lt;br /&gt;
&lt;br /&gt;
-- Head is still valid and can be re-added, so long as we keep a variable referencing it.&lt;br /&gt;
print(head) --&amp;gt; ModelPart(Head)&lt;br /&gt;
models.model.root.LeftLeg:addChild(head)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:addChild|addChild]]&lt;br /&gt;
&lt;br /&gt;
=== Manipulation ===&lt;br /&gt;
Methods relating to manipulating the ModelPart within physical space&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setPos&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets the offset of the the position of the ModelPart. Position translation applies on the local rotation axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPos(pos {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPos(x {{type|number}}, y {{type|number}}, z {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- Move 10 units on the local y axis&lt;br /&gt;
head:setPos(0, 10, 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getPos&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setPos&amp;lt;/code&amp;gt;.  Always 0,0,0 when script begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getPos()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getPos()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
head:setPos(0, 10, 0)&lt;br /&gt;
print(head:getPos()) --&amp;gt; vec(0,10,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setPos|setPos]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setRot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets the rotation of the ModelPart. Rotates the ModelPart around the PivotPoint.&lt;br /&gt;
&lt;br /&gt;
Angles are interpreted as degrees. &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setRot(rot {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setRot(pitch {{type|number}}, yaw {{type|number}}, roll {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- Rotate 45 degrees on the x axis, causing the avatar to look down&lt;br /&gt;
head:setRot(0, 45, 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getRot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setRot&amp;lt;/code&amp;gt;. Will be the Rotation values defined in BlockBench when script begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getRot()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getRot()) --&amp;gt; vec(0,0,0) -- Most ModelParts will not have a rotation set in blockbench&lt;br /&gt;
head:setRot(45, 0, 0)&lt;br /&gt;
print(head:getPos()) --&amp;gt; vec(45,0,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setRot|setRot]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setScale&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets the scale of the ModelPart. Scales the ModelPart around the PivotPoint.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 1. If a number is provided for x and both y and z are not defined, x will be used for all 3 axis.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setScale(scale {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setScale(scaleAll {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setScale(x {{type|number}}, y {{type|number}}, z {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
-- Double the size of the head&lt;br /&gt;
head:setScale(2)&lt;br /&gt;
-- Squishes and stretches the entire model&lt;br /&gt;
models.model:setScale(1.5, 0.75, 1.5)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getScale&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setScale&amp;lt;/code&amp;gt;.  Always 1,1,1 when script begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getScale()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getScale()) --&amp;gt; vec(1,1,1)&lt;br /&gt;
head:setScale(2)&lt;br /&gt;
print(head:getScale()) --&amp;gt; vec(2,2,2)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setScale|setScale]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setPivot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets the pivot point of the ModelPart. &#039;&#039;This overrides the pivot point defined in blockbench.&#039;&#039; It is recommended to use [[ModelParts#ModelPart:setOffsetPivot|setOffsetPivot]] instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPivot(pivot {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPivot(x {{type|number}}, y {{type|number}}, z {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- For a normal size humanoid model, the Head&#039;s pivot point is usually at 0,24,0&lt;br /&gt;
-- If we assume that the Head cube is an 8x8x8 cube,&lt;br /&gt;
-- then the head will rotate around the center of the cube instead of the neck&lt;br /&gt;
head:setPivot(0, 28, 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getPivot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the Pivot Point defined in BlockBench, or the value set by &amp;lt;code&amp;gt;setPivot&amp;lt;/code&amp;gt; if it was already overwritten.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getPivot()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- The Head group&#039;s pivot point for a humanoid model is usually at 0,24,0&lt;br /&gt;
print(head:getPivot()) --&amp;gt; vec(0,24,0)&lt;br /&gt;
head:setPivot(0,0,0)&lt;br /&gt;
-- We have completely ruined the rendering of this ModelPart&lt;br /&gt;
print(head:getPivot()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setPivot|setPivot]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setOffsetRot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets a rotation value that will be added to the ModelPart&#039;s rotation.&lt;br /&gt;
&lt;br /&gt;
Angles are interpreted as degrees. &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetRot(rot {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetRot(pitch {{type|number}}, yaw {{type|number}}, roll {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- ModelParts inherit their rotation from blockbench. The Head usually has a rotation of 0,0,0 for consistency with the vanilla model&lt;br /&gt;
print(head:getRot()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
-- Set the offset to 45 degrees on the x axis, causing the avatar to look down&lt;br /&gt;
head:setOffsetRot(0, 45, 0)&lt;br /&gt;
-- The original rotation is unchanged.&lt;br /&gt;
print(head:getRot()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
&lt;br /&gt;
-- setOffsetRot is not additive.&lt;br /&gt;
head:setOffsetRot(0, 25, 0)&lt;br /&gt;
print(head:getOffsetRot()) --&amp;gt; vec(0,25,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:getRot|getRot]] [[ModelParts#ModelPart:getOffsetRot|getOffsetRot]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getOffsetRot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setOffsetRot&amp;lt;/code&amp;gt;. Will be 0,0,0 when the script begins&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getOffsetRot()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getOffsetRot()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
head:setOffsetRot(45, 0, 0)&lt;br /&gt;
print(head:getOffsetRot()) --&amp;gt; vec(45,0,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setOffsetRot|setOffsetRot]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setOffsetScale&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets a scale value that will be multiplied with the ModelPart&#039;s scale.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 1. If a number is provided for x and both y and z are not defined, x will be used for all 3 axis.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetScale(scale {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetScale(scaleAll {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetScale(x {{type|number}}, y {{type|number}}, z {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
-- Double the size of the head&lt;br /&gt;
head:setScale(2)&lt;br /&gt;
-- Half the size of the head&lt;br /&gt;
head:setOffsetScale(0.5)&lt;br /&gt;
-- Results in no changes&lt;br /&gt;
-- I have no idea what this is used for&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getOffsetScale&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setOffsetScale&amp;lt;/code&amp;gt;.  Always 1,1,1 when script begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getOffsetScale()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getOffsetScale()) --&amp;gt; vec(1,1,1)&lt;br /&gt;
head:setOffsetScale(2)&lt;br /&gt;
print(head:getOffsetScale()) --&amp;gt; vec(2,2,2)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setOffsetScale|setOffsetScale]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setOffsetPivot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Sets a value that will be added to the ModelPart&#039;s pivot point.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; values are interpreted as 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetPivot(pivot {{type|Vector3}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setOffsetPivot(x {{type|number}}, y {{type|number}}, z {{type|number}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
-- If we assume that the Head cube is an 8x8x8 cube and offset the pivot up by 4,&lt;br /&gt;
-- then the head will rotate around the center of the cube instead of the neck&lt;br /&gt;
head:setOffsetPivot(0, 4, 0)&lt;br /&gt;
-- Notice that we did not need to know the original pivot point to do this&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getOffsetPivot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the value that was used for &amp;lt;code&amp;gt;setOffsetPivot&amp;lt;/code&amp;gt;.  Always 0,0,0 when script begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getOffsetPivot()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(head:getOffsetPivot()) --&amp;gt; vec(0,0,0)&lt;br /&gt;
head:setOffsetPivot(0,4,0)&lt;br /&gt;
print(head:getOffsetPivot()) --&amp;gt; vec(0,4,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;@see&#039;&#039;&#039; [[ModelParts#ModelPart:setOffsetPivot|setOffsetPivot]]&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:setMatrix&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Allows you to manually define the matrix used for positioning this ModelPart. Returns self for method chaining.&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;setPos&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setScale&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setPivot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setOffsetRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setOffsetScale&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;setOffsetPivot&amp;lt;/code&amp;gt; will undo &amp;lt;code&amp;gt;setMatrix&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;getPos&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getScale&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getPivot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getOffsetRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getOffsetScale&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;getOffsetPivot&amp;lt;/code&amp;gt; will return invalid values while &amp;lt;code&amp;gt;setMatrix&amp;lt;/code&amp;gt; is in effect. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;getTruePos&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getTrueRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getTrueScale&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;getTruePivot&amp;lt;/code&amp;gt; are probably also affected, but nobody tested them yet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setMatrix(matrix {{type|Matrix4}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- no example provided&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getTruePos&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the position after all calculations are done. This includes &amp;lt;code&amp;gt;setPos&amp;lt;/code&amp;gt; and the data from all playing Animations.&lt;br /&gt;
&lt;br /&gt;
This does not include ParentTypes or transformations applied from a parent part.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getTruePos()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- no example provided&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getTrueRot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the rotation after all calculations are done. This includes &amp;lt;code&amp;gt;setRot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setOffsetRot&amp;lt;/code&amp;gt;, and the data from all playing Animations.&lt;br /&gt;
&lt;br /&gt;
This does not include ParentTypes or transformations applied from a parent part.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getTruePos()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- no example provided&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getTrueScale&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the scale after all calculations are done. This includes &amp;lt;code&amp;gt;setScale&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setOffsetScale&amp;lt;/code&amp;gt;, and the data from all playing Animations.&lt;br /&gt;
&lt;br /&gt;
This does not include ParentTypes or transformations applied from a parent part.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getTrueScale()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- no example provided&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;ModelPart:getTruePivot&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Returns the pivot point after all calculations are done. This includes &amp;lt;code&amp;gt;setPivot&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setOffsetPivot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not include ParentTypes or transformations applied from a parent part.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getTruePivot()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|Vector3}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- no example provided&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Manipulation ===&lt;br /&gt;
Methods relating to modifying how a ModelPart looks&lt;br /&gt;
&lt;br /&gt;
todo: put anything related to renderType, textures, and other visual modifications in here&lt;br /&gt;
&lt;br /&gt;
==== ModelPart:setVisible ====&lt;br /&gt;
Sets if this ModelPart is visible or not. Children of this ModelPart will also be invisible while this part is invisible.&lt;br /&gt;
&lt;br /&gt;
A value of &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; is interpreted as &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; on 0.1.4 and below, and &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; on 0.1.5 and above. This message will disappear &amp;lt;s&amp;gt;if&amp;lt;/s&amp;gt; when 0.1.6 is released.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setVisible(visible {{type|boolean}})&amp;lt;/code&amp;gt;&lt;br /&gt;
| self {{type|ModelPart}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local head = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
head:setVisible(false) -- Bye bye Head!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ModelPart:getVisible ====&lt;br /&gt;
Recursively goes up the ModelPart tree until it finds a ModelPart that is invisible, or the ModelPart is &amp;lt;code&amp;gt;models&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, if a parent part is invisible, this function returns &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;. If all parent parts are visible, this function will return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt;. Kinda stupid. This is fixed in 0.1.5 to never return &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Arguments !! Return Type&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getVisible()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|bool}} &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; {{type|nil}} {{until|0.1.5}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getVisible()&amp;lt;/code&amp;gt;&lt;br /&gt;
| {{type|bool}} {{since|0.1.5}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local root = models.model.root.Head&lt;br /&gt;
&lt;br /&gt;
print(root.Head:getVisible()) --&amp;gt; nil --&amp;lt; this is stupid&lt;br /&gt;
root:setVisible(false) -- Bye bye root!&lt;br /&gt;
print(root.Head:getVisible()) --&amp;gt; false&lt;br /&gt;
root:setVisible(true) -- Welcome back root!&lt;br /&gt;
print(root.Head:getVisible()) --&amp;gt; true --&amp;lt; aaaaaaaa&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ModelPart:setColor ====&lt;br /&gt;
Sets a value to multiply with all pixels on the ModelPart&#039;s texture.&lt;br /&gt;
&lt;br /&gt;
=== renderTasks ===&lt;br /&gt;
todo: put all rendertask functions in here &lt;br /&gt;
&lt;br /&gt;
=== Render Methods ===&lt;br /&gt;
todo: Put partToWorldMatrix, preRender, midRender, and PostRender in here&lt;br /&gt;
&lt;br /&gt;
=== Animation Methods ===&lt;br /&gt;
todo: put getAnimPos/Rot/Scale and overrideVanillaPos/Rot/Scale in here&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
	<entry>
		<id>https://wiki.figuramc.org/index.php?title=Blockbench&amp;diff=240</id>
		<title>Blockbench</title>
		<link rel="alternate" type="text/html" href="https://wiki.figuramc.org/index.php?title=Blockbench&amp;diff=240"/>
		<updated>2024-09-27T03:22:39Z</updated>

		<summary type="html">&lt;p&gt;Riftlight: Blockbench capitalization consistency &amp;amp; some grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The basics on how to use Blockbench&lt;br /&gt;
&lt;br /&gt;
Proper tutorials for Blockbench can be found online. This page just explains Figura specific stuff. This page assumes you are using the Desktop version of Blockbench, not the online app.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Properties ==&lt;br /&gt;
&lt;br /&gt;
This is the popup that appears when you create a Project. You can also get to this page via File-&amp;amp;gt;Project.&amp;lt;br/&amp;gt; &amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/project.png&amp;quot;).default} width=&amp;quot;400&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt; Figura only accepts &amp;lt;Emoji icon=&amp;quot;file/bbmodel&amp;quot;/&amp;gt; bbmodels in the Generic Model format. If your format is not Generic Model, Figura will refuse to load the avatar. To convert a project, File-&amp;amp;gt;Convert Project. Deselect &amp;lt;code&amp;gt;Create Copy&amp;lt;/code&amp;gt;, ensure format is Generic Model, and press Confirm. If the popup does not go away after pressing Confirm, close it manually.&amp;lt;br/&amp;gt; &amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/convert_project.png&amp;quot;).default} width=&amp;quot;400&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;File Name&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Model Identifier&amp;lt;/code&amp;gt; fields are unused by Figura.&amp;lt;br/&amp;gt; &amp;lt;code&amp;gt;UV Mode&amp;lt;/code&amp;gt; determines how Blockbench handles how UVs are positioned. Figura will handle both &amp;lt;code&amp;gt;Box UV&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Per-face UV&amp;lt;/code&amp;gt;. Its up to you which you want. UVs determine where a 2D texture is applied to a 3D model. Each face has it’s own UV coordinates which determines where on the 2D texture it will get it’s pixels from.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/uvmode_box.png&amp;quot;).default} width=&amp;quot;200&amp;quot; style={{&amp;quot;float&amp;quot;:&amp;quot;right&amp;quot;}}&amp;gt;&amp;lt;/img&amp;gt; &amp;lt;code&amp;gt;Box UV&amp;lt;/code&amp;gt; forces each face of a cube to match how vanilla does UVs. If you have ever edited your own vanilla skin before, you will recognize the pattern. While this does simplify the texturing process, it limits what you can do. Also, all textures in the model must have the same size, as what is a pixel is determined by the project’s global &amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt; instead of the size of the texture itself. Also, meshes cannot be used while using &amp;lt;code&amp;gt;Box UV&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/uvmode_perface.png&amp;quot;).default} width=&amp;quot;200&amp;quot; style={{&amp;quot;float&amp;quot;:&amp;quot;right&amp;quot;}}&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Per-face UV&amp;lt;/code&amp;gt; allows full control over each face of the cube/mesh. Each face can be positioned, scaled, and rotated individually from each other. You can even set a different texture for each face, or remove a face to reduce clutter. While the pixel grid is effected by the project’s global &amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt;, changing the &amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt; has zero effect on the UVs themselves, unlike &amp;lt;code&amp;gt;Box UV&amp;lt;/code&amp;gt; which will have destructive effects when changing the project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt; field aids with UV calculation. In rendering, UVs are a float from 0-1 representing the percentage of the texture that this point is at. A UV of (0.5,0.5) represents the center of the texture, regardless of the texture’s own size. A way of calculating this percentage is to take the pixel coordinate you want and divide it by the texture’s size. (32,16)/(64,64)=(0.5,0.25). The &amp;lt;code&amp;gt;Texture Size&amp;lt;/code&amp;gt; field determines this texture size globally. Blockbench never uses the texture’s actual size, which causes issues when you have a model with textures of different sizes. Thankfully, changing it only has an effect on ModelParts that use &amp;lt;code&amp;gt;Box UV&amp;lt;/code&amp;gt;, so when you need to edit ModelParts using a different sized texture, you can change this with no worries so long as you are using &amp;lt;code&amp;gt;Per-face UV&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ModelParts ==&lt;br /&gt;
&lt;br /&gt;
=== ParentTypes ===&lt;br /&gt;
&lt;br /&gt;
If the name of a &amp;lt;Emoji icon=&amp;quot;blockbench/group&amp;quot;/&amp;gt; group begins with a specific string, Figura will apply special effects to that group. Some examples include &amp;lt;code&amp;gt;Head&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RightArm&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;. These are called [[../enums/ModelPartParentTypes|ParentTypes]].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Blank&amp;lt;/code&amp;gt; Texture ===&lt;br /&gt;
&lt;br /&gt;
ModelParts that use the Blockbench inbuilt &amp;lt;code&amp;gt;Blank&amp;lt;/code&amp;gt; texture will not be loaded by Figura at all. If you want a Model to not have a texture and assign the texture via script, use the [[../tutorials/Avatar-Metadata|&amp;lt;code&amp;gt;ignoredTextures&amp;lt;/code&amp;gt; metadata customization]]. The &amp;lt;code&amp;gt;Transparent&amp;lt;/code&amp;gt; texture that can only be applied to individual faces in Per-face UV behave the same way. Figura will not load those faces.&lt;br /&gt;
&lt;br /&gt;
=== Meshes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Emoji icon=&amp;quot;blockbench/mesh&amp;quot;/&amp;gt; Meshes are allowed. Nothing special with Figura. This is just here for those that need to be explicitly told Meshes work.&lt;br /&gt;
&lt;br /&gt;
== Textures ==&lt;br /&gt;
&lt;br /&gt;
=== Local/External Textures ===&lt;br /&gt;
&lt;br /&gt;
In Blockbench, textures have 2 distinct states: Local and External.&amp;lt;br/&amp;gt; To determine the state your texture is in, Right Click a texture-&amp;amp;gt;Properties. An External texture will have a file path, while a Local one will not.&amp;lt;br/&amp;gt;There is one key factor for a texture to be External, and that is for the file itself to be inside the avatar’s folder. If the filepath does not lead to a file inside the avatar’s folder, Figura will load it as a Local file.&amp;lt;br/&amp;gt; &amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/texture_local.png&amp;quot;).default} width=&amp;quot;300&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/texture_external.png&amp;quot;).default} width=&amp;quot;300&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether a texture is Local or External will determine how Figura will load it which is important when getting a Texture in script.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Render Mode&amp;lt;/code&amp;gt; field determines how the texture will be rendered. In Blockbench, this changes nothing visually.&amp;lt;br/&amp;gt; &#039;&#039;&#039;Figura ignores &amp;lt;code&amp;gt;Render Mode&amp;lt;/code&amp;gt;.&#039;&#039;&#039; The Primary Texture will always be &amp;lt;code&amp;gt;TRANSLUCENT&amp;lt;/code&amp;gt; by default, and the Secondary Texture will always be &amp;lt;code&amp;gt;EMISSIVE&amp;lt;/code&amp;gt; by default.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Render Sides&amp;lt;/code&amp;gt; field determines if the cube should be rendered when looking at the back of a face.&amp;lt;br/&amp;gt; &#039;&#039;&#039;Figura ignores &amp;lt;code&amp;gt;Render Sides&amp;lt;/code&amp;gt;.&#039;&#039;&#039; To apply the same effect, use the &amp;lt;code&amp;gt;TRANSLUCENT_CULL&amp;lt;/code&amp;gt; [[../enums/RenderTypes|RenderType]] in a script.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Texture Suffix ===&lt;br /&gt;
&lt;br /&gt;
In Blockbench, each cube (face) can only point to a single texture, which means that Figura needs to get creative when it wants to link multiple textures together for stuff like emissive textures.&amp;lt;br/&amp;gt; When Figura loads a texture, it looks for another texture with the same name but with a specific suffix. Then for all ModelParts in Blockbench that use the texture, Figura will link the suffixed texture to that ModelPart as well.&lt;br /&gt;
&lt;br /&gt;
List of suffixes used by Figura:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;_e&amp;lt;/code&amp;gt;: This texture will be used as the Secondary Texture, also known as the [[../tutorials/Emissive%20Textures|Emissive Texture]], of the ModelPart. The Secondary RenderType of a ModelPart is by default &amp;lt;code&amp;gt;EMISSIVE&amp;lt;/code&amp;gt;, but can be changed in script.&lt;br /&gt;
* &amp;lt;code&amp;gt;_n&amp;lt;/code&amp;gt;: This texture will be used as the [https://en.wikipedia.org/wiki/Normal_mapping Normal Texture]. &amp;lt;b&amp;gt;Do not confuse this with the Primary Texture&amp;lt;/b&amp;gt;. “Normal” means something very specific in modeling. This suffix is used with Iris Shaders, and does nothing with vanilla rendering. &amp;lt;b&amp;gt;&amp;lt;i&amp;gt;This suffix currently does not function&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;_s&amp;lt;/code&amp;gt;: This texture will be used as the [https://en.wikipedia.org/wiki/Specularity Specular Texture]. This suffix is used with Iris Shaders, and does nothing with vanilla rendering. &amp;lt;b&amp;gt;&amp;lt;i&amp;gt;This suffix currently does not function&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example is the &amp;lt;Emoji icon=&amp;quot;blockbench/group&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;Head&amp;lt;/code&amp;gt;, &amp;lt;Emoji icon=&amp;quot;file/texture&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;skin&amp;lt;/code&amp;gt;, and &amp;lt;Emoji icon=&amp;quot;file/texture&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;skin_e&amp;lt;/code&amp;gt;. When the &amp;lt;Emoji icon=&amp;quot;blockbench/group&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;Head&amp;lt;/code&amp;gt; uses the texture &amp;lt;Emoji icon=&amp;quot;file/texture&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;skin&amp;lt;/code&amp;gt;, when the Avatar is loaded, &amp;lt;Emoji icon=&amp;quot;file/texture&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;skin_e&amp;lt;/code&amp;gt; is used as the Secondary Texture, ie the Emissive Texture.&amp;lt;br/&amp;gt; &amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/settexture.png&amp;quot;).default} width=&amp;quot;300&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a texture to have the same name, they must both be either [[#localexternal-textures|Local or External]], and should they be external, they must be in the same folder. Otherwise, they will not have the same name internally.&amp;lt;br/&amp;gt; For textures with file extensions, the suffix goes before the extension. &amp;lt;Emoji icon=&amp;quot;file/texture&amp;quot;/&amp;gt; &amp;lt;code&amp;gt;skin_e.png&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
=== Animation Properties ===&lt;br /&gt;
&lt;br /&gt;
This popup appears when you create an animation. To get back to this popup, Right Click an Animation-&amp;amp;gt;Properties.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/animation_properties.png&amp;quot;).default} width=&amp;quot;500&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Name&lt;br /&gt;
: This is the animation’s name. It is very important that you change this to something shorter. The entire textbox is the animation’s name, so unless you want to refer to this animation in lua with &amp;lt;code&amp;gt;animations.player[&amp;quot;animation.model.new&amp;quot;]&amp;lt;/code&amp;gt;, change the name. An animation named just &amp;lt;code&amp;gt;&amp;quot;new&amp;quot;&amp;lt;/code&amp;gt; is indexed via &amp;lt;code&amp;gt;animations.player.new&amp;lt;/code&amp;gt;. Much nicer, right?&lt;br /&gt;
&lt;br /&gt;
; Loop Mode&lt;br /&gt;
: This controls what happens when the animation reaches the end. There are 3 valid loop modes:&lt;br /&gt;
: {{tagged|Play Once|The animation will stop immediately at the end. Note that badly-made animations may have a visible jump to their original position in this mode.}}&lt;br /&gt;
: {{tagged|Hold On Last Frame|The animation will hold the values from its last frame after ending. Note that while an animation is holding, it is still considered playing, so calling &amp;lt;code&amp;gt;:play()&amp;lt;/code&amp;gt; again will do nothing.}}&lt;br /&gt;
: {{tagged|Loop|When the animation reaches its end, it will jump to the beginning. Note that the start and end frames should be the same in this mode, as there won&#039;t be an in-between animation.}}&lt;br /&gt;
&lt;br /&gt;
; Override&lt;br /&gt;
: If this is enabled, Mimic-type [[Enums/ParentTypes|Enums/ParentTypes]] won&#039;t apply their rotations while this animation is playing. Note that keyframes must be present on the specific channel for override to apply! For example, putting a keyframe on Head&#039;s rotation won&#039;t apply override to its position or scale, Body, or even other Heads.&lt;br /&gt;
&lt;br /&gt;
; Snapping&lt;br /&gt;
: This sets what unit of time Blockbench will set animations to. Holding Ctrl allows you to bypass this. Figura ignores this value.&lt;br /&gt;
&lt;br /&gt;
; Anim Time Update&lt;br /&gt;
: &#039;&#039;Default value: 0&#039;&#039;&lt;br /&gt;
: This allows you to set the time Figura starts playing the animation at. For example, setting this to 2 skips the first 2 seconds of the animation. This lets you add keyframes before the animation to help with interpolations.&lt;br /&gt;
: {{tagged|Trivia|In Molang (and, therefore, Blockbench), this sets the animation&#039;s time &#039;&#039;every tick&#039;&#039; to a Molang expression. In Figura, you can achieve the equivalent by calling &amp;lt;code&amp;gt;setTime&amp;lt;/code&amp;gt; in a script.}}&lt;br /&gt;
&lt;br /&gt;
; Blend Weight&lt;br /&gt;
: Every keyframe value in the animation is multiplied by this value. This isn&#039;t very useful itself, but can be used by scripts (for example, [[GSAnimBlend]]) to transition into or out of animations.&lt;br /&gt;
&lt;br /&gt;
; Start Delay&lt;br /&gt;
: &#039;&#039;Default value: 0&#039;&#039;&lt;br /&gt;
: This delays the animation&#039;s start time by the given amount.&lt;br /&gt;
&lt;br /&gt;
; Loop Delay&lt;br /&gt;
: &#039;&#039;Default value: 0&#039;&#039;&lt;br /&gt;
: This sets the amount of time the animation will pause at the end before it loops again. This is only relevant in Loop mode.&lt;br /&gt;
&lt;br /&gt;
=== Keyframe Expressions ===&lt;br /&gt;
&lt;br /&gt;
While Blockbench supports Molang, &#039;&#039;&#039;Figura does not&#039;&#039;&#039;.&amp;lt;br/&amp;gt; To remedy this, Figura allows writing lua code into keyframe fields.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Figura provides data for the keyframe expression, which is accessible via the &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
It has 2 pieces of data, the keyframe time, and the Animation object of the animation itself.&amp;lt;br/&amp;gt; Keyframe time is measured in percentage, not seconds. So, assuming a Step interpolation keyframe, &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is at the time at the keyframe itself and &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; is at the next keyframe. Keyframe time is only useful when the keyframe uses Step interpolation.&amp;lt;br/&amp;gt;When using other interpolation types, the expression will execute before it has reached the keyframe itself to interpolate. While this happens, it will give the Keyframe time of the previous keyframe and go back to zero once it reaches itself.&lt;br /&gt;
&lt;br /&gt;
They can be extracted via the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;local time, anim = ...&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Keyframe Expressions accept 2 different formats:&lt;br /&gt;
&lt;br /&gt;
* A single lua expression that evaluates to a number&lt;br /&gt;
* A lua script that &amp;lt;code&amp;gt;returns&amp;lt;/code&amp;gt; a number&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;math.sin(world.getTime())&amp;lt;/code&amp;gt; is a single lua expression, so it is a valid Keyframe Expression.&amp;lt;br/&amp;gt; However, &amp;lt;code&amp;gt;local _, anim=... math.sin(anim:getTime())&amp;lt;/code&amp;gt; is not a single lua expression and will need to have an explicit return value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;local _, anim = ...&lt;br /&gt;
&lt;br /&gt;
return math.sin(anim:getTime())&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can rewrite it as a single lua expression: &amp;lt;code&amp;gt;math.sin({...}[2]:getTime())&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt; This deconstructs the &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; varargs into a table and grabs the second value.&lt;br /&gt;
&lt;br /&gt;
=== Instruction Keyframes ===&lt;br /&gt;
&lt;br /&gt;
Instruction Keyframes run lua code when the Animation reaches that keyframe. This can be used to play sounds, spawn particles, literally anything. Remember that Lua code is what goes in this spot, not Molang.&amp;lt;br/&amp;gt; You can access Instruction Keyframes via the Magic Wand icon. An Effects timeline should appear along with the other ModelPart timelines.&lt;br /&gt;
&lt;br /&gt;
=== Animation Features That Figura Does Not Care About ===&lt;br /&gt;
&lt;br /&gt;
Below are features provided by Blockbench Animations that figura does not use when loading the bbmodel.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Variable Placeholders&#039;&#039;&#039;&amp;lt;br/&amp;gt; &amp;lt;img src={require(&amp;quot;@site/static/img/blockbench/animation_variableplaceholders.png&amp;quot;).default} width=&amp;quot;200&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br/&amp;gt; This is completely ignored by Figura.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Inverse Kinematics&#039;&#039;&#039;&amp;lt;br/&amp;gt; Don’t bother. Not a thing in Figura.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Global Rotation&#039;&#039;&#039;&amp;lt;br/&amp;gt; There is a toggle for Global Rotation next to the Rotation timeline for ModelParts. Figura does not obey this, so keep it disabled.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sound Keyframes&#039;&#039;&#039;&amp;lt;br/&amp;gt; Figura does not read these. Use [[#instruction-keyframes|Instruction Keyframes]].&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Particle Keyframes&#039;&#039;&#039;&amp;lt;br/&amp;gt; Figura does not read these. Use [[#instruction-keyframes|Instruction Keyframes]].&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riftlight</name></author>
	</entry>
</feed>