luv

Workshop wiki

body-gallery.lisp

luvcraft/body-gallery.lisp

system luvcraft/web · 19 definitions · on GitHub

The browser edge for luvcraft's analytic agent bodies.

A web-body-type is the small piece of application knowledge that the browser needs around the shader graph: which shader role names the body, which knob group belongs to it, and the conservative sphere that its billboard rasterizes. Everything else -- WGSL and knob metadata -- is derived from the same Lisp objects that the native game uses.

in-package#:luvcraft.web
defclassweb-body-type
id:initarg:id:readerweb-body-id
label:initarg:label:readerweb-body-label
role:initarg:role:readerweb-body-role
knob-group:initarg:knob-group:readerweb-body-knob-group
center-height:initarg:center-height:readerweb-body-center-height
radius:initarg:radius:readerweb-body-radius
:documentation

One native analytic body as a browser-facing shader and framing preset.

defparameter*web-body-types*
list
make-instance'web-body-type:id"gnome":label"Gnome":role:gnome-sdf

Covers gnome-figure-radius throughout every published knob range, including the tallest leaned hat.

:knob-group:gnome:center-height0.85:radius1.90
make-instance'web-body-type:id"cat":label"Cat":role:cat-sdf

Covers cat-figure-radius throughout its knob ranges.

:knob-group:cat:center-height0.64:radius1.16
defunweb-body-types

The ordered body catalog shown by the web gallery.

defclassbody-gallery-bundle
body:initarg:body:readerbody-gallery-bundle-body
vertex:initarg:vertex:readerbody-gallery-bundle-vertex
fragment:initarg:fragment:readerbody-gallery-bundle-fragment
defuncompile-body-gallery

Compile every catalog body from the shared shader graph to WGSL.

loopforbodyinforknobs=
luvcraft:knobs-in-group
web-body-knob-groupbody
foroverrides=
mapcar#'luvcraft:knob-nameknobs
collect
make-instance'body-gallery-bundle:bodybody:vertex
wgsl:compile-wgsl
shader:shader-specification-for
web-body-rolebody
:vertex
:overridesoverrides
:fragment
wgsl:compile-wgsl
shader:shader-specification-for
web-body-rolebody
:fragment
:overridesoverrides
defunweb-name
name
string-downcase
stringname
defunoverride-for-knob
knobbundle
let
name
luvcraft:knob-nameknob
or
findname
wgsl:wgsl-document-overrides
body-gallery-bundle-vertexbundle
:key#'wgsl:wgsl-override-name
findname
wgsl:wgsl-document-overrides
body-gallery-bundle-fragmentbundle
:key#'wgsl:wgsl-override-name
defunknob-stages
knobbundle
let
name
luvcraft:knob-nameknob
loopforin`
"vertex",
body-gallery-bundle-vertexbundle
"fragment",
body-gallery-bundle-fragmentbundle
when
findname
wgsl:wgsl-document-overridesdocument
:key#'wgsl:wgsl-override-name
collectstage
defunknob-json-object
knobbundle
let
override
unlessoverride
error"Body knob ~S did not occur in either compiled shader."
luvcraft:knob-nameknob
`
"name".,
web-name
luvcraft:knob-nameknob
"identifier".,
wgsl:wgsl-override-identifieroverride
"label".,
luvcraft:knob-labelknob
"documentation".,
or
luvcraft:knob-documentationknob
""
"minimum".,
luvcraft:knob-minimumknob
"maximum".,
luvcraft:knob-maximumknob
"step".,
luvcraft:knob-stepknob
"stages".,
defunbundle-json-object
bundlebase-path
let*
body
body-gallery-bundle-bodybundle
id
web-body-idbody
knobs
luvcraft:knobs-in-group
web-body-knob-groupbody
`
"id".,id
"label".,
web-body-labelbody
"centerHeight".,
web-body-center-heightbody
"radius".,
web-body-radiusbody
"statureKnob".,
formatnil"~A-stature"id
"vertexUrl".,
formatnil"~A/body/~A/vertex.wgsl"base-pathid
"fragmentUrl".,
formatnil"~A/body/~A/fragment.wgsl"base-pathid
"knobs".,
mapcarknobs
defunbody-gallery-json
&optional
base-path"/bodies"

Encode the catalog and actual native knob metadata for JavaScript.

cl-json:encode-json-alist-to-string`
"bodies".,
mapcar
lambda
bundle
bundle-json-objectbundlebase-path
bundles
defungallery-asset
name
uiop:read-file-string
asdf:system-relative-pathname"luvcraft/web"
formatnil"luvcraft/web/~A"name
defunfind-bundle
idbundles
findidbundles:test#'string=:key
lambda
bundle
web-body-id
body-gallery-bundle-bodybundle
defunbody-shader-response
pathbundles
let*
parts
uiop:split-stringpath:separator'
#\/
id
thirdparts
file
fourthparts
bundle
and
=4
lengthparts
find-bundleidbundles
whenbundle
cond
string=file"vertex.wgsl"
wgsl:wgsl-document-source
body-gallery-bundle-vertexbundle
string=file"fragment.wgsl"
wgsl:wgsl-document-source
body-gallery-bundle-fragmentbundle
defclassbody-gallery-page
bundles:initarg:bundles:readerbody-gallery-page-bundles
catalog-json:initarg:catalog-json:readerbody-gallery-page-catalog-json
defunmake-body-gallery-page
&optional
make-instance'body-gallery-page:path"/bodies":label"Agent bodies":description"Gnomes and cats, compiled from luv shaders to live WebGPU.":bundlesbundles:catalog-json
defmethodrespond-to-web-request
cond
or
string=path"/"
string=path"/index.html"
ok-response"text/html; charset=utf-8"
gallery-asset"body-gallery.html"
string=path"/gallery.js"
ok-response"text/javascript; charset=utf-8"
gallery-asset"body-gallery.js"
string=path"/gallery.css"
ok-response"text/css; charset=utf-8"
gallery-asset"body-gallery.css"
string=path"/bodies.json"
ok-response"application/json; charset=utf-8"
body-gallery-page-catalog-jsonpage
t
let
source
body-shader-responsepath
body-gallery-page-bundlespage
ifsource
ok-response"text/wgsl; charset=utf-8"source
call-next-method
defunmake-luvcraft-web-application
&keybundlesshowcase-directory

Build the luvcraft web application and its currently installed pages.

defunserve-luvcraft-web
&key
host"127.0.0.1"
port8765

Compile the web-facing artifacts once, then serve luvcraft until stopped.