[{"data":1,"prerenderedAt":1327},["ShallowReactive",2],{"data":3,"\u002Fwiki\u002Fguides\u002Fanimation-expressions":118},[4,9,14,19,24,29,34,39,44,49,54,59,64,68,73,78,83,88,93,98,103,108,113],{"title":5,"path":6,"description":7,"id":8},"FAQ","\u002Fblockbench\u002Ffaq","Frequently Asked Questions about Blockbench","content\u002Fblockbench\u002Ffaq.md",{"title":10,"path":11,"description":12,"id":13},"Formats","\u002Fblockbench\u002Fformats","formats","content\u002Fblockbench\u002Fformats.md",{"title":15,"path":16,"description":17,"id":18},"Legacy Versions","\u002Fblockbench\u002Flegacy-versions","Blockbench version history and changelogs prior to switching to Github Releases","content\u002Fblockbench\u002Flegacy-versions.md",{"title":20,"path":21,"description":22,"id":23},"Localization","\u002Fblockbench\u002Flocalization","How to contribute to Blockbench languages","content\u002Fblockbench\u002Flocalization.md",{"title":25,"path":26,"description":27,"id":28},"Logos and Brand Assets","\u002Fblockbench\u002Flogos","Frequently Asked Questions about the Blockbench app","content\u002Fblockbench\u002Flogos.md",{"title":30,"path":31,"description":32,"id":33},"Custom Themes","\u002Fblockbench\u002Fthemes","Themes allow you to change the visual appearance of Blockbench. You can drag and drop .bbtheme files into Blockbench to load them.","content\u002Fblockbench\u002Fthemes.md",{"title":35,"path":36,"description":37,"id":38},"The .bbmodel format","\u002Fdocs\u002Fbbmodel","An overview of the .bbmodel file format","content\u002Fdocs\u002Fbbmodel.md",{"title":40,"path":41,"description":42,"id":43},"Blockbench","\u002Fdocs\u002Fblockbench","The Blockbench object provides useful variables and methods to interact with general functionality of Blockbench.","content\u002Fdocs\u002Fblockbench.md",{"title":45,"path":46,"description":47,"id":48},"Upgrading Plugins to 5.0","\u002Fdocs\u002Fplugin-upgrade-to-5.0","An overview of breaking changes in the plugin API in 5.0","content\u002Fdocs\u002Fplugin-upgrade-to-5.0.md",{"title":50,"path":51,"description":52,"id":53},"Creating a Plugin","\u002Fdocs\u002Fplugin","This article will go over the basic steps needed to create your first plugin.","content\u002Fdocs\u002Fplugin.md",{"title":55,"path":56,"description":57,"id":58},"Properties","\u002Fdocs\u002Fproperty","Properties are used to dynamically assign properties to existing classes that are undo-relevant.\nThe advantages of using properties include:","content\u002Fdocs\u002Fproperty.md",{"title":60,"path":61,"description":62,"id":63},"Interface","\u002Fdocs\u002Fui","","content\u002Fdocs\u002Fui.md",{"title":65,"path":66,"description":62,"id":67},"Undo","\u002Fdocs\u002Fundo","content\u002Fdocs\u002Fundo.md",{"title":69,"path":70,"description":71,"id":72},"Web App URL Parameters","\u002Fdocs\u002Furl-parameters","How to provide integration with the Blockbench web app using URL parameters","content\u002Fdocs\u002Furl-parameters.md",{"title":74,"path":75,"description":76,"id":77},"Utils","\u002Fdocs\u002Futility","Blockbench comes with a bunch of custom utility functions to make the life of developers easier.","content\u002Fdocs\u002Futility.md",{"title":79,"path":80,"description":81,"id":82},"Animation Expressions","\u002Fguides\u002Fanimation-expressions","Expressions in animations can be used to create dynamic animations based on math expressions, or to create systems where variables can be used to modify the transformation or state of the model, such as facial expressions","content\u002Fguides\u002Fanimation-expressions.md",{"title":84,"path":85,"description":86,"id":87},"Bedrock Modeling and Animation","\u002Fguides\u002Fbedrock-modeling","Learn how to create entity models and animations for Minecraft Bedrock Edition","content\u002Fguides\u002Fbedrock-modeling.md",{"title":89,"path":90,"description":91,"id":92},"Blockbench Overview & Tips","\u002Fguides\u002Fblockbench-overview-tips","The fundamentals of Blockbench and how to use it efficiently","content\u002Fguides\u002Fblockbench-overview-tips.md",{"title":94,"path":95,"description":96,"id":97},"Emissive Textures in Renders","\u002Fguides\u002Femissive-textures-renders","How to create elegant emissive textures in renders","content\u002Fguides\u002Femissive-textures-renders.md",{"title":99,"path":100,"description":101,"id":102},"3D Export","\u002Fguides\u002Fexport-formats","An overview of the different export formats and how to transfer your model into other programs","content\u002Fguides\u002Fexport-formats.md",{"title":104,"path":105,"description":106,"id":107},"Particles and Sounds in MC Bedrock","\u002Fguides\u002Fminecraft-particles-sounds","How to add particles and sounds effects to animations for Minecraft Bedrock Edition","content\u002Fguides\u002Fminecraft-particles-sounds.md",{"title":109,"path":110,"description":111,"id":112},"Minecraft Style Guide","\u002Fguides\u002Fminecraft-style-guide","Tips for creating art in the Minecraft style","content\u002Fguides\u002Fminecraft-style-guide.md",{"title":114,"path":115,"description":116,"id":117},"Rendering Models","\u002Fguides\u002Fmodel-rendering","Learn how to create renders of your Blockbench models","content\u002Fguides\u002Fmodel-rendering.md",{"id":82,"title":79,"body":119,"description":81,"extension":1319,"meta":1320,"navigation":1323,"path":80,"seo":1324,"stem":1325,"__hash__":1326},{"type":120,"value":121,"toc":1280},"minimark",[122,126,131,135,138,143,159,162,167,217,221,252,256,275,279,294,298,301,322,326,329,413,416,426,429,433,442,445,454,458,461,465,468,471,474,481,485,493,496,499,514,524,531,538,542,553,556,560,567,570,604,607,611,614,638,644,647,653,664,676,682,685,711,717,720,734,738,742,745,748,780,792,795,801,805,808,811,843,847,850,858,865,869,879,889,895,899,905,921,928,934,941,952,958,961,965,968,971,974,995,998,1002,1005,1008,1011,1017,1045,1048,1081,1084,1127,1130,1134,1137,1140,1157,1160,1164,1167,1203,1206,1210,1213,1276],[123,124,79],"h1",{"id":125},"animation-expressions",[127,128,130],"h2",{"id":129},"overview","Overview",[132,133,134],"p",{},"Blockbench supports math expressions in several places in the animation workflow.\nExpressions can be used for various tasks, from driving values with math expressions to create animations along sine curves, over dynamically reacting values, to modifying the state and transformation of a model via variables.",[132,136,137],{},"Expressions use a C-like syntax that is based on the Molang language that is used for animations in Minecraft.\nThis means that the same expressions can be used both for animations inside Blockbench for various purposes, for general 3D exports, and for exporting to Minecraft Bedrock Edition.",[139,140,142],"h3",{"id":141},"syntax-summary","Syntax summary",[144,145,146,150,153,156],"ul",{},[147,148,149],"li",{},"Expressions support a C-like syntax. Any expression returns a numeric value.",[147,151,152],{},"Some syntax requires boolean values, in such cases a value of 0 will be considered false, any other value will be considered true.",[147,154,155],{},"All trigonometry functions use degrees to describe angles.",[147,157,158],{},"Expressions are not case sensitive, line breaks and most white spaces are ignored.",[132,160,161],{},"Here is the most important syntax in a few short examples:",[163,164,166],"h4",{"id":165},"add-multiply-subtract-divide","Add, multiply, subtract, divide",[168,169,173],"pre",{"className":170,"code":171,"language":172,"meta":62,"style":62},"language-js shiki shiki-themes github-light github-dark","5 * 7 + 49 \u002F (4+3)\n","js",[174,175,176],"code",{"__ignoreMap":62},[177,178,181,185,189,192,195,198,201,205,208,211,214],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"sj4cs","5",[177,186,188],{"class":187},"szBVR"," *",[177,190,191],{"class":183}," 7",[177,193,194],{"class":187}," +",[177,196,197],{"class":183}," 49",[177,199,200],{"class":187}," \u002F",[177,202,204],{"class":203},"sVt8B"," (",[177,206,207],{"class":183},"4",[177,209,210],{"class":187},"+",[177,212,213],{"class":183},"3",[177,215,216],{"class":203},")\n",[163,218,220],{"id":219},"math-expressions","Math expressions",[168,222,224],{"className":170,"code":223,"language":172,"meta":62,"style":62},"Math.sin( time * 400 ) * 12\n",[174,225,226],{"__ignoreMap":62},[177,227,228,231,235,238,241,244,247,249],{"class":179,"line":180},[177,229,230],{"class":203},"Math.",[177,232,234],{"class":233},"sScJk","sin",[177,236,237],{"class":203},"( time ",[177,239,240],{"class":187},"*",[177,242,243],{"class":183}," 400",[177,245,246],{"class":203}," ) ",[177,248,240],{"class":187},[177,250,251],{"class":183}," 12\n",[163,253,255],{"id":254},"assigning-variables","Assigning variables",[168,257,259],{"className":170,"code":258,"language":172,"meta":62,"style":62},"v.my_value = 20;\n",[174,260,261],{"__ignoreMap":62},[177,262,263,266,269,272],{"class":179,"line":180},[177,264,265],{"class":203},"v.my_value ",[177,267,268],{"class":187},"=",[177,270,271],{"class":183}," 20",[177,273,274],{"class":203},";\n",[163,276,278],{"id":277},"using-variables","Using variables",[168,280,282],{"className":170,"code":281,"language":172,"meta":62,"style":62},"20 * v.my_value\n",[174,283,284],{"__ignoreMap":62},[177,285,286,289,291],{"class":179,"line":180},[177,287,288],{"class":183},"20",[177,290,188],{"class":187},[177,292,293],{"class":203}," v.my_value\n",[163,295,297],{"id":296},"ternary-operators","Ternary operators",[132,299,300],{},"Ternary operators consist of a pattern of three values, divided by a question mark and a colon.\nThe first value is evaluated first. If it is true or has a value, the second value is returned. Otherwise, the third value is returned.",[168,302,304],{"className":170,"code":303,"language":172,"meta":62,"style":62},"v.is_enabled ? 20 : 10\n",[174,305,306],{"__ignoreMap":62},[177,307,308,311,314,316,319],{"class":179,"line":180},[177,309,310],{"class":203},"v.is_enabled ",[177,312,313],{"class":187},"?",[177,315,271],{"class":183},[177,317,318],{"class":187}," :",[177,320,321],{"class":183}," 10\n",[163,323,325],{"id":324},"common-variables","Common variables",[132,327,328],{},"These variables are commonly used when working with expressions in animations.",[330,331,332,348],"table",{},[333,334,335],"thead",{},[336,337,338,342,345],"tr",{},[339,340,341],"th",{},"Variable",[339,343,344],{},"Description",[339,346,347],{},"Supported in Minecraft Bedrock",[349,350,351,365,377,389,401],"tbody",{},[336,352,353,359,362],{},[354,355,356],"td",{},[174,357,358],{},"time",[354,360,361],{},"Returns the current time within the animation in seconds",[354,363,364],{},"No",[336,366,367,372,374],{},[354,368,369],{},[174,370,371],{},"q.anim_time",[354,373,361],{},[354,375,376],{},"Yes",[336,378,379,384,387],{},[354,380,381],{},[174,382,383],{},"q.delta_time",[354,385,386],{},"Returns the delta time since the last rendered frame",[354,388,376],{},[336,390,391,396,399],{},[354,392,393],{},[174,394,395],{},"Math.PI",[354,397,398],{},"The value of the number Pi",[354,400,376],{},[336,402,403,408,411],{},[354,404,405],{},[174,406,407],{},"q.distance_from_camera",[354,409,410],{},"The distance between the camera and the center of the scene",[354,412,376],{},[132,414,415],{},"Blockbench will provide autocomplete options for most syntax.",[132,417,418,419],{},"A full overview of the syntax of Molang can be found here: ",[420,421,425],"a",{"href":422,"rel":423},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fminecraft\u002Fcreator\u002Fdocuments\u002Fmolang\u002Fsyntax-guide",[424],"nofollow","Molang Syntax Guide",[132,427,428],{},"Additional Blockbench-only features and syntax will be explained in this article.",[139,430,432],{"id":431},"exporting-expressions","Exporting expressions",[132,434,435,436,441],{},"Common ",[420,437,440],{"href":438,"rel":439},"https:\u002F\u002Fwww.blockbench.net\u002Fwiki\u002Fguides\u002Fexport-formats",[424],"3D export formats"," such as glTF and FBX do not support expressions in animations, they are limited to keyframes.\nDue to this, expressions will be baked down into keyframes when exporting to such formats. This limits expressions to things like sine curve driven animations and similar approaches. Use-cases such as variable-driven model state are not possible with these formats.",[132,443,444],{},"Advanced animation expressions can best be used when previewing animations directly in Blockbench or recording them into GIFs or videos.",[132,446,447,448,453],{},"Additionally, export to Minecraft Bedrock Edition (and Java Edition via ",[420,449,452],{"href":450,"rel":451},"https:\u002F\u002Fgithub.com\u002Fbernie-g\u002Fgeckolib",[424],"Geckolib",") fully supports expressions.",[127,455,457],{"id":456},"how-to-use-expressions","How to use expressions",[132,459,460],{},"Expressions can be used in various places within an animation. If a field for numeric values allows you to type in non-numeric expressions, that is usually a sign that expressions are supported.\nExpression input fields will highlight syntax in different colors and provide autocomplete.",[139,462,464],{"id":463},"keyframes","Keyframes",[132,466,467],{},"Keyframe values can be either numeric values or expressions. If only one keyframe exist, the entire channel will be animated based on the expressions of the keyframe.\nOtherwise, expressions will be evaluated at the current time in the timeline and then interpolated between just like linear numeric keyframes.",[132,469,470],{},"Keyframe expressions generally don't work in keyframes with smooth or bézier interpolation.",[132,472,473],{},"To enter an expression into a keyframe, create or select a keyframe. Then write your expression into the input of the respective axis in your keyframe field.",[132,475,476],{},[477,478],"img",{"alt":479,"src":480},"Keyframe expressions","\u002Fimages\u002Fwiki\u002Fguides\u002Fanimation-expressions\u002Fkeyframe-expression.png",[139,482,484],{"id":483},"anim-time-update","Anim Time Update",[132,486,487,488,492],{},"Right click an animation and click ",[489,490,491],"strong",{},"Properties..."," and you will see a dialog with animation properties. Some of these support expressions.",[132,494,495],{},"Anim Time Update is an expression that controls how fast the animation moves along. The expression is evaluated any time an animation frame is rendered.",[132,497,498],{},"By default, if the field is empty, the expression would look like this:",[168,500,502],{"className":170,"code":501,"language":172,"meta":62,"style":62},"query.anim_time + query.delta_time\n",[174,503,504],{"__ignoreMap":62},[177,505,506,509,511],{"class":179,"line":180},[177,507,508],{"class":203},"query.anim_time ",[177,510,210],{"class":187},[177,512,513],{"class":203}," query.delta_time\n",[132,515,516,519,520,523],{},[174,517,518],{},"query.anim_time"," refers to the current time in the animation. ",[174,521,522],{},"query.delta_time"," is the real time that has passed since the last frame was rendered. This expression ensures that the animation progresses each time it is rendered by exactly how much time has passed, ensuring consistent playback speed even if some frames take longer to render.",[132,525,526,527,530],{},"A simple way to modify this is to put in ",[174,528,529],{},"query.anim_time + query.delta_time * 2",". This doubles the delta time, resulting in an animation playing at twice the speed.",[132,532,533,534,537],{},"Or put in ",[174,535,536],{},"query.anim_time + query.delta_time * (1 + 0.6 * math.sin(query.anim_time * 500))"," to modulate the playback speed.",[139,539,541],{"id":540},"blend-weight","Blend Weight",[132,543,544,545,548,549,552],{},"In the same dialog, you can enter an expression for blend weight. Blend weight lets you multiply the amplitude of the entire animation by a factor. Entering ",[174,546,547],{},"0.5"," will make the animation play only half as much, entering ",[174,550,551],{},"2"," will double the effect.",[132,554,555],{},"As usual, complex expressions are supported to achieve certain effects.",[139,557,559],{"id":558},"placeholders","Placeholders",[132,561,562,563,566],{},"The ",[489,564,565],{},"Variable Placeholders"," panel allows you to run arbitrary expressions without those directly affecting the animation. This is particularly useful for defining values for variables, allowing you to preview the model in particular states.",[132,568,569],{},"You can simply define variables like this:",[168,571,573],{"className":170,"code":572,"language":172,"meta":62,"style":62},"variable.foo = 25;\nv.bar = 5 + 5;\n",[174,574,575,587],{"__ignoreMap":62},[177,576,577,580,582,585],{"class":179,"line":180},[177,578,579],{"class":203},"variable.foo ",[177,581,268],{"class":187},[177,583,584],{"class":183}," 25",[177,586,274],{"class":203},[177,588,590,593,595,598,600,602],{"class":179,"line":589},2,[177,591,592],{"class":203},"v.bar ",[177,594,268],{"class":187},[177,596,597],{"class":183}," 5",[177,599,194],{"class":187},[177,601,597],{"class":183},[177,603,274],{"class":203},[132,605,606],{},"Additionally, you can use UI inputs, as explained in the following section.",[139,608,610],{"id":609},"placeholder-ui-inputs","Placeholder UI Inputs",[132,612,613],{},"You can use special syntax to add UI inputs that provide an easier way to change values:",[168,615,617],{"className":170,"code":616,"language":172,"meta":62,"style":62},"v.enabled = toggle('Enabled')\n",[174,618,619],{"__ignoreMap":62},[177,620,621,624,626,629,632,636],{"class":179,"line":180},[177,622,623],{"class":203},"v.enabled ",[177,625,268],{"class":187},[177,627,628],{"class":233}," toggle",[177,630,631],{"class":203},"(",[177,633,635],{"class":634},"sZZnC","'Enabled'",[177,637,216],{"class":203},[132,639,640],{},[477,641],{"alt":642,"src":643},"Defining UI Inputs","\u002Fimages\u002Fwiki\u002Fguides\u002Fanimation-expressions\u002Fvariable-ui-inputs.png",[132,645,646],{},"The following types of inputs are available:",[163,648,650],{"id":649},"togglename",[174,651,652],{},"toggle(name)",[132,654,655,656,659,660,663],{},"Adds a checkbox. Returns ",[174,657,658],{},"1"," when enabled and ",[174,661,662],{},"0"," when disabled",[144,665,666],{},[147,667,668,671,672,675],{},[489,669,670],{},"Name:"," Display name of the element, should be written in single quotes (",[174,673,674],{},"'",")",[163,677,679],{"id":678},"slidername-step-min-max",[174,680,681],{},"slider(name, step, min, max)",[132,683,684],{},"Adds a numeric slider input that users can slide or enter a number into.",[144,686,687,693,699,705],{},[147,688,689,671,691,675],{},[489,690,670],{},[174,692,674],{},[147,694,695,698],{},[489,696,697],{},"Step:"," Set a value by which the value is incremented when using the slider. Optional and defaults to 1.",[147,700,701,704],{},[489,702,703],{},"Min:"," Set a minimum value. Optional.",[147,706,707,710],{},[489,708,709],{},"Max:"," Set a maximum value. Optional.",[163,712,714],{"id":713},"impulsename-duration",[174,715,716],{},"impulse(name, duration)",[132,718,719],{},"Adds a button. When pressed, this will return 1 for a short while, then return 0 again.",[144,721,722,728],{},[147,723,724,671,726,675],{},[489,725,670],{},[174,727,674],{},[147,729,730,733],{},[489,731,732],{},"Duration:"," Set how long the impulse will last in seconds. Optional and defaults to 0.1.",[127,735,737],{"id":736},"use-cases","Use cases",[139,739,741],{"id":740},"animating-with-sine-curves","Animating with Sine Curves",[132,743,744],{},"There are a lot of use-cases for sine curves when creating animations. Sine curves can create a smooth back and forth movement.\nDepending on the frequency and amplitude, this can be used for anything from breathing, over walk cycle animations, to high frequency movement like vibration or shivering.",[132,746,747],{},"A basic sine curve looks like this:",[168,749,751],{"className":170,"code":750,"language":172,"meta":62,"style":62},"20 + Math.sin(q.anim_time * 180) * 5\n",[174,752,753],{"__ignoreMap":62},[177,754,755,757,759,762,764,767,769,772,775,777],{"class":179,"line":180},[177,756,288],{"class":183},[177,758,194],{"class":187},[177,760,761],{"class":203}," Math.",[177,763,234],{"class":233},[177,765,766],{"class":203},"(q.anim_time ",[177,768,240],{"class":187},[177,770,771],{"class":183}," 180",[177,773,774],{"class":203},") ",[177,776,240],{"class":187},[177,778,779],{"class":183}," 5\n",[132,781,782,784,785,788,789,791],{},[174,783,288],{}," is the base value here, before adding the curve. ",[174,786,787],{},"180"," is the frequency of the curve, in this case the curve will complete 180 degrees or half a cycle per second. ",[174,790,184],{}," is the magnitude of the curve.\nWith this expression, the value will smoothly swing between 15 and 25 every two seconds.",[132,793,794],{},"In addition to the Blockbench preview, you can use the Graph Editor to preview sine curves. The Graph Editor can be opened by clicking the Toggle Graph Editor button in the top left corner of the timeline.",[132,796,797],{},[477,798],{"alt":799,"src":800},"Sine Curve in the Graph Editor","\u002Fimages\u002Fwiki\u002Fguides\u002Fanimation-expressions\u002Fsine-graph.png",[139,802,804],{"id":803},"baking","Baking",[132,806,807],{},"Besides letting the exporter take care of baking, you can also bake an expression into static keyframes while working on the animation in Blockbench. Baking, in this case, just means converting the one math expression into lots of individual keyframes with static numbers that represent the curve.",[132,809,810],{},"To bake a set of keyframes, follow these steps:",[812,813,814,823,826,829,832],"ol",{},[147,815,816,817,822],{},"Install the ",[420,818,821],{"href":819,"rel":820},"https:\u002F\u002Fwww.blockbench.net\u002Fplugins\u002Fbakery",[424],"Bakery"," plugin",[147,824,825],{},"Ensure the sections you want to bake have a start and end keyframe. For simple curves, simply copy the start keyframe and paste it at the end.",[147,827,828],{},"Select all keyframes that you want to bake.",[147,830,831],{},"In the Menu bar, click Animation > Bake Animations",[147,833,834,835],{},"Adjust the parameters\n",[144,836,837,840],{},[147,838,839],{},"Rate: Set the interval of generated keyframes. At 1, every snapping interval will get a keyframe, but you can increase the value to lower the amount of keyframes generated, lowering both the accuracy of the curve, but also the amount of data being generated.",[147,841,842],{},"Spherical Interpolation: Enables quaternion interpolation between rotation keyframes, ensuring rotation lerping takes the shortest path. This is not generally supported in combination with expressions.",[139,844,846],{"id":845},"face-rig","Face Rig",[132,848,849],{},"You can use expressions and variables to set up complex rigs and switch parts based on variables. A good example for that is a face rig, where you can have multiple mouth shapes, different variants for your eyes, and switch between then to create unique expressions.",[132,851,852,853],{},"Here is a video tutorial explaining this method: ",[420,854,857],{"href":855,"rel":856},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=MmMJuuX5Ago",[424],"Rigging Faces in Blockbench (using Variables) - YouTube",[132,859,860,861,864],{},"Note about the video: No keyframe is needed on the ",[174,862,863],{},"mouth"," parent group.",[163,866,868],{"id":867},"model-setup","Model Setup",[132,870,871,872,874,875,878],{},"First, choose a part of your face that you want to animate. Let's take the mouth. Create a new group called ",[174,873,863],{}," for everything related to the mouth. Inside it, create a group called ",[174,876,877],{},"mouth_1",", and inside that, add a cube or mesh which contains your first mouth shape. In the most simple example, this could be an empty plane that you draw a mouth on. But you can also do something more complex and use multiple elements.",[132,880,881,882,884,885,888],{},"Now, duplicate ",[174,883,877],{}," to create ",[174,886,887],{},"mouth_2",", which should be a different mouth shape. Create as many mouth shapes as you need.",[132,890,891],{},[477,892],{"alt":893,"src":894},"Outliner with face rig","\u002Fimages\u002Fwiki\u002Fguides\u002Fanimation-expressions\u002Fface-outliner.png",[163,896,898],{"id":897},"animation-setup","Animation Setup",[132,900,901,902,904],{},"Now, switch to Animate mode and create an animation. Create a scale keyframe on the ",[174,903,877],{}," bone with the following expression:",[168,906,908],{"className":170,"code":907,"language":172,"meta":62,"style":62},"v.mouth_shape == 1\n",[174,909,910],{"__ignoreMap":62},[177,911,912,915,918],{"class":179,"line":180},[177,913,914],{"class":203},"v.mouth_shape ",[177,916,917],{"class":187},"==",[177,919,920],{"class":183}," 1\n",[132,922,923,924,927],{},"This will compare the variable ",[174,925,926],{},"mouth_shape"," to the number 1. If the variable is in deed 1, it will return 1, which leaves the bone at the original scale. Otherwise, it will return 0, which will scale down the bone and effectively hide it.",[132,929,930,931,933],{},"Repeat this step for all other mouth variants, so that ",[174,932,887],{}," is only displayed when the variable is 2, etc.",[132,935,936,937,940],{},"You can now add a slider to control the mouth manually. Refer to the ",[420,938,559],{"href":939},"#placeholders"," section for more details. In this case, we will add a slider called \"Mouth\" that will let us control the value of the variable in steps of 1, and in a range between 1 and 3:",[168,942,946],{"className":943,"code":944,"language":945,"meta":62,"style":62},"language-javascript shiki shiki-themes github-light github-dark","v.mouth_shape = slider('Mouth', 1, 1, 3)\n","javascript",[174,947,948],{"__ignoreMap":62},[177,949,950],{"class":179,"line":180},[177,951,944],{},[132,953,954],{},[477,955],{"alt":956,"src":957},"Face rig setup, including scale keyframes and a variable placeholder slider","\u002Fimages\u002Fwiki\u002Fguides\u002Fanimation-expressions\u002Fface-rig-expressions.png",[132,959,960],{},"You can repeat the previous steps for as many details in your rig as you like, including eyes, eye brows, nose, etc.",[163,962,964],{"id":963},"use-the-rig-in-animations","Use the rig in animations",[132,966,967],{},"The final step is to keyframe the value of the variable. You can either do this in the same animation, or create a new animation for this, and keep both playing.",[132,969,970],{},"Click the \"Animate Effects\" button at the top of the timeline to open the effects animator, then create a keyframe under \"Instructions\". Instructions keyframes allow us to run expressions at certain times in the animation.",[132,972,973],{},"In the keyframe panel, set the Script field to a script that changes the variables. You can also use multiple lines, separated by a semicolon, to set multiple variables at once:",[168,975,977],{"className":943,"code":976,"language":945,"meta":62,"style":62},"v.mouth_shape = 2;\nv.eye_right_shape = 1;\nv.eye_left_shape = 8;\n",[174,978,979,984,989],{"__ignoreMap":62},[177,980,981],{"class":179,"line":180},[177,982,983],{},"v.mouth_shape = 2;\n",[177,985,986],{"class":179,"line":589},[177,987,988],{},"v.eye_right_shape = 1;\n",[177,990,992],{"class":179,"line":991},3,[177,993,994],{},"v.eye_left_shape = 8;\n",[132,996,997],{},"You can now create multiple of these instruction keyframes at different times during your animation. That way you can animate dynamic facial expressions that change during the animation, for example to let your character blink, talk, or display emotions.",[139,999,1001],{"id":1000},"speed-ramping","Speed Ramping",[132,1003,1004],{},"As mentioned above, animation playback speed can be modified in real time via expressions. This can be used to create speed ramping effects.",[132,1006,1007],{},"Please note that this does not carry over to traditional export formats such as glTF, even with baking.",[132,1009,1010],{},"In this example, let's assume we have a 4 second long timeline. Between the 1 second and 1.3 second mark, the action happens, and we want to slow down the animation and play this part in slow-motion.",[132,1012,1013,1014,1016],{},"First, let's write an expression that can detect that time range. We will use ",[174,1015,371],{},", which is an expression that returns the current timeline time.",[168,1018,1020],{"className":170,"code":1019,"language":172,"meta":62,"style":62},"q.anim_time > 1 && q.anim_time \u003C 1.3\n",[174,1021,1022],{"__ignoreMap":62},[177,1023,1024,1027,1030,1033,1036,1039,1042],{"class":179,"line":180},[177,1025,1026],{"class":203},"q.anim_time ",[177,1028,1029],{"class":187},">",[177,1031,1032],{"class":183}," 1",[177,1034,1035],{"class":187}," &&",[177,1037,1038],{"class":203}," q.anim_time ",[177,1040,1041],{"class":187},"\u003C",[177,1043,1044],{"class":183}," 1.3\n",[132,1046,1047],{},"Now, we want to return the value 0.2 during that time range to slow down the animation to 20% speed. The rest of the time, we will return 1 which represents normal speed.",[168,1049,1051],{"className":170,"code":1050,"language":172,"meta":62,"style":62},"(q.anim_time > 1 && q.anim_time \u003C 1.3) ? 0.2 : 1\n",[174,1052,1053],{"__ignoreMap":62},[177,1054,1055,1057,1059,1061,1063,1065,1067,1070,1072,1074,1077,1079],{"class":179,"line":180},[177,1056,766],{"class":203},[177,1058,1029],{"class":187},[177,1060,1032],{"class":183},[177,1062,1035],{"class":187},[177,1064,1038],{"class":203},[177,1066,1041],{"class":187},[177,1068,1069],{"class":183}," 1.3",[177,1071,774],{"class":203},[177,1073,313],{"class":187},[177,1075,1076],{"class":183}," 0.2",[177,1078,318],{"class":187},[177,1080,920],{"class":183},[132,1082,1083],{},"We'll plug this into the default anim time update variable as a speed factor. Keeping in mind to wrap the expression in parantheses to maintain the correct order of operations. We end up with this:",[168,1085,1087],{"className":170,"code":1086,"language":172,"meta":62,"style":62},"q.anim_time + q.delta_time * ((q.anim_time > 1 && q.anim_time \u003C 1.3) ? 0.2 : 1)\n",[174,1088,1089],{"__ignoreMap":62},[177,1090,1091,1093,1095,1098,1100,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125],{"class":179,"line":180},[177,1092,1026],{"class":203},[177,1094,210],{"class":187},[177,1096,1097],{"class":203}," q.delta_time ",[177,1099,240],{"class":187},[177,1101,1102],{"class":203}," ((q.anim_time ",[177,1104,1029],{"class":187},[177,1106,1032],{"class":183},[177,1108,1035],{"class":187},[177,1110,1038],{"class":203},[177,1112,1041],{"class":187},[177,1114,1069],{"class":183},[177,1116,774],{"class":203},[177,1118,313],{"class":187},[177,1120,1076],{"class":183},[177,1122,318],{"class":187},[177,1124,1032],{"class":183},[177,1126,216],{"class":203},[132,1128,1129],{},"When entering this expression into the Anim Time Update field in your animation's properties, you will get the desired speed ramping effect.",[127,1131,1133],{"id":1132},"expressions-in-numeric-inputs","Expressions in Numeric Inputs",[132,1135,1136],{},"Besides animations, expressions can also be used in almost any numeric input inside Blockbench, where it will resolve instantly upon confirming the input.",[132,1138,1139],{},"Examples where it can be used include:",[144,1141,1142,1145,1148,1151,1154],{},[147,1143,1144],{},"Element position and rotation number sliders",[147,1146,1147],{},"UV position sliders",[147,1149,1150],{},"Numeric inputs for setting texture or UV size",[147,1152,1153],{},"Numeric inputs in any dialogs and in settings",[147,1155,1156],{},"Sliders such as brush size",[132,1158,1159],{},"This can be used for some interesting use-cases, such as procedurally processing and modifying position values of elements.",[139,1161,1163],{"id":1162},"special-rules-for-number-sliders","Special rules for Number Sliders",[132,1165,1166],{},"Sliders often control many elements at once, therefore they use special rules to allow running the expression on each element individually:",[144,1168,1169,1190,1197],{},[147,1170,1171,1172,1174,1175,1177,1178,1181,1182,1185,1186,1189],{},"Beginning an expression with the sign ",[174,1173,210],{},", ",[174,1176,240],{},", or ",[174,1179,1180],{},"\u002F"," will add to, multiply, or divide the current value of each element individually. Since ",[174,1183,1184],{},"-"," is already reserved for entering negative values, you can instead use ",[174,1187,1188],{},"+-"," to subtract a value.",[147,1191,1192,1193,1196],{},"Using ",[174,1194,1195],{},"val"," in an expression will return the previous value of the field for each element",[147,1198,1192,1199,1202],{},[174,1200,1201],{},"n"," will return the index of the element in the list of all processed elements. The order may be arbitrary or depend on the order of selection.",[132,1204,1205],{},"When selecting multiple elements, the expression is evaluated per element. When in vertex selection mode, position inputs are evaluated per vertex. UV inputs are evaluated per face.",[139,1207,1209],{"id":1208},"use-cases-1","Use-cases",[132,1211,1212],{},"The practical use-cases are infinite, which is a number too big to include in an article. However, here are some examples:",[330,1214,1215,1224],{},[333,1216,1217],{},[336,1218,1219,1222],{},[339,1220,1221],{},"Expression",[339,1223,344],{},[349,1225,1226,1236,1246,1256,1266],{},[336,1227,1228,1233],{},[354,1229,1230],{},[174,1231,1232],{},"16*4",[354,1234,1235],{},"Returns 64",[336,1237,1238,1243],{},[354,1239,1240],{},[174,1241,1242],{},"*2",[354,1244,1245],{},"Double all values",[336,1247,1248,1253],{},[354,1249,1250],{},[174,1251,1252],{},"+-Math.PI",[354,1254,1255],{},"Subtract PI from all values",[336,1257,1258,1263],{},[354,1259,1260],{},[174,1261,1262],{},"Math.random(0, 8)",[354,1264,1265],{},"Randomize the position value of all selected elements to a value between 0 and 8",[336,1267,1268,1273],{},[354,1269,1270],{},[174,1271,1272],{},"val \u003C 0 ? 0 : val*2",[354,1274,1275],{},"Set all negative values to 0, double all positive values",[1277,1278,1279],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":62,"searchDepth":589,"depth":991,"links":1281},[1282,1294,1305,1315],{"id":129,"depth":589,"text":130,"children":1283},[1284,1293],{"id":141,"depth":991,"text":142,"children":1285},[1286,1288,1289,1290,1291,1292],{"id":165,"depth":1287,"text":166},4,{"id":219,"depth":1287,"text":220},{"id":254,"depth":1287,"text":255},{"id":277,"depth":1287,"text":278},{"id":296,"depth":1287,"text":297},{"id":324,"depth":1287,"text":325},{"id":431,"depth":991,"text":432},{"id":456,"depth":589,"text":457,"children":1295},[1296,1297,1298,1299,1300],{"id":463,"depth":991,"text":464},{"id":483,"depth":991,"text":484},{"id":540,"depth":991,"text":541},{"id":558,"depth":991,"text":559},{"id":609,"depth":991,"text":610,"children":1301},[1302,1303,1304],{"id":649,"depth":1287,"text":652},{"id":678,"depth":1287,"text":681},{"id":713,"depth":1287,"text":716},{"id":736,"depth":589,"text":737,"children":1306},[1307,1308,1309,1314],{"id":740,"depth":991,"text":741},{"id":803,"depth":991,"text":804},{"id":845,"depth":991,"text":846,"children":1310},[1311,1312,1313],{"id":867,"depth":1287,"text":868},{"id":897,"depth":1287,"text":898},{"id":963,"depth":1287,"text":964},{"id":1000,"depth":991,"text":1001},{"id":1132,"depth":589,"text":1133,"children":1316},[1317,1318],{"id":1162,"depth":991,"text":1163},{"id":1208,"depth":991,"text":1209},"md",{"authors":1321},[1322],"JannisX11",true,{"title":79,"description":81},"guides\u002Fanimation-expressions","0SGR8hmCNsW3NSbZxDuq_BKTAt0KYNwPB8OwUf-OOmg",1776013264586]