diff --git a/docs/README.md b/docs/README.md index 56359d8..f4aabb5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,7 +14,7 @@ Warudo is an avatar animation software specifically designed for 3D VTuber lives Warudo is a comprehensive, feature-packed 3D VTubing software designed for both casual and professional users. It offers support for [a wide variety of motion capture systems](mocap/overview.md), so you can both stream at home or at a professional mocap studio. It also offers a wide range of features, including posing your character with 500+ idle animations, integration with livestreaming platforms, a node-based visual scripting system, and many more. -Warudo is also extremely customizable. It provides a Mod SDK for importing any Unity-compatible 3D assets, and a C# scripting SDK for those inclined to develop custom features, making it versatile for both users and developers. +Warudo is also extremely customizable. It provkides a Mod SDK for importing any Unity-compatible 3D assets, and a C# scripting SDK for those inclined to develop custom features, making it versatile for both users and developers. Here are just a few cool examples from the Warudo community: diff --git a/docs/blueprints/tutorials/balloon.md b/docs/blueprints/tutorials/balloon.md index 4a8895d..7661ed1 100644 --- a/docs/blueprints/tutorials/balloon.md +++ b/docs/blueprints/tutorials/balloon.md @@ -79,7 +79,7 @@ Note that we have changed **Scale Vector3 → Vector3** to (1, 1, 1), and **Offs To see why this works, let's run through the calculations again. When we puff our cheeks, the maximum value would be (1, 1, 1) + (1, 1, 1) = (2, 2, 2), and the minimum value would be (0, 0, 0) + (1, 1, 1) = (1, 1, 1). That's exactly what we want! -## On Update +## On Update {#on-update} I hope you hated manually triggering the Get Character Bone Scale node as much as I did. Indeed, we can't be clicking in our blueprint every time we want to inflate our character's head. Only if there is a way to automatically trigger the node... Wait, there is? @@ -91,7 +91,7 @@ The **On Update** node is an event node that is triggered every frame when Warud Remember you can add nodes after the Get Character Bone Scale node to trigger more effects using your cheeks! Try to add a **Set Character BlendShape** node to activate a blendshape on your character when you puff your cheeks. Hint: Set Character BlendShape → Target Value is a decimal number between 0 and 1, so you can connect Get Character BlendShape → Value directly to it. ::: -## Resetting Bone Scale +## Resetting Bone Scale {#resetting-bone-scale} Now you can use this blueprint to inflate your character's head in your streams, but you probably don't want to enable this effect all the time. So, because you know event nodes in a disabled blueprint will not be triggered, you decide to only enable the blueprint when you want it and disable it afterwards. diff --git a/docs/blueprints/tutorials/dance.md b/docs/blueprints/tutorials/dance.md index 7f2bd63..b6ca59e 100644 --- a/docs/blueprints/tutorials/dance.md +++ b/docs/blueprints/tutorials/dance.md @@ -83,7 +83,7 @@ First, let's remove the connection between If Branch ↔ Play Character One Shot The Switch On Integer node works like this: when the node is triggered, it will check the value of the **Input Integer** data input, and trigger the corresponding flow output. For example, if Input Integer is 1, the flow output labeled 1 will be triggered; if Input Integer is 2, the flow output labeled 2 will be triggered; and so on. -Let's connect each flow output to a different outcome. For example, I have connected the flow output labeled 1 to the Play Character One Shot Overlay Animation node, 2 to a **Play Sound** node, and 3 to a **Spawn Particle** node: +Let's connect each flow output to a different outcome. For example, I have connected the flow output labeled 1 to the Play Character One Shot Overlay Animation node, 2 to a **Play Sounds** node, and 3 to a **Spawn Particle** node. Remember to set the **Source** option of both nodes: ![](/doc-img/en-blueprint-dance-8.png) @@ -91,7 +91,7 @@ Now let's test it! Manually set **Switch On Integer → Input Integer** to any n ![](/doc-img/en-blueprint-dance-9.png) -The last thing we need to do is to randomize the Input Integer. You already guessed it: there is a **Generate Random Integer** node! We set **Value Max** to 3, so that it outputs an integer between 1 and 3. +The last thing we need to do is to randomize the Input Integer. You may have already guessed it: there is a **Generate Random Integer** node! We set **Value Min** to 1 and **Value Max** to 3, so that it outputs an integer between 1 and 3. ![](/doc-img/en-blueprint-dance-10.png) diff --git a/docs/blueprints/tutorials/karaoke.md b/docs/blueprints/tutorials/karaoke.md index 2ac99ab..cc42cea 100644 --- a/docs/blueprints/tutorials/karaoke.md +++ b/docs/blueprints/tutorials/karaoke.md @@ -4,7 +4,7 @@ sidebar_position: 40 # Karaoke Time -Who doesn't love to karoake on stream? But now we are in the 3D world, let's add some realism by making our character hold a microphone. This tutorial will show you how to do just that: toggling a singing pose and a microphone prop with a hotkey. +Who doesn't love to karaoke on stream? But now we are in the 3D world, let's add some realism by making our character hold a microphone. This tutorial will show you how to do just that: toggling a singing pose and a microphone prop with a hotkey.
Singing my heart out!
diff --git a/docs/blueprints/tutorials/nap.md b/docs/blueprints/tutorials/nap.md index 4096db7..dfe05ba 100644 --- a/docs/blueprints/tutorials/nap.md +++ b/docs/blueprints/tutorials/nap.md @@ -4,6 +4,107 @@ sidebar_position: 100 # Taking a Nap -:::caution -This page is a work in progress. Information may be incomplete or inaccurate. +It is common to take a break during a stream. In Warudo, when your face is no longer tracked, your character will slowly transition back to an idle pose and expression. In this tutorial, we will make the character transition to a sleeping pose and expression instead, adding a bit of subtle realism to your character. + + +Sleeping on the job!
+ +:::info +This tutorial assumes you are using iFacialMocap or MediaPipe for face tracking. Other face tracking systems may not work because they do not provide a signal when your face is no longer tracked. ::: + +## The Face Tracking Blueprint + +Let's open our face tracking blueprint! Depending on the blueprint options you have selected during the onboarding process, your blueprint may look different from the one below, but the general idea is the same. Also, they look equally terrifying—there's so many nodes and connections! + +![](/doc-img/en-blueprint-nap-1.png) + +We will not go through every node in this blueprint, but let's break it down into a few parts. First you should see this node sequence at the left: + +![](/doc-img/en-blueprint-nap-2.png) + +This one is easy! You have already seen the On Disable Blueprint node in a [previous tutorial](balloon#resetting-bone-scale). It is triggered when the blueprint is disabled, and this face tracking blueprint is disabled when you turn off **Character → Motion Capture**. So, when you disable motion capture, the character's facial expression (blendshapes) is reset by the **Reset Character Tracking BlendShapes** node, and the character's bones (e.g., head, eyes) are reset by the **Reset Overridden Character Bones** node. + +Now let's take a look on the right side of the blueprint: + +![](/doc-img/en-blueprint-nap-3.png) + +You are already familiar with the [On Update node](balloon#on-update); it is triggered every frame Warudo is running. This node sequence is saying: for every frame, we want to update the character's blendshapes (**Set Character Tracking BlendShapes**), bones (**Override Character Bone Rotation Offsets**), and root position (**Override Character Root Position**). But what blendshapes? What bones? And what root position? These are the jobs of the nodes in the middle of the blueprint: + +![](/doc-img/en-blueprint-nap-16.png) + +## Switch BlendShape List + +Fortunately, for the purpose of this tutorial, we only need to look at a few nodes. Locate the **Get iFacialMocap Receiver Data** node (or, if you are using MediaPipe, the **Get MediaPipe Receiver Data** node); this is the "source" node that provides face tracking data. + +![](/doc-img/en-blueprint-nap-4.png) + +The node connections are currently too close to each other, so for clarity, let's move the Get iFacialMocap Receiver Data node towards the bottom left, like this: + +![](/doc-img/en-blueprint-nap-5.png) + +Zoom and pan the blueprint until you see the following 3 nodes: Get iFacialMocap Receiver Data, Empty BlendShape List, and Switch BlendShape List. Knowing nothing about the **Switch BlendShape List** node yet, just by inspecting the connections to it, can you guess what it does? + +![](/doc-img/en-blueprint-nap-6.png) + +Let's figure this out. First, we see **Get iFacialMocap Receiver Data → Is Tracked** is connected to **Switch BlendShape List → Condition**. This means the Switch BlendShape List node cares about whether the face is tracked or not. If the face is tracked, the Condition is Yes; otherwise, the Condition is No. + +Next, we see **Empty BlendShape List → Output** is connected to **Switch BlendShape List → If False**, and **Get iFacialMocap Receiver Data → BlendShapes** is connected to **Switch BlendShape List → If True**. Hmm, I think I am starting to get it! + +Indeed, the Switch BlendShape List node essentially checks if the face is tracked at the moment; if the face is tracked, it will pass the tracking blendshapes to the output, reflecting our facial expression on the character; otherwise, it will pass an empty blendshape list to the output, resulting the character not having any facial expression at all. + +What makes this node even more powerful is its ability to switch between two blendshape lists with _smooth transitions_: the **To True/False Transition Time**, **To True/False Transition Delay**, and **To True/False Transition Easing** options allow you to precisely control how the character's facial expression changes when the face becomes tracked or untracked. For example, if To False Transition Time is set to 0.5 seconds and To False Transition Delay is set to 1 second, then 1 second after your face is no longer tracked, the character's facial expression will smoothly transition to the empty blendshape list (i.e., a natural expression) in 0.5 seconds! + +Anyway, if we want to change the character's expression when our face is no longer tracked, we can just modify the input to Switch BlendShape List → If False, which is currently a mere empty blendshape list. We can add a **BlendShape List Set BlendShape** node in between to add a blendshape to the list: + +![](/doc-img/en-blueprint-nap-7.png) + +In the above example, I am creating a blendshape list with only one entry: `Blink` set to 1. This blendshape list will be passed to the output whenever face tracking is lost, resulting in the character closing their eyes. + +:::tip +If your character does not have a `Blink` blendshape, you can use the blinking blendshapes that come with your character, for example, `eyeBlinkLeft` and `eyeBlinkRight`. To set multiple blendshapes, simply add another BlendShape List Set BlendShape node in between. +::: + +Now try to put your hand in front of your iPhone's front camera to block face tracing (or if you are using MediaPipe, just move your face away from the camera), and you should see your character closing their eyes! + +![](/doc-img/en-blueprint-nap-13.png) + +The default settings will close the eyes quite fast, so you may want to adjust the **To False Transition Time** and **To False Transition Delay** options to make the transition more natural. I have set them to 2 and 1 seconds respectively: + +![](/doc-img/en-blueprint-nap-8.png) + +## Switch Rotation List + +:::info +Before reading this section, if you have enabled idle head animation during the onboarding process (which is by default enabled when not tracking), you need to disable it first. Locate the **Generate Idle Head Animation** node and set **Enabled** to No: + +![](/doc-img/en-blueprint-nap-12.png) +::: + + +To make the character transition to a sleeping pose, such as tilting their head to the side, the process is actually very similar to what we have just done. Let's once again move the Get iFacialMocap Receiver Data node towards the bottom: + +![](/doc-img/en-blueprint-nap-9.png) + +Until you can see the **Default Character Rotation List** and **Switch Rotation List** nodes on the right: + +![](/doc-img/en-blueprint-nap-10.png) +![](/doc-img/en-blueprint-nap-11.png) + +A 3D character's pose is defined by how much each bone is rotated, which is why instead of blendshapes, we are seeing "bone rotations" everywhere. The Switch Rotation List node here checks if the face is tracked, and passes the bone rotation data (i.e., head movement) to the output if the face is tracked, and passes the default rotation list (i.e., head does not move at all) to the output otherwise. + +To tilt the head to the side, we can simply add an **Offset Character Bone Rotation List** node in between to offset the head's rotation: + +![](/doc-img/en-blueprint-nap-15.png) + +I have added **Head** to the **Character Bones** list and set **Rotation Offset** to (15, 0, -20), which means the head will be rotated 15 degrees to the front and 20 degrees to the right. You are of course welcome to adjust the rotation to your liking, or even add more bones to the list to make the character's sleeping pose more complex! + +:::tip +Instead of manually entering the numbers, you can click and drag the X/Y/Z labels left and right to adjust the numbers. This trick works for any number input! +::: + +Now when your face is no longer tracked, your character will tilt their head to the side! + +![](/doc-img/en-blueprint-nap-14.png) + + diff --git a/docs/blueprints/tutorials/squashing.md b/docs/blueprints/tutorials/squashing.md index 3608329..b80b846 100644 --- a/docs/blueprints/tutorials/squashing.md +++ b/docs/blueprints/tutorials/squashing.md @@ -4,9 +4,126 @@ sidebar_position: 90 # Squashing the Head with Props -:::caution -This page is a work in progress. Information may be incomplete or inaccurate. +Since we are already [playing with bone scales](balloon), let's take it a step further in this tutorial and squash the character's head flat! + + +I guess you can say I am... flattened.
+ +## The First Attempt + +Let's start with what we are familiar with: the classic On Keystroke Pressed and Throw Prop At Character nodes. (You can of course replace On Keystroke Pressed with any event node you want, but we stick with it for simplicity.) Note that we have set **Throw Prop At Character → From** to **Above Character Head** and the distance to 5, so the prop will fall from above the character's head. + +![](/doc-img/en-blueprint-squashing-1.png) + +Just like what we did in the last tutorial, we can use the **Set Character Bone Scale** node to scale the head bone when the prop collides with the character, like this: + +![](/doc-img/en-blueprint-squashing-2.png) + +Now when we press C, the prop falls from above the character's head, and the character's head is squashed flat on collision. + +We will also add a separate **Set Character Bone Scale** node that helps the head bone return to its original scale: + +![](/doc-img/en-blueprint-squashing-8.png) + +We can click on the Enter flow input whenever we want to reset the head bone scale! (Or if you prefer, you can assign a hotkey to it.) This will be quite useful in below sections when you want to reset the head scale. + +## Multi Gate + +So far, we know how to squash the character's head flat and also resetting it. The problem is we want to have some progression, as in, the head should be squashed more and more flat as we press C more and more times. How do we do that? + +The **Multi Gate** node can help! Different from all the nodes we have seen before, the Multi Gate node has a variable number of flow outputs, meaning that you can have as many flow outputs you want. Set the **Exit Count** to 4 like below, and you will see 4 flow outputs from Exit 1 to Exit 4: + +![](/doc-img/en-blueprint-squashing-3.png) + +Each time the Multi Gate is triggered, it will trigger the **next flow output**. For example, if the Multi Gate is triggered for the first time, it will trigger Exit 1; if it is triggered for the second time, it will trigger Exit 2; and so on. When the Multi Gate is triggered for the fifth time, since there is no Exit 5, it will trigger Exit 1 again, and the cycle repeats. + +That's exactly what we need! We can reset the head bone scale to 1 when the Multi Gate is triggered for the first time, and squash a little bit when it is triggered for the second time, and squash a little bit more when it is triggered for the third time, and so on. Translated into a blueprint, it looks like this: + +![](/doc-img/en-blueprint-squashing-4.png) + +We start with the normal scale (1, 1, 1), then squashed a little bit (1.33, 0.83, 1.33), then (1.66, 0.67, 1.66), then (2, 0.5, 2). Note we scale up the X and Z axes but scale down the Y axis, so the head is squashed flat; you can also keep X and Z at 1 and only scale down Y, but I find it looks better when the head is squashed this way. + +Now go ahead and press C a few times, and you will see the head is squashed more and more flat, while resetting every 4 times! + +## Variables + +We can call it a day, but you know we always want to make things more interesting. What if we want to squash the head 10 times? Or 100 times? Creating 100 flow outputs and 100 Set Character Bone Scale nodes is not a good idea; there must be a better way. + +That's when a **variable** helps. A variable is a piece of data that can be changed and read by nodes. In the above blueprint, we created 4 Set Character Bone Scale nodes, but the settings on each node are essentially the same except the **Scale** option. This means instead of creating many nodes, we can just create one node, and tell that node to use a changing value (i.e., a variable) as the scale! + +Let's start by creating a variable. Go to the **Properties** tab in the node editor, and click the **+** button to create a variable. Set its name to **BumpedTimes** and type to **Integer** (an integer is a fancy way of saying "whole number", since we can't squash the head 1.5 times or 2.3 times): + +![](/doc-img/en-blueprint-squashing-5.png) + +We use the **Integer Variable Add** node right after the Throw Prop At Character node to increment the variable by 1 every time the prop collides with the character: + +![](/doc-img/en-blueprint-squashing-6.png) + +Go back to Warudo and press C a few times, and you will see the variable is incremented by 1 every time the prop collides with the character: + +![](/doc-img/en-blueprint-squashing-7.png) + +To read from this variable, we can use the **Get Integer Variable** node. Let's reset the **BumpedTimes** variable to 0 in the Properties tab, and add Set Character Bone Scale, Get Integer Variable, and Scale Vector3 nodes like below. Note **Scale Vector3 → Scale** is set to (1, 1, 1): + +![](/doc-img/en-blueprint-squashing-9.png) + +:::tip +Before reading on, can you guess what the blueprint does? +::: + +Now if you press C, the head bone should grow bigger and bigger every time the prop collides with the character! This makes sense, because what we are saying is: every time a prop hits, we increment BumpedTimes by 1, and then we set the head bone scale to (1, 1, 1) multiplied by BumpedTimes. So, the first time the prop hits, BumpedTimes is 1, and the head bone scale is (1, 1, 1) × 1 = (1, 1, 1); the second time the prop hits, BumpedTimes is 2, and the head bone scale is (1, 1, 1) × 2 = (2, 2, 2); and so on. + +But we want to squash the head, not grow it like a balloon! Go ahead and recreate the below blueprint: + +![](/doc-img/en-blueprint-squashing-10.png) + +Reset the BumpedTimes variable to 0 in the Properties tab, and press C a few times. You should see the head bone is squashed more and more flat! But how does that work? + +One personal trick I use when I read blueprints like this is to follow the flow of the data from right to left. In this case, we start with the **Vector3** literal node which would output our final scale to the Set Character Bone Scale node. Note the X and Z values are provided by the top **Float Addition** node, and the Y value is provided by the bottom Float Addition node. The top **Get Integer Variable → Float Multiplication → Float Addition** path is essentially calculating (BumpedTimes × 0.1 + 1), while the bottom path is calculating (BumpedTimes × -0.1 + 1). + +:::tip +We use the Float Multiplication/Addition nodes instead of Integer Multiplication/Addition because the end result is a decimal number (float), not a whole number (integer). +::: + +Let's manually calculate the final scale for different values of BumpedTimes: + +| BumpedTimes | X and Z | Y | Final Scale | +| ----------- | ------- | - | ----------- | +| 1 | 1 × 0.1 + 1 = 1.1 | 1 × -0.1 + 1 = 0.9 | (1.1, 0.9, 1.1) | +| 2 | 2 × 0.1 + 1 = 1.2 | 2 × -0.1 + 1 = 0.8 | (1.2, 0.8, 1.2) | +| 3 | 3 × 0.1 + 1 = 1.3 | 3 × -0.1 + 1 = 0.7 | (1.3, 0.7, 1.3) | +| 4 | 4 × 0.1 + 1 = 1.4 | 4 × -0.1 + 1 = 0.6 | (1.4, 0.6, 1.4) | + +I am sure you can see the pattern here: the X and Z values are increasing by 0.1 every time, while the Y value is decreasing by 0.1 every time. This is exactly what we want: the head bone is squashed more and more flat every time the prop hits! + +## Resetting a Variable + +However, if you press C a few more times, you will eventually see the head bone grow in the opposite direction, like this: + +![](/doc-img/en-blueprint-squashing-11.png) + +Why? Well, let's continue our calculations above: + +| BumpedTimes | X and Z | Y | Final Scale | +| ----------- | ------- | - | ----------- | +| 8 | 8 × 0.1 + 1 = 1.8 | 8 × -0.1 + 1 = 0.2 | (1.8, 0.2, 1.8) | +| 9 | 9 × 0.1 + 1 = 1.9 | 9 × -0.1 + 1 = 0.1 | (1.9, 0.1, 1.9) | +| 10 | 10 × 0.1 + 1 = 2 | 10 × -0.1 + 1 = 0 | (2, 0, 2) | +| 11 | 11 × 0.1 + 1 = 2.1 | 11 × -0.1 + 1 = -0.1 | (2.1, -0.1, 2.1) | +| 12 | 12 × 0.1 + 1 = 2.2 | 12 × -0.1 + 1 = -0.2 | (2.2, -0.2, 2.2) | + +The Y value is becoming negative, which means the head bone grows downward! This is not what we want. Let's reset the head bone scale to (1, 1, 1) when BumpedTimes is 10; that's the flattest we can get without the head growing downward. Fortunately, we already know how to do this: using the If Branch node we learned in the [dance](dance#if-branch) tutorial! + +![](/doc-img/en-blueprint-squashing-12.png) + +The newly added nodes are quite simple: we check if BumpedTimes is greater than or equal to 10, and if so, we reset it to 0, and reset the head bone scale back to 1. + +:::tip +We use the **Integer Greater Than Or Equal** node here, but you can also use the **Integer Equal** node to check if BumpedTimes is equal to 10. The difference is that the former will trigger the If True flow output when BumpedTimes is 10, 11, 12, etc., while the latter will only trigger the If True flow output when BumpedTimes is exactly 10. We usually use the former because it is more flexible (imagine somehow BumpedTimes becomes 11 by a mistake, then we will never be able to reset it back to 0). ::: -Since we are already [playing with bone scales](balloon), let's take it a step further in this tutorial and squash the character's head with props! +The final blueprint looks like this (quite a big one!): + +![](/doc-img/en-blueprint-squashing-13.png) +Congratulations! That's blueprint variables for you. This is a more challenging tutorial than the previous ones, so kudos to you for making it this far! diff --git a/docs/blueprints/tutorials/spinning.md b/docs/modding/particle-mod.md similarity index 53% rename from docs/blueprints/tutorials/spinning.md rename to docs/modding/particle-mod.md index 6d4fc35..4e59384 100644 --- a/docs/blueprints/tutorials/spinning.md +++ b/docs/modding/particle-mod.md @@ -1,11 +1,9 @@ --- -sidebar_position: 110 +sidebar_position: 40 --- -# Spinning and Turning +# Particle Mod :::caution This page is a work in progress. Information may be incomplete or inaccurate. ::: - -[//]: # (optional: use for loop to do this) diff --git a/static/doc-img/en-blueprint-nap-1.png b/static/doc-img/en-blueprint-nap-1.png new file mode 100644 index 0000000..4b4ac20 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-1.png differ diff --git a/static/doc-img/en-blueprint-nap-10.png b/static/doc-img/en-blueprint-nap-10.png new file mode 100644 index 0000000..70d8a80 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-10.png differ diff --git a/static/doc-img/en-blueprint-nap-11.png b/static/doc-img/en-blueprint-nap-11.png new file mode 100644 index 0000000..93e6b6a Binary files /dev/null and b/static/doc-img/en-blueprint-nap-11.png differ diff --git a/static/doc-img/en-blueprint-nap-12.png b/static/doc-img/en-blueprint-nap-12.png new file mode 100644 index 0000000..093785e Binary files /dev/null and b/static/doc-img/en-blueprint-nap-12.png differ diff --git a/static/doc-img/en-blueprint-nap-13.png b/static/doc-img/en-blueprint-nap-13.png new file mode 100644 index 0000000..06e31cf Binary files /dev/null and b/static/doc-img/en-blueprint-nap-13.png differ diff --git a/static/doc-img/en-blueprint-nap-14.png b/static/doc-img/en-blueprint-nap-14.png new file mode 100644 index 0000000..0c2d217 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-14.png differ diff --git a/static/doc-img/en-blueprint-nap-15.png b/static/doc-img/en-blueprint-nap-15.png new file mode 100644 index 0000000..4909771 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-15.png differ diff --git a/static/doc-img/en-blueprint-nap-16.png b/static/doc-img/en-blueprint-nap-16.png new file mode 100644 index 0000000..bb16c94 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-16.png differ diff --git a/static/doc-img/en-blueprint-nap-2.png b/static/doc-img/en-blueprint-nap-2.png new file mode 100644 index 0000000..4a8dcb9 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-2.png differ diff --git a/static/doc-img/en-blueprint-nap-3.png b/static/doc-img/en-blueprint-nap-3.png new file mode 100644 index 0000000..fa49acd Binary files /dev/null and b/static/doc-img/en-blueprint-nap-3.png differ diff --git a/static/doc-img/en-blueprint-nap-4.png b/static/doc-img/en-blueprint-nap-4.png new file mode 100644 index 0000000..59f6db4 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-4.png differ diff --git a/static/doc-img/en-blueprint-nap-5.png b/static/doc-img/en-blueprint-nap-5.png new file mode 100644 index 0000000..e6cd98e Binary files /dev/null and b/static/doc-img/en-blueprint-nap-5.png differ diff --git a/static/doc-img/en-blueprint-nap-6.png b/static/doc-img/en-blueprint-nap-6.png new file mode 100644 index 0000000..4138111 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-6.png differ diff --git a/static/doc-img/en-blueprint-nap-7.png b/static/doc-img/en-blueprint-nap-7.png new file mode 100644 index 0000000..2f70aff Binary files /dev/null and b/static/doc-img/en-blueprint-nap-7.png differ diff --git a/static/doc-img/en-blueprint-nap-8.png b/static/doc-img/en-blueprint-nap-8.png new file mode 100644 index 0000000..118ba90 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-8.png differ diff --git a/static/doc-img/en-blueprint-nap-9.png b/static/doc-img/en-blueprint-nap-9.png new file mode 100644 index 0000000..bc85230 Binary files /dev/null and b/static/doc-img/en-blueprint-nap-9.png differ diff --git a/static/doc-img/en-blueprint-squashing-1.png b/static/doc-img/en-blueprint-squashing-1.png new file mode 100644 index 0000000..a91cbc6 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-1.png differ diff --git a/static/doc-img/en-blueprint-squashing-10.png b/static/doc-img/en-blueprint-squashing-10.png new file mode 100644 index 0000000..82d650c Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-10.png differ diff --git a/static/doc-img/en-blueprint-squashing-11.png b/static/doc-img/en-blueprint-squashing-11.png new file mode 100644 index 0000000..46cddde Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-11.png differ diff --git a/static/doc-img/en-blueprint-squashing-12.png b/static/doc-img/en-blueprint-squashing-12.png new file mode 100644 index 0000000..6143214 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-12.png differ diff --git a/static/doc-img/en-blueprint-squashing-13.png b/static/doc-img/en-blueprint-squashing-13.png new file mode 100644 index 0000000..926a6ef Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-13.png differ diff --git a/static/doc-img/en-blueprint-squashing-2.png b/static/doc-img/en-blueprint-squashing-2.png new file mode 100644 index 0000000..aeff784 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-2.png differ diff --git a/static/doc-img/en-blueprint-squashing-3.png b/static/doc-img/en-blueprint-squashing-3.png new file mode 100644 index 0000000..7de8108 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-3.png differ diff --git a/static/doc-img/en-blueprint-squashing-4.png b/static/doc-img/en-blueprint-squashing-4.png new file mode 100644 index 0000000..b28fbf3 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-4.png differ diff --git a/static/doc-img/en-blueprint-squashing-5.png b/static/doc-img/en-blueprint-squashing-5.png new file mode 100644 index 0000000..5eed086 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-5.png differ diff --git a/static/doc-img/en-blueprint-squashing-6.png b/static/doc-img/en-blueprint-squashing-6.png new file mode 100644 index 0000000..e0d9d5c Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-6.png differ diff --git a/static/doc-img/en-blueprint-squashing-7.png b/static/doc-img/en-blueprint-squashing-7.png new file mode 100644 index 0000000..7b4eaf1 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-7.png differ diff --git a/static/doc-img/en-blueprint-squashing-8.png b/static/doc-img/en-blueprint-squashing-8.png new file mode 100644 index 0000000..eeb97eb Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-8.png differ diff --git a/static/doc-img/en-blueprint-squashing-9.png b/static/doc-img/en-blueprint-squashing-9.png new file mode 100644 index 0000000..50050f9 Binary files /dev/null and b/static/doc-img/en-blueprint-squashing-9.png differ diff --git a/static/doc-img/nap.mp4 b/static/doc-img/nap.mp4 new file mode 100644 index 0000000..1d826ad Binary files /dev/null and b/static/doc-img/nap.mp4 differ diff --git a/static/doc-img/squashing.mp4 b/static/doc-img/squashing.mp4 new file mode 100644 index 0000000..1755d2e Binary files /dev/null and b/static/doc-img/squashing.mp4 differ