Browse Source

Start making SVG interactive

master
Macoy Madson 4 months ago
parent
commit
f0e66cd440
  1. 2
      Dependencies/nanosvg
  2. 60
      data/TestPuppet.svg
  3. 9
      src/NanoSVG.cake
  4. 105
      src/VectorPuppetShow.cake

2
Dependencies/nanosvg

@ -1 +1 @@
Subproject commit 5d01ca80ec32efaecee50c0d71461993ede55c16
Subproject commit ae22b51cde85a401813c3104b94c6bcd69e580e7

60
data/TestPuppet.svg

@ -26,10 +26,10 @@
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.1775363"
inkscape:cx="446.18745"
inkscape:cx="228.35976"
inkscape:cy="649.97768"
inkscape:document-units="px"
inkscape:current-layer="g1453"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
@ -56,7 +56,7 @@
id="layer1"
transform="translate(0,-26.066667)">
<g
id="g1429"
id="Arm_Right"
inkscape:label="Arm Right"
transform="matrix(0.92814178,0,0,0.92814178,12.903386,-31.027851)"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
@ -66,11 +66,11 @@
rx="29.659384"
cy="134.09808"
cx="83.36084"
id="path1405"
id="Arm_Upper_Right"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1409"
id="Arm_Lower_Right"
cx="38.759418"
cy="134.09808"
rx="25.954048"
@ -82,42 +82,42 @@
rx="6.7407689"
cy="134.09808"
cx="8.0889225"
id="path1411"
id="Hand_Right"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
inkscape:label="Leg Left"
id="g1453"
inkscape:label="Leg Right"
id="Leg_Right"
transform="matrix(0,-1.3183544,1.3183544,0,-60.6927,295.51511)"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<ellipse
inkscape:label="Arm Lower Right"
inkscape:label="Leg Lower Right"
ry="6.1939092"
rx="25.954048"
cy="134.09808"
cx="38.759418"
id="ellipse1449"
id="Leg_Lower_Right"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1447"
id="Leg_Upper_Right"
cx="83.36084"
cy="134.09808"
rx="29.659384"
ry="7.6395378"
inkscape:label="Arm Upper Right" />
inkscape:label="Leg Upper Right" />
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1451"
id="Foot_Right"
cx="8.0889225"
cy="134.09808"
rx="6.7407689"
ry="5.842"
inkscape:label="Hand Right" />
inkscape:label="Foot Right" />
</g>
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.32291663;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1455"
id="Neck"
cx="134.55244"
cy="81.183044"
rx="6.2913847"
@ -125,20 +125,20 @@
inkscape:label="Neck" />
<circle
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.32291663;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1397"
id="Head"
cx="134.55244"
cy="53.551071"
inkscape:label="Head"
r="24.557083" />
<g
id="g1424"
id="Arm_Left"
inkscape:label="Arm Left"
transform="matrix(0.92814178,0,0,0.92814178,12.903386,-31.027851)"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<ellipse
transform="scale(-1,1)"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1415"
id="Arm_Upper_Left"
cx="-179.30446"
cy="134.09808"
rx="29.659384"
@ -151,12 +151,12 @@
rx="25.954048"
cy="134.09808"
cx="-223.90587"
id="ellipse1417"
id="Arm_Lower_Left"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
transform="scale(-1,1)"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.42533898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1419"
id="Hand_Left"
cx="-254.57637"
cy="134.09808"
rx="6.7407689"
@ -165,7 +165,7 @@
</g>
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.15914345;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1399"
id="UpperBody"
cx="134.55244"
cy="106.91435"
rx="29.553249"
@ -176,43 +176,43 @@
rx="24.259771"
cy="135.45627"
cx="134.55244"
id="ellipse1401"
id="Waist"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.32291663;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:label="Waist" />
<g
transform="matrix(0,-1.3183544,1.3183544,0,-23.780004,295.51511)"
id="g1445"
id="Leg_Left"
inkscape:label="Leg Left"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<ellipse
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1441"
id="Leg_Lower_Left"
cx="38.759418"
cy="134.09808"
rx="25.954048"
ry="6.1939092"
inkscape:label="Arm Lower Right" />
inkscape:label="Leg Lower Left" />
<ellipse
inkscape:label="Arm Upper Right"
inkscape:label="Leg Upper Left"
ry="7.6395378"
rx="29.659384"
cy="134.09808"
cx="83.36084"
id="ellipse1439"
id="Leg_Upper_Left"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
inkscape:label="Hand Right"
inkscape:label="Foot Left"
ry="5.842"
rx="6.7407689"
cy="134.09808"
cx="8.0889225"
id="ellipse1443"
id="Foot_Left"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.00346053;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<ellipse
inkscape:label="Hip"
style="fill:#c37033;fill-opacity:1;stroke:#275d59;stroke-width:1.32291663;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="ellipse1403"
id="Hip"
cx="134.55244"
cy="148.49042"
rx="26.762945"

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

9
src/NanoSVG.cake

@ -5,3 +5,12 @@
(export-and-evaluate
(add-c-search-directory-module "Dependencies/nanosvg/src")
(c-import "nanosvg.h" "nanosvgrast.h"))
(defmacro each-shape-in-svg-image (image any shape-name symbol &rest body array)
(tokenize-push output
(c-for (var (token-splice shape-name) (addr NSVGshape)
(path (token-splice image) > shapes))
(token-splice shape-name)
(set (token-splice shape-name) (path (token-splice shape-name) > next))
(token-splice-rest body tokens)))
(return true))

105
src/VectorPuppetShow.cake

@ -61,7 +61,7 @@
(SDL_GL_SetAttribute SDL_GL_CONTEXT_MINOR_VERSION 6)
(SDL_SetHint SDL_HINT_RENDER_VSYNC "1")
(var window (addr SDL_Window) null)
(unless (sdl-initialize-for-2d (addr window) "Presentation" 1920 1080)
(unless (sdl-initialize-for-2d (addr window) "Vector Puppet Show" 1920 1080)
(vpslog "Failed to initialize SDL\n")
(return 1))
(defer (sdl-shutdown window))
@ -145,6 +145,8 @@
;; SVGs
;;
(var svg-image-texture (addr SDL_Texture) null)
(var puppet-image (addr NSVGimage) null)
(defer (when puppet-image (nsvgDelete puppet-image)))
(var svg-image-width int 0)
(var svg-image-height int 0)
(defer
@ -152,36 +154,46 @@
(SDL_DestroyTexture svg-image-texture)))
(scope
(var filename (addr (const char)) "data/TestPuppet.svg")
(var image (addr NSVGimage) (nsvgParseFromFile filename "px" 96.0f))
(unless image
(set puppet-image (nsvgParseFromFile filename "px" 96.0f))
(unless puppet-image
(vpslog "Failed to load SVG %s\n" filename)
(return 1))
(defer (nsvgDelete image))
(var rasterizer (addr NSVGrasterizer) (nsvgCreateRasterizer))
(unless rasterizer
(vpslog "Failed to create NanoSVG rasterizer\n")
(return 1))
(defer (nsvgDeleteRasterizer rasterizer))
(var-cast-to image-buffer (addr (unsigned char))
(malloc (* (path image > width) (path image > height) 4)))
(malloc (* (path puppet-image > width) (path puppet-image > height) 4)))
(defer (free image-buffer))
(nsvgRasterize rasterizer image 0 0 1 image-buffer (path image > width) (path image > height)
(* 4 (path image > width)))
(each-shape-in-svg-image puppet-image shape
;; (when (= 0 (strncmp (path shape > id) "Head" (sizeof (path shape > id))))
;; (set (path shape > flags)
;; (bit-xor (path shape > flags) NSVG_FLAGS_VISIBLE)))
(vpslog "Shape %s\n\tBounds: %.2f %.2f -> %.2f %.2f\n" (path shape > id)
(at 0 (path shape > bounds))
(at 1 (path shape > bounds))
(at 2 (path shape > bounds))
(at 3 (path shape > bounds))))
(nsvgRasterize rasterizer puppet-image 0 0 1 image-buffer
(path puppet-image > width) (path puppet-image > height)
(* 4 (path puppet-image > width)))
(var image-surface (addr SDL_Surface)
(SDL_CreateRGBSurfaceWithFormatFrom
image-buffer
(path image > width)
(path image > height)
(path puppet-image > width)
(path puppet-image > height)
32 ;; bit depth of each pixel (RGBA)
(* (path image > width) 4) ;; pitch (width of a row in bytes)
(* (path puppet-image > width) 4) ;; pitch (width of a row in bytes)
;; Because of how SDL reads pixels in, this does seem to be endian-dependent
;; I don't fully understand why
SDL_PIXELFORMAT_RGBA32))
(defer (SDL_FreeSurface image-surface)) ;; We don't need this after making the texture
(set svg-image-texture (SDL_CreateTextureFromSurface renderer image-surface))
(set svg-image-width (path image > width))
(set svg-image-height (path image > height))
(set svg-image-width (path puppet-image > width))
(set svg-image-height (path puppet-image > height))
(unless svg-image-texture
(sdl-print-error)
(return 1)))
@ -240,12 +252,6 @@
(SDL_SetRenderDrawColor renderer 11 11 11 255)
(SDL_RenderClear renderer)
(render-string
renderer (addr (field (at body-font-index font-atlases) atlas))
(field (at body-font-index font-atlases) texture)
(/ true-window-width 9) (- true-window-height 10)
"This is a test string")
(scope
(var source-rectangle SDL_Rect
(array 0
@ -261,30 +267,45 @@
(SDL_RenderCopy renderer svg-image-texture
(addr source-rectangle) (addr destination-rectangle)))
;; (when s-enable-debug-overlay
;; (var buffer (array 256 char) (array 0))
;; (var mouse-x int 0)
;; (var mouse-y int 0)
;; (SDL_GetMouseState (addr mouse-x) (addr mouse-y))
;; (snprintf buffer (- (array-size buffer) 1) "Mouse: %4d %4d Percent of window: %.2f %.2f Wizard relative: %4d %4d"
;; mouse-x mouse-y
;; (/ mouse-x (type-cast true-window-width float)) (/ mouse-y (type-cast true-window-height float))
;; (- mouse-x (field g-wizard-hero x)) (- mouse-y (field g-wizard-hero y)))
;; (render-string
;; renderer (addr (field (at body-code-font-index font-atlases) atlas))
;; (field (at body-code-font-index font-atlases) texture)
;; 10 (- true-window-height 20)
;; buffer))
;; ;; #"#
;; ;; result= FT_Set_Char_Size(typeface, 0, (16 * 64), 300, 300);
;; ;; if (!((result== FT_Err_Ok)))
;; ;; {
;; ;; fprintf(stderr, "error: encountered error %d while %s\n", result, "setting character size");
;; ;; FT_Done_Face(typeface);
;; ;; FT_Done_FreeType(freetypeLibrary);
;; ;; return 1;
;; ;; }#"#)
(var mouse-x int 0)
(var mouse-y int 0)
(SDL_GetMouseState (addr mouse-x) (addr mouse-y))
(each-shape-in-svg-image puppet-image shape
(var shape-bounds SDL_Rect
(array (type-cast (at 0 (path shape > bounds)) int)
(type-cast (at 1 (path shape > bounds)) int)
(type-cast (- (at 2 (path shape > bounds))
(at 0 (path shape > bounds)))
int)
(type-cast (- (at 3 (path shape > bounds))
(at 1 (path shape > bounds)))
int)))
(SDL_SetRenderDrawColor renderer 230 10 10 255)
(when (and (>= mouse-x (type-cast (at 0 (path shape > bounds)) float))
(>= mouse-y (type-cast (at 1 (path shape > bounds)) float))
(< mouse-x (type-cast (at 2 (path shape > bounds)) float))
(< mouse-y (type-cast (at 3 (path shape > bounds)) float)))
(SDL_SetRenderDrawColor renderer 10 230 10 255)
(render-string
renderer (addr (field (at body-font-index font-atlases) atlas))
(field (at body-font-index font-atlases) texture)
(/ true-window-width 9) (- true-window-height 10)
(path shape > id)))
(SDL_RenderDrawRect renderer (addr shape-bounds)))
(when true
(var buffer (array 256 char) (array 0))
(var mouse-x int 0)
(var mouse-y int 0)
(SDL_GetMouseState (addr mouse-x) (addr mouse-y))
(snprintf buffer (- (array-size buffer) 1) "Mouse: %4d %4d Percent of window: %.2f %.2f"
mouse-x mouse-y
(/ mouse-x (type-cast true-window-width float)) (/ mouse-y (type-cast true-window-height float)))
(render-string
renderer (addr (field (at body-code-font-index font-atlases) atlas))
(field (at body-code-font-index font-atlases) texture)
10 (- true-window-height 50)
buffer))
(SDL_RenderPresent renderer)
(SDL_UpdateWindowSurface window)

Loading…
Cancel
Save