Browse Source

[ts][webgl] Added example demonstrating how to drag bones. Closes #2151.

Mario Zechner 3 years ago
parent
commit
e01ba364df
2 changed files with 127 additions and 0 deletions
  1. 1 0
      spine-ts/index.html
  2. 126 0
      spine-ts/spine-webgl/example/bone-dragging.html

+ 1 - 0
spine-ts/index.html

@@ -30,6 +30,7 @@
 			<li><a href="/spine-webgl/example/mix-and-match.html">Mix &amp; match</a></li>
 			<li><a href="/spine-webgl/example/drag-and-drop.html">Drag &amp; drop</a></li>
 			<li><a href="/spine-webgl/example/dress-up.html">Dress-up</a></li>
+			<li><a href="/spine-webgl/example/bone-dragging.html">Bone dragging</a></li>
 			<li><a href="/spine-webgl/demos/additiveblending.html">Additive blending</a></li>
 			<li><a href="/spine-webgl/demos/clipping.html">Clipping</a></li>
 			<li><a href="/spine-webgl/demos/hoverboard.html">Hoverboard</a></li>

+ 126 - 0
spine-ts/spine-webgl/example/bone-dragging.html

@@ -0,0 +1,126 @@
+<html>
+<script src="../dist/iife/spine-webgl.js"></script>
+<style>
+	* {
+		margin: 0;
+		padding: 0;
+	}
+</style>
+
+<body>
+	<canvas id="canvas" style="position: absolute; width: 100%; height: 100%;"></canvas>
+	<script>
+        class App {
+            constructor() {
+                this.skeleton = null;
+                this.animationState = null;
+                this.draggableBones = [];
+                this.draggedBone = null;
+            }
+
+            loadAssets(canvas) {				
+                canvas.assetManager.loadBinary("assets/stretchyman-pro.skel");				
+                canvas.assetManager.loadTextureAtlas("assets/stretchyman-pma.atlas");
+            }
+
+            initialize(canvas) {
+                let assetManager = canvas.assetManager;
+                var atlas = assetManager.require("assets/stretchyman-pma.atlas");				
+                var atlasLoader = new spine.AtlasAttachmentLoader(atlas);				
+                var skeletonBinary = new spine.SkeletonBinary(atlasLoader);				
+                skeletonBinary.scale = 1;
+                var skeletonData = skeletonBinary.readSkeletonData(assetManager.require("assets/stretchyman-pro.skel"));
+                this.skeleton = new spine.Skeleton(skeletonData);				
+                var animationStateData = new spine.AnimationStateData(skeletonData);
+                this.animationState = new spine.AnimationState(animationStateData);				
+
+                // Find the bones that should be draggable
+                let draggableBoneNames = [            
+                    "back-leg-ik-target",
+                    "front-leg-ik-target",
+                    "back-arm-ik-target",
+                    "front-arm-ik-target",            
+                    "hip",
+                    "neck2"
+                ];                
+                for (let boneName of draggableBoneNames) {                    
+                    let bone = this.skeleton.findBone(boneName);
+                    if (bone == null) throw Error("Couldn't find bone " + boneName);            
+                    this.draggableBones.push(bone)
+                }
+
+                // Setup an input listener on the canvas to process touch/mouse events.        
+                canvas.input.addListener({            
+                    down: (x, y) => {
+                        // Calculate the mouse position in the coordinate space of the camera, aka world space.
+                        // The skeleton and its bones live in the same coordinate space.
+                        let mousePosition = new spine.Vector3(x, y);
+                        canvas.renderer.camera.screenToWorld(mousePosition, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
+
+                        // Find the first bone within a radius of 20 pixels to the mouse position
+                        this.selectedBone = null;
+                        for (let bone of this.draggableBones) {
+                            if (mousePosition.distance(new spine.Vector3(bone.worldX, bone.worldY, 0)) < 20) {
+                                this.selectedBone = bone;
+                                break;
+                            }
+                        }
+                    },
+                    dragged: (x, y) => {
+                        // If no bone was selected, bail.
+                        if (this.selectedBone == null) return;
+
+                        // Calculate the mouse position in the coordinate space of the camera, aka world space.
+                        // The skeleton and its bones live in this coordinate space.
+                        let mousePosition = new spine.Vector3(x, y);
+                        canvas.renderer.camera.screenToWorld(mousePosition, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
+                        
+                        if (this.selectedBone.parent != null) {
+                            // If the bone to be dragged has a parent, transform the mouse world position to
+                            // the parent bone's coordinate system, and set the bone's position accordingly.
+                            let position = new spine.Vector2(mousePosition.x, mousePosition.y);
+                            this.selectedBone.parent.worldToLocal(position);
+                            this.selectedBone.x = position.x;
+                            this.selectedBone.y = position.y;
+                        } else {
+                            // If the dragged bone has no parent, it's the root bone and we can simply set its
+                            // position to the mouse world position.
+                            this.selectedBone.x = mousePosition.x;
+                            this.selectedBone.y = mousePosition.y;
+                        }
+                    }
+                })
+            }
+
+            update(canvas, delta) {				
+                this.animationState.update(delta);				
+                this.animationState.apply(this.skeleton);				
+                this.skeleton.updateWorldTransform();
+            }
+
+            render(canvas) {
+                let renderer = canvas.renderer;				
+                renderer.resize(spine.ResizeMode.Expand);				
+                canvas.clear(0.2, 0.2, 0.2, 1);
+                
+                renderer.begin();				
+                renderer.drawSkeleton(this.skeleton, true);
+
+                // Draw a circle with a radius of 20 pixels around each draggable bone
+                let boneColor = new spine.Color(1, 0, 0, 0.5);
+                let selectedBoneColor = new spine.Color(0, 1, 0, 0.5);
+                for (let bone of this.draggableBones) {            
+                    renderer.circle(true, bone.worldX, bone.worldY, 20, bone == this.selectedBone ? selectedBoneColor : boneColor);
+                }	        
+
+                renderer.end();
+            }
+        }
+
+        new spine.SpineCanvas(document.getElementById("canvas"), {
+            app: new App()
+        })
+    </script>
+</body>
+
+</html>