diff --git a/Dependencies/gamelib b/Dependencies/gamelib index 3c916b8..a460f3f 160000 --- a/Dependencies/gamelib +++ b/Dependencies/gamelib @@ -1 +1 @@ -Subproject commit 3c916b8cb7a05eebbee790f4b8d3480cf5f296aa +Subproject commit a460f3fcd8cab8de22ff9381edb9f55954438868 diff --git a/data/TestPuppet_skeleton.cakedata b/data/TestPuppet_skeleton.cakedata index 2cbeba8..56ad6ef 100644 --- a/data/TestPuppet_skeleton.cakedata +++ b/data/TestPuppet_skeleton.cakedata @@ -1,194 +1,258 @@ (skeleton-data :svg-name "TestPuppet" - :bones (array (skeleton-bone :shape-id "UpperArmRight" - :start-position (vec 0.000 0.000) - :rest-position (vec 1.000 2.000) - :end-position (vec 3.000 4.000)) (skeleton-bone :shape-id "LowerArmRight" - :start-position (vec 0.000 10.000) - :rest-position (vec 10.000 10.000) - :end-position (vec 0.000 10.000)) (skeleton-bone :shape-id "Arm_Upper_Right" + :bones (array (skeleton-bone :shape-id "Arm_Upper_Right" + :parent-shape-id "UpperBody" :start-position (vec 435.000 255.000) - :rest-position (vec 0.000 0.000) + :rest-position (vec 249.000 251.000) :end-position (vec 247.000 252.000)) (skeleton-bone :shape-id "Arm_Lower_Right" + :parent-shape-id "Arm_Upper_Right" :start-position (vec 268.000 256.000) - :rest-position (vec 0.000 0.000) + :rest-position (vec 102.000 255.000) :end-position (vec 101.000 255.000)) (skeleton-bone :shape-id "Arm_Upper_Left" - :start-position (vec 581.000 253.000) - :rest-position (vec 846.000 254.000) - :end-position (vec 773.000 252.000)) (skeleton-bone :shape-id "Arm_Lower_Left" + :parent-shape-id "UpperBody" + :start-position (vec 584.000 253.000) + :rest-position (vec 794.000 254.000) + :end-position (vec 772.000 254.000)) (skeleton-bone :shape-id "Arm_Lower_Left" + :parent-shape-id "Arm_Upper_Left" :start-position (vec 758.000 256.000) - :rest-position (vec 958.000 209.000) + :rest-position (vec 913.000 254.000) :end-position (vec 919.000 254.000)) (skeleton-bone :shape-id "Hand_Right" + :parent-shape-id "Arm_Lower_Right" + :start-position (vec 95.000 255.000) + :rest-position (vec 65.000 257.000) + :end-position (vec 59.000 256.000)) (skeleton-bone :shape-id "Hand_Left" + :parent-shape-id "Arm_Lower_Left" + :start-position (vec 922.000 255.000) + :rest-position (vec 997.000 252.000) + :end-position (vec 963.000 255.000)) (skeleton-bone :shape-id "Waist" + :parent-shape-id "Hip" + :start-position (vec 511.000 449.000) + :rest-position (vec 515.000 354.000) + :end-position (vec 515.000 353.000)) (skeleton-bone :shape-id "UpperBody" + :parent-shape-id "Waist" + :start-position (vec 511.000 371.000) + :rest-position (vec 508.000 230.000) + :end-position (vec 509.000 230.000)) (skeleton-bone :shape-id "Neck" + :parent-shape-id "UpperBody" + :start-position (vec 509.000 223.000) + :rest-position (vec 510.000 196.000) + :end-position (vec 510.000 195.000)) (skeleton-bone :shape-id "Head" + :parent-shape-id "Neck" + :start-position (vec 509.000 181.000) + :rest-position (vec 510.000 16.000) + :end-position (vec 510.000 16.000)) (skeleton-bone :shape-id "Leg_Upper_Right" + :parent-shape-id "Hip" + :start-position (vec 437.000 484.000) + :rest-position (vec 439.000 737.000) + :end-position (vec 439.000 738.000)) (skeleton-bone :shape-id "Leg_Upper_Left" + :parent-shape-id "Hip" + :start-position (vec 579.000 474.000) + :rest-position (vec 582.000 737.000) + :end-position (vec 581.000 739.000)) (skeleton-bone :shape-id "Leg_Lower_Left" + :parent-shape-id "Leg_Upper_Left" + :start-position (vec 578.000 701.000) + :rest-position (vec 580.000 944.000) + :end-position (vec 580.000 944.000)) (skeleton-bone :shape-id "Leg_Lower_Right" + :parent-shape-id "Leg_Upper_Right" + :start-position (vec 439.000 705.000) + :rest-position (vec 438.000 937.000) + :end-position (vec 438.000 951.000)) (skeleton-bone :shape-id "Foot_Right" + :parent-shape-id "Leg_Lower_Right" + :start-position (vec 438.000 940.000) + :rest-position (vec 438.000 1008.000) + :end-position (vec 438.000 1009.000)) (skeleton-bone :shape-id "Foot_Left" + :parent-shape-id "Leg_Lower_Left" + :start-position (vec 579.000 953.000) + :rest-position (vec 577.000 1002.000) + :end-position (vec 577.000 1002.000)) (skeleton-bone :shape-id "Hip" + :parent-shape-id "Hip" + :start-position (vec 510.000 465.000) + :rest-position (vec 593.000 465.000) + :end-position (vec 593.000 464.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" - :start-position (vec 0.000 0.000) - :rest-position (vec 0.000 0.000) - :end-position (vec 0.000 0.000)) (skeleton-bone :shape-id "" + :parent-shape-id "" :start-position (vec 0.000 0.000) :rest-position (vec 0.000 0.000) :end-position (vec 0.000 0.000)))) diff --git a/src/VectorPuppetShow.cake b/src/VectorPuppetShow.cake index b796937..819c8c2 100644 --- a/src/VectorPuppetShow.cake +++ b/src/VectorPuppetShow.cake @@ -10,12 +10,14 @@ "CHelpers.cake" "FileUtilities.cake" ;; GameLib "Introspection.cake" "SDL.cake" "DynamicArray.cake" "Dictionary.cake" "DataBundle.cake" - "SDLFontAtlas.cake" "FreeType.cake" + "SDLFontAtlas.cake" "FreeType.cake" "Hash.cake" "HashStringTable.cake" &with-decls "Math.cake") (c-import "" &with-decls "") +(var g-string-table hash-string-table null) + (bundle-file s-start-ubuntu-regular-font s-end-ubuntu-regular-font (unsigned char) "data/Fonts/Ubuntu-R.ttf") @@ -28,6 +30,8 @@ (define-keybind s-view-svg-keybind (array SDL_SCANCODE_F3)) (define-keybind s-view-puppet-keybind (array SDL_SCANCODE_F4)) +(define-keybind s-assigning-parent-keybind (array SDL_SCANCODE_P)) + (define-keybind s-toggle-fullscreen-keybind (array SDL_SCANCODE_F11)) (var s-key-states sdl-key-states (array 0)) @@ -61,6 +65,7 @@ (def-introspect-struct skeleton-bone shape (addr NSVGshape) (ignore) shape-id (array 64 char) + parent-shape-id (array 64 char) start-position vec2 (override 'vec2) rest-position vec2 (override 'vec2) end-position vec2 (override 'vec2)) @@ -178,12 +183,47 @@ ;; (incr point-index))) ;; (break)))) +(defstruct-local skeleton-effector + shape-id hash-string-id + position vec2) + +(defun-local do-inverse-kinematics (skeleton (addr skeleton-data) + effectors (addr skeleton-effector) + num-effectors int) + (each-in-range num-effectors effector-index + (var root-effector (addr skeleton-effector) (addr (at effector-index effectors))) + (var next-chain-effector skeleton-effector (deref root-effector)) + ;; TODO: This is only to catch loops, not refine the descent + (var max-iterations (const int) 10) + (var num-iterations int 0) + (while (and (field next-chain-effector shape-id) + (< num-iterations max-iterations)) + (incr num-iterations) + (each-item-addr-in-array (path skeleton > bones) i bone (addr skeleton-bone) + (unless (= (id-from-string (addr g-string-table) + (path bone > shape-id) + (strlen (path bone > shape-id))) + (field next-chain-effector shape-id)) + (continue)) + (vpslog "Do kinematics on %s\n" (string-from-hash-string-id (addr g-string-table) + (field next-chain-effector shape-id))) + (set (field next-chain-effector shape-id) 0) + (when (at 0 (path bone > parent-shape-id)) + (set (field next-chain-effector shape-id) + (id-from-string (addr g-string-table) + (path bone > parent-shape-id) + (strlen (path bone > parent-shape-id))))) + (break))))) + (defun main (&return int) + (hash-crc32-initialize) (comptime-cond ('Windows (SetProcessDpiAwarenessContext DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))) (data-bundle-load-all-resources) + (defer (free-hash-string-table (addr g-string-table))) + (SDL_GL_SetAttribute SDL_GL_CONTEXT_MAJOR_VERSION 4) (SDL_GL_SetAttribute SDL_GL_CONTEXT_MINOR_VERSION 6) (SDL_SetHint SDL_HINT_RENDER_VSYNC "1") @@ -384,6 +424,7 @@ (var view-atlas bool false) (var view-svg bool false) (var view-puppet bool true) + (var assigning-parent bool false) (var exit-reason (addr (const char)) null) (while true @@ -411,6 +452,8 @@ (set view-svg (not view-svg))) (when (keybind-tapped (addr s-view-puppet-keybind) (addr s-key-states)) (set view-puppet (not view-puppet))) + (when (keybind-tapped (addr s-assigning-parent-keybind) (addr s-key-states)) + (set assigning-parent (not assigning-parent))) (var true-window-width int 0) (var true-window-height int 0) @@ -474,7 +517,7 @@ (set exit-reason "Failed to render atlas texture"))) ;; Start over selection to always ensure we pick the smallest shape - (when (bit-and mouse-button-state SDL_BUTTON_MMASK) + (when (bit-and mouse-button-state SDL_BUTTON_LMASK) (set selected-shape null)) (when view-selection ;; Shape selection and debug viewing (var hovered-shape-id-buffer (array 1024 char) (array 0)) @@ -534,8 +577,9 @@ (< mouse-x (at 2 sized-bounds)) (< mouse-y (at 3 sized-bounds))) ;; Select shape - (when (and (bit-and mouse-button-state SDL_BUTTON_MMASK) + (when (and (bit-and mouse-button-state SDL_BUTTON_LMASK) (or (not selected-shape) (is-shape-smaller sized-bounds selected-shape-bounds))) + (var previous-selected-bone (addr skeleton-bone) selected-bone) (set selected-shape shape) (memcpy selected-shape-bounds sized-bounds (sizeof selected-shape-bounds)) (each-item-addr-in-array (field skeleton bones) bone-index bone (addr skeleton-bone) @@ -548,7 +592,12 @@ (when (= 0 (strncmp (path shape > id) (path bone > shape-id) (sizeof (path bone > shape-id)))) (set selected-bone bone) - (break)))) + (break))) + (when (and previous-selected-bone assigning-parent) + (set assigning-parent false) + (snprintf (path previous-selected-bone > parent-shape-id) + (sizeof (path previous-selected-bone > parent-shape-id)) + "%s" (path shape > id)))) (SDL_SetRenderDrawColor renderer 10 230 10 255) (set hovered-write-head (+ hovered-write-head @@ -566,6 +615,14 @@ hovered-shape-id-buffer)) (when packed-rectangles + (var effector skeleton-effector (array 0)) + (set-fields effector + position (path selected-bone > end-position)) + (var effector-target (addr (const char)) "Hand_Right") + (set (field effector shape-id) (id-from-string (addr g-string-table) + effector-target + (strlen effector-target))) + (do-inverse-kinematics (addr skeleton) (addr effector) 1) (var current-rectangle (addr stbrp_rect) packed-rectangles) (each-shape-in-svg-image puppet-image shape (unless (bit-and (path shape > flags) NSVG_FLAGS_VISIBLE) @@ -588,7 +645,7 @@ (SDL_RenderDrawRect renderer (addr draw-rectangle))) (when view-puppet - ;; We are ever so slightly off + ;; We are ever so slightly off due to this, but it's pretty close (var sized-bounds (array 4 float) (array 0)) (nanosvg-get-shape-bounds-with-stroke-float shape sized-bounds) (var to-rectangle SDL_Rect @@ -630,14 +687,14 @@ (incr current-rectangle))) (cond - ((and (bit-and mouse-button-state SDL_BUTTON_LMASK) + ((and (bit-and mouse-button-state SDL_BUTTON_MMASK) (or (at SDL_SCANCODE_LCTRL (field s-key-states this-frame-states)) (at SDL_SCANCODE_RCTRL (field s-key-states this-frame-states)))) (set-fields (deref selected-bone) shape selected-shape (rest-position X) mouse-x (rest-position Y) mouse-y)) - ((bit-and mouse-button-state SDL_BUTTON_LMASK) + ((bit-and mouse-button-state SDL_BUTTON_MMASK) (set-fields (deref selected-bone) shape selected-shape (start-position X) mouse-x @@ -663,7 +720,12 @@ (when selected-shape (var buffer (array 256 char) (array 0)) - (snprintf buffer (- (array-size buffer) 1) "Editing shape %s" (path selected-shape > id)) + (snprintf buffer (- (array-size buffer) 1) "%s shape %s (parent %s)" + (? assigning-parent "Parenting" "Editing") + (path selected-shape > id) + (? (at 0 (path selected-bone > parent-shape-id)) + (path selected-bone > parent-shape-id) + "none")) (render-string renderer (addr (field (at body-font-index font-atlases) atlas)) (field (at body-font-index font-atlases) texture)