Draw both arms on the supine motions and retire the hide list
Hollow Body Hold, Leg Raises, and Reverse Crunch hid the far arm because it was never authored - a leftover from the planar rig. Both arms are now posed, so the far arm reads as the standard light member behind the near one, the same visual language every other exercise uses, and the figures stay truthful from any viewpoint. With no remaining users, the hide mechanism is deleted from both renderers, the motion schema, and the docs. Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
||||||
<title>Hollow Body Hold</title>
|
<title>Hollow Body Hold</title>
|
||||||
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_l" d="M 105.9 148.1 L 75.9 148.1 L 45.9 148.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_l" d="M 190.9 148.8 L 236.9 148.8 L 276.9 148.8 L 276.9 137.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_l" d="M 190.9 148.8 L 236.9 148.8 L 276.9 148.8 L 276.9 137.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
||||||
<title>Hollow Body Hold</title>
|
<title>Hollow Body Hold</title>
|
||||||
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_l" d="M 108.7 129.5 L 81.5 117.0 L 54.3 104.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -2,7 +2,6 @@
|
|||||||
"name": "Hollow Body Hold",
|
"name": "Hollow Body Hold",
|
||||||
"primary": 2,
|
"primary": 2,
|
||||||
"working": ["spine"],
|
"working": ["spine"],
|
||||||
"hide": ["arm_l"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.4, "tween": 0.8,
|
"hold": 0.4, "tween": 0.8,
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
"shoulder_r": 180, "elbow_r": 0,
|
"shoulder_r": 180, "elbow_r": 0,
|
||||||
|
"shoulder_l": 180, "elbow_l": 0,
|
||||||
"hip_r": 0, "knee_r": 0,
|
"hip_r": 0, "knee_r": 0,
|
||||||
"hip_l": 0, "knee_l": 0
|
"hip_l": 0, "knee_l": 0
|
||||||
},
|
},
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"spine": [0, 14],
|
"spine": [0, 14],
|
||||||
"neck": 20,
|
"neck": 20,
|
||||||
"shoulder_r": 175, "elbow_r": 0,
|
"shoulder_r": 175, "elbow_r": 0,
|
||||||
|
"shoulder_l": 175, "elbow_l": 0,
|
||||||
"hip_r": 18, "knee_r": 0,
|
"hip_r": 18, "knee_r": 0,
|
||||||
"hip_l": 18, "knee_l": 0
|
"hip_l": 18, "knee_l": 0
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 124 KiB |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
|
||||||
<title>Hollow Body Hold</title>
|
<title>Hollow Body Hold</title>
|
||||||
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_l" d="M 108.7 129.5 L 81.5 117.0 L 54.3 104.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -6,6 +6,7 @@
|
|||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_l" d="M 190.9 148.8 L 213.9 109.5 L 233.9 75.4 L 224.4 70.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_l" d="M 190.9 148.8 L 213.9 109.5 L 233.9 75.4 L 224.4 70.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 100.0 149.9 L 130.0 150.9 L 160.0 152.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 185.0 149.2 L 208.0 110.0 L 228.0 75.9 L 218.5 70.5" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 185.0 149.2 L 208.0 110.0 L 228.0 75.9 L 218.5 70.5" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -7,6 +7,7 @@
|
|||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 185.0 149.2 L 230.6 142.9 L 270.2 137.4 L 268.6 126.7" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 185.0 149.2 L 230.6 142.9 L 270.2 137.4 L 268.6 126.7" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 100.0 149.9 L 130.0 150.9 L 160.0 152.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">
|
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -2,13 +2,13 @@
|
|||||||
"name": "Leg Raises",
|
"name": "Leg Raises",
|
||||||
"primary": 1,
|
"primary": 1,
|
||||||
"working": ["leg_r", "leg_l"],
|
"working": ["leg_r", "leg_l"],
|
||||||
"hide": ["arm_r"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.5, "tween": 1.4,
|
"hold": 0.5, "tween": 1.4,
|
||||||
"root": {"pos": [185, 148], "pitch": -90},
|
"root": {"pos": [185, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 60, "knee_r": 0,
|
"hip_r": 60, "knee_r": 0,
|
||||||
"hip_l": 60, "knee_l": 0
|
"hip_l": 60, "knee_l": 0
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"root": {"pos": [185, 148], "pitch": -90},
|
"root": {"pos": [185, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 8, "knee_r": 0,
|
"hip_r": 8, "knee_r": 0,
|
||||||
"hip_l": 8, "knee_l": 0
|
"hip_l": 8, "knee_l": 0
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 111 KiB |
@@ -6,6 +6,7 @@
|
|||||||
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 185.0 148.0 Q 141.5 148.0 100.0 148.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_l" d="M 190.9 148.8 L 213.9 109.5 L 233.9 75.4 L 224.4 70.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_l" d="M 190.9 148.8 L 213.9 109.5 L 233.9 75.4 L 224.4 70.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 100.0 149.9 L 130.0 150.9 L 160.0 152.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 185.0 149.2 L 208.0 110.0 L 228.0 75.9 L 218.5 70.5" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 185.0 149.2 L 208.0 110.0 L 228.0 75.9 L 218.5 70.5" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="80.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="80.4" y1="133.9" x2="80.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -6,6 +6,7 @@
|
|||||||
<path id="girdle" d="M 92.9 148.1 L 87.0 148.0 L 87.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 92.9 148.1 L 87.0 148.0 L 87.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 177.9 148.8 L 172.0 148.0 L 172.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 177.9 148.8 L 172.0 148.0 L 172.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 172.0 148.0 Q 128.5 148.0 87.0 148.0" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 172.0 148.0 Q 128.5 148.0 87.0 148.0" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 87.0 149.9 L 117.0 150.9 L 147.0 152.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 172.0 149.2 L 164.0 104.6 L 201.6 118.1 L 205.4 107.9" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 172.0 149.2 L 164.0 104.6 L 201.6 118.1 L 205.4 107.9" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="67.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="67.4" cy="143.9" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="67.4" y1="133.9" x2="67.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="67.4" y1="133.9" x2="67.4" y2="127.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -6,6 +6,7 @@
|
|||||||
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 171.9 136.8 L 166.0 136.0 L 166.0 137.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 171.9 136.8 L 166.0 136.0 L 166.0 137.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 166.0 136.0 Q 124.6 154.2 82.6 143.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 166.0 136.0 Q 124.6 154.2 82.6 143.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 82.6 145.3 L 112.6 146.3 L 142.6 147.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 166.0 137.2 L 146.6 96.2 L 186.0 103.0 L 187.9 92.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 166.0 137.2 L 146.6 96.2 L 186.0 103.0 L 187.9 92.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="62.6" cy="144.0" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="62.6" cy="144.0" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="62.6" y1="134.0" x2="62.6" y2="127.1" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="62.6" y1="134.0" x2="62.6" y2="127.1" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -2,13 +2,13 @@
|
|||||||
"name": "Reverse Crunch",
|
"name": "Reverse Crunch",
|
||||||
"primary": 2,
|
"primary": 2,
|
||||||
"working": ["spine"],
|
"working": ["spine"],
|
||||||
"hide": ["arm_r"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.5, "tween": 0.7,
|
"hold": 0.5, "tween": 0.7,
|
||||||
"root": {"pos": [172, 148], "pitch": -90},
|
"root": {"pos": [172, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 100, "knee_r": 120,
|
"hip_r": 100, "knee_r": 120,
|
||||||
"hip_l": 100, "knee_l": 120
|
"hip_l": 100, "knee_l": 120
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"root": {"pos": [166, 136], "pitch": -105},
|
"root": {"pos": [166, 136], "pitch": -105},
|
||||||
"spine": [0, 20],
|
"spine": [0, 20],
|
||||||
"neck": -7, "head": 2,
|
"neck": -7, "head": 2,
|
||||||
|
"shoulder_r": 3, "elbow_r": 0,
|
||||||
"shoulder_l": 3, "elbow_l": 0,
|
"shoulder_l": 3, "elbow_l": 0,
|
||||||
"hip_r": 100, "knee_r": 125,
|
"hip_r": 100, "knee_r": 125,
|
||||||
"hip_l": 100, "knee_l": 125
|
"hip_l": 100, "knee_l": 125
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 128 KiB |
@@ -6,6 +6,7 @@
|
|||||||
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="pelvisBar" d="M 171.9 136.8 L 166.0 136.0 L 166.0 137.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="pelvisBar" d="M 171.9 136.8 L 166.0 136.0 L 166.0 137.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="spine" d="M 166.0 136.0 Q 124.6 154.2 82.6 143.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="spine" d="M 166.0 136.0 Q 124.6 154.2 82.6 143.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="arm_r" d="M 82.6 145.3 L 112.6 146.3 L 142.6 147.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path id="leg_r" d="M 166.0 137.2 L 146.6 96.2 L 186.0 103.0 L 187.9 92.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
<path id="leg_r" d="M 166.0 137.2 L 146.6 96.2 L 186.0 103.0 L 187.9 92.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<circle id="head" cx="62.6" cy="144.0" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
<circle id="head" cx="62.6" cy="144.0" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
|
||||||
<line id="nose" x1="62.6" y1="134.0" x2="62.6" y2="127.1" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
<line id="nose" x1="62.6" y1="134.0" x2="62.6" y2="127.1" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -45,7 +45,6 @@ never touches a motion script** — proportions are the skeleton's problem.
|
|||||||
"primary": 2, // 1-based frame used for visual.svg
|
"primary": 2, // 1-based frame used for visual.svg
|
||||||
"camera": {"yaw": 0}, // 0 = side view (default), 90 = face-on
|
"camera": {"yaw": 0}, // 0 = side view (default), 90 = face-on
|
||||||
"working": ["arm_l", "leg_r"], // parts drawn in the accent color
|
"working": ["arm_l", "leg_r"], // parts drawn in the accent color
|
||||||
"hide": [], // limbs occluded by convention, not drawn
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.5, "tween": 0.8, // seconds held / animating to the next frame
|
"hold": 0.5, "tween": 0.8, // seconds held / animating to the next frame
|
||||||
@@ -115,8 +114,9 @@ never touches a motion script** — proportions are the skeleton's problem.
|
|||||||
shoulder girdle and pelvis drawn as bars across the attach points (near-full
|
shoulder girdle and pelvis drawn as bars across the attach points (near-full
|
||||||
width face-on, a shoulder/hip nub in profile); teal when the trunk is the
|
width face-on, a shoulder/hip nub in profile); teal when the trunk is the
|
||||||
working part.
|
working part.
|
||||||
- Canvas 320×180, ground line at y = 152. Limbs listed in `hide` are
|
- Canvas 320×180, ground line at y = 152. Every limb is always drawn — a
|
||||||
occluded by convention in this view and not drawn.
|
supine figure's far arm reads as the light far member, never a hidden one,
|
||||||
|
so any viewpoint (and the orbit) stays truthful.
|
||||||
|
|
||||||
## The props layer
|
## The props layer
|
||||||
|
|
||||||
@@ -172,8 +172,7 @@ authored yaw nothing moves, so the authored look is exact.
|
|||||||
and `pad` default to perpendicular to the lower bone (forearm/shin), or
|
and `pad` default to perpendicular to the lower bone (forearm/shin), or
|
||||||
take an explicit `angle`. Under orbit the segment rotates with the scene
|
take an explicit `angle`. Under orbit the segment rotates with the scene
|
||||||
and foreshortens naturally. `plateR` puts filled discs on both ends
|
and foreshortens naturally. `plateR` puts filled discs on both ends
|
||||||
(dumbbells default to 4.5). A prop whose limb is hidden that frame simply
|
(dumbbells default to 4.5).
|
||||||
isn't drawn.
|
|
||||||
- **`roller`** — a machine roller pad seen end-on: a filled disc riding the
|
- **`roller`** — a machine roller pad seen end-on: a filled disc riding the
|
||||||
limb's lower bone near the joint in `at`, on the `side` (+1/−1) of the bone
|
limb's lower bone near the joint in `at`, on the `side` (+1/−1) of the bone
|
||||||
it presses — a leg extension's instep roller (`side: 1`), a leg curl's
|
it presses — a leg extension's instep roller (`side: 1`), a leg curl's
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 302 KiB After Width: | Height: | Size: 303 KiB |
@@ -602,23 +602,18 @@ def prepare(motion, figure="neutral", flip=False, strict=False):
|
|||||||
def render_exercise(folder, figure="neutral", flip=False, strict=False):
|
def render_exercise(folder, figure="neutral", flip=False, strict=False):
|
||||||
motion = load_motion(folder)
|
motion = load_motion(folder)
|
||||||
working = set(motion.get("working", []))
|
working = set(motion.get("working", []))
|
||||||
hide = set(motion.get("hide", []))
|
|
||||||
norms, prof, cam, pitch, props = prepare(motion, figure, flip, strict)
|
norms, prof, cam, pitch, props = prepare(motion, figure, flip, strict)
|
||||||
|
|
||||||
mat = mat_bounds(norms, prof, cam, pitch)
|
mat = mat_bounds(norms, prof, cam, pitch)
|
||||||
|
|
||||||
def geometry(nf):
|
def geometry(nf):
|
||||||
_, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
|
_, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
|
||||||
for limb in hide:
|
|
||||||
geo.pop(limb, None)
|
|
||||||
return geo, order, shade
|
return geo, order, shade
|
||||||
|
|
||||||
resolved = []
|
resolved = []
|
||||||
key_cells = []
|
key_cells = []
|
||||||
for nf in norms:
|
for nf in norms:
|
||||||
out, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
|
out, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
|
||||||
for limb in hide:
|
|
||||||
geo.pop(limb, None)
|
|
||||||
resolved.append(out)
|
resolved.append(out)
|
||||||
key_cells.append((geo, order, shade, resolve_props(props, geo, nf["root"]["pos"])))
|
key_cells.append((geo, order, shade, resolve_props(props, geo, nf["root"]["pos"])))
|
||||||
|
|
||||||
@@ -653,7 +648,6 @@ def render_orbit(folder, figure="neutral"):
|
|||||||
motion authors one). Props rotate with the figure about the root anchor."""
|
motion authors one). Props rotate with the figure about the root anchor."""
|
||||||
motion = load_motion(folder)
|
motion = load_motion(folder)
|
||||||
working = set(motion.get("working", []))
|
working = set(motion.get("working", []))
|
||||||
hide = set(motion.get("hide", []))
|
|
||||||
norms, prof, cam, pitch, props = prepare(motion, figure)
|
norms, prof, cam, pitch, props = prepare(motion, figure)
|
||||||
resolved = [frame_geometry(nf, prof, cam, pitch=pitch)[0] for nf in norms]
|
resolved = [frame_geometry(nf, prof, cam, pitch=pitch)[0] for nf in norms]
|
||||||
mat = mat_bounds(norms, prof, cam, pitch)
|
mat = mat_bounds(norms, prof, cam, pitch)
|
||||||
@@ -671,8 +665,6 @@ def render_orbit(folder, figure="neutral"):
|
|||||||
posed, auth_geo, _, _ = frame_geometry(nf, prof, cam, pitch=pitch)
|
posed, auth_geo, _, _ = frame_geometry(nf, prof, cam, pitch=pitch)
|
||||||
posed["pins"] = {}
|
posed["pins"] = {}
|
||||||
_, geo, order, shade = frame_geometry(posed, prof, cam + off, pitch=pitch, mat=mat)
|
_, geo, order, shade = frame_geometry(posed, prof, cam + off, pitch=pitch, mat=mat)
|
||||||
for limb in hide:
|
|
||||||
geo.pop(limb, None)
|
|
||||||
prims = resolve_props(props, geo, nf["root"]["pos"],
|
prims = resolve_props(props, geo, nf["root"]["pos"],
|
||||||
prop_rotation(pitch, off), auth_geo)
|
prop_rotation(pitch, off), auth_geo)
|
||||||
imgs.append(draw_geo(geo, order, shade, working, colors, font=font, prims=prims))
|
imgs.append(draw_geo(geo, order, shade, working, colors, font=font, prims=prims))
|
||||||
@@ -686,13 +678,11 @@ def contact_sheet(folders, figure="neutral", out=None):
|
|||||||
cells = []
|
cells = []
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
motion = load_motion(folder)
|
motion = load_motion(folder)
|
||||||
working, hide = set(motion.get("working", [])), set(motion.get("hide", []))
|
working = set(motion.get("working", []))
|
||||||
norms, prof, cam, pitch, props = prepare(motion, figure)
|
norms, prof, cam, pitch, props = prepare(motion, figure)
|
||||||
mat = mat_bounds(norms, prof, cam, pitch)
|
mat = mat_bounds(norms, prof, cam, pitch)
|
||||||
for i, nf in enumerate(norms, start=1):
|
for i, nf in enumerate(norms, start=1):
|
||||||
_, geo, order, shade = frame_geometry(nf, prof, cam, pitch=pitch, mat=mat)
|
_, geo, order, shade = frame_geometry(nf, prof, cam, pitch=pitch, mat=mat)
|
||||||
for limb in hide:
|
|
||||||
geo.pop(limb, None)
|
|
||||||
prims = resolve_props(props, geo, nf["root"]["pos"])
|
prims = resolve_props(props, geo, nf["root"]["pos"])
|
||||||
cells.append((f"{motion['name']} {i}/{len(norms)}",
|
cells.append((f"{motion['name']} {i}/{len(norms)}",
|
||||||
draw_geo(geo, order, shade, working, PALETTES["default"],
|
draw_geo(geo, order, shade, working, PALETTES["default"],
|
||||||
@@ -705,7 +695,7 @@ def demo_sheet(folder):
|
|||||||
opens: neutral / female / male profiles (same motion script, different
|
opens: neutral / female / male profiles (same motion script, different
|
||||||
proportions), the flipped camera, an alternate theme."""
|
proportions), the flipped camera, an alternate theme."""
|
||||||
motion = load_motion(folder)
|
motion = load_motion(folder)
|
||||||
working, hide = set(motion.get("working", [])), set(motion.get("hide", []))
|
working = set(motion.get("working", []))
|
||||||
idx = motion.get("primary", 1) - 1
|
idx = motion.get("primary", 1) - 1
|
||||||
font = legend_font()
|
font = legend_font()
|
||||||
variants = [("neutral", "neutral", False, "default"),
|
variants = [("neutral", "neutral", False, "default"),
|
||||||
@@ -718,8 +708,6 @@ def demo_sheet(folder):
|
|||||||
norms, prof, cam, pitch, props = prepare(motion, figure, flip)
|
norms, prof, cam, pitch, props = prepare(motion, figure, flip)
|
||||||
mat = mat_bounds(norms, prof, cam, pitch)
|
mat = mat_bounds(norms, prof, cam, pitch)
|
||||||
_, geo, order, shade = frame_geometry(norms[idx], prof, cam, flip, pitch, mat)
|
_, geo, order, shade = frame_geometry(norms[idx], prof, cam, flip, pitch, mat)
|
||||||
for limb in hide:
|
|
||||||
geo.pop(limb, None)
|
|
||||||
prims = resolve_props(props, geo, norms[idx]["root"]["pos"])
|
prims = resolve_props(props, geo, norms[idx]["root"]["pos"])
|
||||||
cells.append((f"{motion['name']} — {label}",
|
cells.append((f"{motion['name']} — {label}",
|
||||||
draw_geo(geo, order, shade, working, PALETTES[palette],
|
draw_geo(geo, order, shade, working, PALETTES[palette],
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ struct FigureAnimation {
|
|||||||
let timeline: MotionTimeline
|
let timeline: MotionTimeline
|
||||||
/// Parts drawn in the working accent color (`arm_r`, `leg_l`, `spine`, …).
|
/// Parts drawn in the working accent color (`arm_r`, `leg_l`, `spine`, …).
|
||||||
let working: Set<String>
|
let working: Set<String>
|
||||||
/// Limbs fully occluded in this view — never drawn.
|
|
||||||
let hide: Set<String>
|
|
||||||
/// Equipment layer (see SYSTEM.md "The props layer").
|
/// Equipment layer (see SYSTEM.md "The props layer").
|
||||||
let props: [MotionProp]
|
let props: [MotionProp]
|
||||||
|
|
||||||
@@ -34,28 +32,20 @@ struct FigureAnimation {
|
|||||||
else { return nil }
|
else { return nil }
|
||||||
self.timeline = timeline
|
self.timeline = timeline
|
||||||
self.working = Set(resources.motion.working ?? [])
|
self.working = Set(resources.motion.working ?? [])
|
||||||
self.hide = Set(resources.motion.hide ?? [])
|
|
||||||
self.props = resources.motion.props ?? []
|
self.props = resources.motion.props ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Seconds per full camera revolution for orbiting motions.
|
/// Seconds per full camera revolution for orbiting motions.
|
||||||
private static let orbitPeriod: Double = 24
|
private static let orbitPeriod: Double = 24
|
||||||
|
|
||||||
/// Prop-free, hide-free motions slowly orbit the camera while animating — the
|
/// Prop-free motions slowly orbit the camera while animating — the bodyweight
|
||||||
/// bodyweight moves. Scene equipment is a view-locked billboard and a `hide` list
|
/// moves. Machines keep their fixed camera until their equipment rotates too.
|
||||||
/// describes one authored viewpoint, so machines keep their fixed camera.
|
var orbits: Bool { props.isEmpty }
|
||||||
var orbits: Bool { props.isEmpty && hide.isEmpty }
|
|
||||||
|
|
||||||
/// Drawable geometry at `time` — the figure plus the resolved equipment layers —
|
/// Drawable geometry at `time` — the figure plus the resolved equipment layers.
|
||||||
/// with limbs listed in `hide` dropped so neither they nor any prop riding them
|
|
||||||
/// are drawn.
|
|
||||||
func geometry(at time: Double) -> FigureGeometry {
|
func geometry(at time: Double) -> FigureGeometry {
|
||||||
let yaw = orbits ? 360 * (time / Self.orbitPeriod) : 0
|
let yaw = orbits ? 360 * (time / Self.orbitPeriod) : 0
|
||||||
var geo = timeline.geometry(at: time, yawOffset: yaw, props: props)
|
return timeline.geometry(at: time, yawOffset: yaw, props: props)
|
||||||
for name in hide {
|
|
||||||
if let limb = FigureLimb(rawValue: name) { geo.limbs[limb] = nil }
|
|
||||||
}
|
|
||||||
return geo
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,8 +235,6 @@ struct ExerciseMotion: Codable {
|
|||||||
let camera: MotionCamera?
|
let camera: MotionCamera?
|
||||||
/// Parts (`arm_r`, `leg_l`, `spine`, …) drawn in the working accent color.
|
/// Parts (`arm_r`, `leg_l`, `spine`, …) drawn in the working accent color.
|
||||||
let working: [String]?
|
let working: [String]?
|
||||||
/// Limbs fully occluded in this view — never drawn.
|
|
||||||
let hide: [String]?
|
|
||||||
/// Equipment layer: scene shapes and cables behind the figure, joint-attached
|
/// Equipment layer: scene shapes and cables behind the figure, joint-attached
|
||||||
/// items (bar/dumbbell/pad) over the limbs. See SYSTEM.md "The props layer".
|
/// items (bar/dumbbell/pad) over the limbs. See SYSTEM.md "The props layer".
|
||||||
let props: [MotionProp]?
|
let props: [MotionProp]?
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"name": "Hollow Body Hold",
|
"name": "Hollow Body Hold",
|
||||||
"primary": 2,
|
"primary": 2,
|
||||||
"working": ["spine"],
|
"working": ["spine"],
|
||||||
"hide": ["arm_l"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.4, "tween": 0.8,
|
"hold": 0.4, "tween": 0.8,
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
"shoulder_r": 180, "elbow_r": 0,
|
"shoulder_r": 180, "elbow_r": 0,
|
||||||
|
"shoulder_l": 180, "elbow_l": 0,
|
||||||
"hip_r": 0, "knee_r": 0,
|
"hip_r": 0, "knee_r": 0,
|
||||||
"hip_l": 0, "knee_l": 0
|
"hip_l": 0, "knee_l": 0
|
||||||
},
|
},
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"spine": [0, 14],
|
"spine": [0, 14],
|
||||||
"neck": 20,
|
"neck": 20,
|
||||||
"shoulder_r": 175, "elbow_r": 0,
|
"shoulder_r": 175, "elbow_r": 0,
|
||||||
|
"shoulder_l": 175, "elbow_l": 0,
|
||||||
"hip_r": 18, "knee_r": 0,
|
"hip_r": 18, "knee_r": 0,
|
||||||
"hip_l": 18, "knee_l": 0
|
"hip_l": 18, "knee_l": 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
"name": "Leg Raises",
|
"name": "Leg Raises",
|
||||||
"primary": 1,
|
"primary": 1,
|
||||||
"working": ["leg_r", "leg_l"],
|
"working": ["leg_r", "leg_l"],
|
||||||
"hide": ["arm_r"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.5, "tween": 1.4,
|
"hold": 0.5, "tween": 1.4,
|
||||||
"root": {"pos": [185, 148], "pitch": -90},
|
"root": {"pos": [185, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 60, "knee_r": 0,
|
"hip_r": 60, "knee_r": 0,
|
||||||
"hip_l": 60, "knee_l": 0
|
"hip_l": 60, "knee_l": 0
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"root": {"pos": [185, 148], "pitch": -90},
|
"root": {"pos": [185, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 8, "knee_r": 0,
|
"hip_r": 8, "knee_r": 0,
|
||||||
"hip_l": 8, "knee_l": 0
|
"hip_l": 8, "knee_l": 0
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
"name": "Reverse Crunch",
|
"name": "Reverse Crunch",
|
||||||
"primary": 2,
|
"primary": 2,
|
||||||
"working": ["spine"],
|
"working": ["spine"],
|
||||||
"hide": ["arm_r"],
|
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"hold": 0.5, "tween": 0.7,
|
"hold": 0.5, "tween": 0.7,
|
||||||
"root": {"pos": [172, 148], "pitch": -90},
|
"root": {"pos": [172, 148], "pitch": -90},
|
||||||
"spine": [0, 0],
|
"spine": [0, 0],
|
||||||
"neck": 12, "head": -12,
|
"neck": 12, "head": -12,
|
||||||
|
"shoulder_r": -2, "elbow_r": 0,
|
||||||
"shoulder_l": -2, "elbow_l": 0,
|
"shoulder_l": -2, "elbow_l": 0,
|
||||||
"hip_r": 100, "knee_r": 120,
|
"hip_r": 100, "knee_r": 120,
|
||||||
"hip_l": 100, "knee_l": 120
|
"hip_l": 100, "knee_l": 120
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"root": {"pos": [166, 136], "pitch": -105},
|
"root": {"pos": [166, 136], "pitch": -105},
|
||||||
"spine": [0, 20],
|
"spine": [0, 20],
|
||||||
"neck": -7, "head": 2,
|
"neck": -7, "head": 2,
|
||||||
|
"shoulder_r": 3, "elbow_r": 0,
|
||||||
"shoulder_l": 3, "elbow_l": 0,
|
"shoulder_l": 3, "elbow_l": 0,
|
||||||
"hip_r": 100, "knee_r": 125,
|
"hip_r": 100, "knee_r": 125,
|
||||||
"hip_l": 100, "knee_l": 125
|
"hip_l": 100, "knee_l": 125
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ struct ExerciseMotionTests {
|
|||||||
#expect(hypot(releasedHand.x - releasedHand0.x, releasedHand.y - releasedHand0.y) > 1)
|
#expect(hypot(releasedHand.x - releasedHand0.x, releasedHand.y - releasedHand0.y) > 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prop-free bodyweight motions slowly orbit the camera while looping; motions with
|
/// Prop-free bodyweight motions slowly orbit the camera while looping; motions
|
||||||
/// equipment (view-locked scene shapes) or a hide list keep their authored view.
|
/// with equipment keep their authored view (until machines orbit too).
|
||||||
@Test func orbitAppliesOnlyToPropFreeMotions() throws {
|
@Test func orbitAppliesOnlyToPropFreeMotions() throws {
|
||||||
let birdDog = try #require(FigureAnimation(exerciseName: "Bird Dog"))
|
let birdDog = try #require(FigureAnimation(exerciseName: "Bird Dog"))
|
||||||
#expect(birdDog.orbits)
|
#expect(birdDog.orbits)
|
||||||
|
|||||||