Skip to content

Commit

Permalink
[vc] Move animation-node-player to VybeC
Browse files Browse the repository at this point in the history
  • Loading branch information
pfeodrippe committed Jan 29, 2025
1 parent dbe6c1b commit bfbc2fd
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- main
# - develop
- develop
paths-ignore:
- '**/README.md'
- '**/CHANGELOG.md'
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Now it's working fine with the `vybe-games` builds
- Create `vc/eval*` to debug standalone forms
- Accept meta `^:void` in `if`/`cond` expressions to signal to the C compiler that we don't care about the return
- Move animation-node-player to VybeC
- Add `vf/defsystem-c`

## v0.7.469
Expand Down
30 changes: 23 additions & 7 deletions src/vybe/c.clj
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@
(let [{:keys [ret args]} (vp/fn-descriptor->map type)]
(format "%s (*%s)(%s);"
(-adapt-type (:schema ret))
(name k)
(->name k)
(->> (mapv (fn [{:keys [symbol schema]}]
(str (-adapt-type schema) " " (->name symbol)))
args)
Expand All @@ -277,7 +277,7 @@
(comp->c vec-type (merge (update opts :level inc)
{:embedded true}))
(-adapt-type vec-type))
(name k)
(->name k)
size))

:else
Expand Down Expand Up @@ -311,7 +311,7 @@
:type type
:component component}
e)))))
" " (name k) ";")))))
" " (->name k) ";")))))
(mapv #(str nesting %))
(str/join "\n"))
(if embedded
Expand All @@ -320,6 +320,7 @@
(if embedded
""
(str " " c-name ";"))))))
#_ (println (comp->c vybe.jolt/VyBody))
#_ (println (comp->c vybe.flecs/system_desc_t))
#_ (println (comp->c VybeAllocator))
#_ (println (comp->c Unit))
Expand Down Expand Up @@ -1203,9 +1204,11 @@ signal(SIGSEGV, sighandler);
(tap> {:label "Error when transpiling to C"
:error error-map})

(let [{:keys [file line column]} (:metadata (ex-data e))]
(throw (clojure.lang.Compiler$CompilerException. file line column e))
#_(throw (ex-info "Error when transpiling to C" error-map)))))))
(try
(let [{:keys [file line column]} (:metadata (ex-data e))]
(throw (clojure.lang.Compiler$CompilerException. file line column e)))
(catch Exception _e
(throw (ex-info "Error when transpiling to C" error-map))))))))

(defn- adapt-schema
[schema]
Expand Down Expand Up @@ -1463,7 +1466,7 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i
([code-form {:keys [sym-meta sym sym-name] :as opts}]
(let [{:keys [c-code ::c-data form-hash final-form init-struct-val]}
(-> code-form
(transpile (assoc opts ::version 52)))
(transpile (assoc opts ::version 53)))

obj-name (str "vybe_" sym-name "_"
(when (or (:no-cache sym-meta)
Expand Down Expand Up @@ -1991,6 +1994,19 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i
[{:keys [form]}]
(eval form))
(defn cast*
"Cast a struct into another. Does nothing in the JVM."
[v c]
v)
(defmethod c-macroexpand #'cast*
[{:keys [args]}]
`(let [v# ~(first args)]
(-> v#
vp/&
(vp/as [:* ~(second args)])
deref)))
(declare ^:no-ns typeof
^:no-ns typename
#_^:no-ns comptime)
Expand Down
7 changes: 7 additions & 0 deletions src/vybe/flecs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2346,9 +2346,16 @@
(if (map? binding-form)
;; Map destructuring.
(vec (concat [res-internal-sym form]
;; :keys destructuring
(->> (:keys binding-form)
(mapcat #(vector %
(list (keyword %)
`(deref
~res-internal-sym)))))
;; {aabb-min :min aabb-max :max} destructuring
(->> (dissoc binding-form :keys)
(mapcat #(vector (first %)
(list (keyword (second %))
`(deref
~res-internal-sym)))))))
;; No destructuring.
Expand Down
123 changes: 63 additions & 60 deletions src/vybe/game/system.clj
Original file line number Diff line number Diff line change
Expand Up @@ -212,45 +212,45 @@
t))
(keys p1))))))

(vf/defsystem animation-node-player w
[[_ node] [:vg.anim/target-node :*]
_ [:vg.anim/target-component '?c]
{:keys [id]} [:src '?c vf/VybeComponentId]
node-ref vf/Ref
{:keys [timeline_count values timeline]} vt/AnimationChannel
player [:meta {:flags #{:up :cascade}
:inout :mut}
vt/AnimationPlayer]
parent-e [:vf/entity {:flags #{:up}} :vg.anim/active]
_ [:not {:flags #{:up}} :vg.anim/stop]]
#_(println :c c)

#_(def aaa )
(let [c (vp/comp-cache id)
values (vp/arr values timeline_count c)
timeline (vp/arr timeline timeline_count :float)
idx* (first (indices #(>= % (:current_time player)) timeline))
idx (max (dec (or idx* (count timeline))) 0)
t (when idx*
(/ (- (:current_time player)
(nth timeline idx))
(- (nth timeline (inc idx))
(nth timeline idx))))]

(when-not idx*
(conj parent-e :vg.anim/stop)
;; Just for triggering the `animation-loop` system.
(conj (vf/ent w node) :vg.anim.entity/stop))

;; We modify the component from the ref and then we have to notify flecs
;; that it was modified.
(merge @node-ref (if t
(lerp-p (nth values idx)
(nth values (inc idx))
t)
(nth values idx)))

(vf/modified! w node c)))
#_(vf/defsystem animation-node-player w
[[_ node] [:vg.anim/target-node :*]
_ [:vg.anim/target-component '?c]
{:keys [id]} [:src '?c vf/VybeComponentId]
node-ref vf/Ref
{:keys [timeline_count values timeline]} vt/AnimationChannel
player [:meta {:flags #{:up :cascade}
:inout :mut}
vt/AnimationPlayer]
parent-e [:vf/entity {:flags #{:up}} :vg.anim/active]
_ [:not {:flags #{:up}} :vg.anim/stop]]
#_(println :c c)

#_(def aaa )
(let [c (vp/comp-cache id)
values (vp/arr values timeline_count c)
timeline (vp/arr timeline timeline_count :float)
idx* (first (indices #(>= % (:current_time player)) timeline))
idx (max (dec (or idx* (count timeline))) 0)
t (when idx*
(/ (- (:current_time player)
(nth timeline idx))
(- (nth timeline (inc idx))
(nth timeline idx))))]

(when-not idx*
(conj parent-e :vg.anim/stop)
;; Just for triggering the `animation-loop` system.
(conj (vf/ent w node) :vg.anim.entity/stop))

;; We modify the component from the ref and then we have to notify flecs
;; that it was modified.
(merge @node-ref (if t
(lerp-p (nth values idx)
(nth values (inc idx))
t)
(nth values idx)))

(vf/modified! w node c)))

;; TODO We could also c-macroexpand/c-invoke from a protocol.
(defmethod vc/c-macroexpand #'conj
Expand All @@ -264,11 +264,13 @@
c)))
nil))

(vf/defsystem-c animation-node-player-2 w
(vf/defsystem-c animation-node-player w
[[_ node] [:vg.anim/target-node '?node]
;; TODO We could have some sugar to get multiple components from the same entity.
translation [:src '?node vt/Translation]
scale [:src '?node vt/Scale]
rotation [:src '?node vt/Rotation]

[_ c] [:vg.anim/target-component '?c]
{:keys [kind timeline_count values timeline]} vt/AnimationChannel
player [:meta {:flags #{:up :cascade}
Expand All @@ -280,14 +282,9 @@
;; TODO OPTM We could also leverage the previous index.
idx* (vc/bs_lower_bound timeline* timeline_count (:current_time @player))
idx (cond
(= idx* 0)
0

(>= idx* timeline_count)
-1

:else
(dec idx*))]
(= idx* 0) 0
(>= idx* timeline_count) -1
:else (dec idx*))]

(if (>= idx 0)
(let [v (/ (- (:current_time @player)
Expand All @@ -299,22 +296,28 @@
^:void
(cond
(= kind 0)
(merge @translation
(nth (vp/arr values timeline_count vt/Translation) idx))
(let [arr (vp/arr values timeline_count vt/Translation)]
(merge @translation
(-> (vr.c/vector-3-lerp (-> (nth arr idx) (vc/cast* vt/Vector3))
(-> (nth arr (inc idx)) (vc/cast* vt/Vector3))
v)
(vc/cast* vt/Translation))))

(= kind 1)
(merge @scale
(nth (vp/arr values timeline_count vt/Scale) idx))
(let [arr (vp/arr values timeline_count vt/Scale)]
(merge @scale
(-> (vr.c/vector-3-lerp (-> (nth arr idx) (vc/cast* vt/Vector3))
(-> (nth arr (inc idx)) (vc/cast* vt/Vector3))
v)
(vc/cast* vt/Scale))))

(= kind 2)
(merge @rotation
(nth (vp/arr values timeline_count vt/Rotation) idx)))

#_(merge @node-ref (if t
(lerp-p (nth values idx)
(nth values (inc idx))
t)
(nth values idx)))
(let [arr (vp/arr values timeline_count vt/Rotation)]
(merge @rotation
(-> (vr.c/quaternion-slerp (-> (nth arr idx) (vc/cast* vt/Vector4))
(-> (nth arr (inc idx)) (vc/cast* vt/Vector4))
v)
(vc/cast* vt/Rotation)))))

;; We modify the component from the ref and then we have to notify flecs
;; that it was modified.
Expand Down
4 changes: 2 additions & 2 deletions test/vybe/flecs_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
(vg.s/vybe-transform w)

(testing "system builders can be called over and over if they don't change"
(= (vf/eid (vg.s/animation-node-player-2 w))
(vf/eid (vg.s/animation-node-player-2 w))))
(= (vf/eid (vg.s/animation-node-player w))
(vf/eid (vg.s/animation-node-player w))))

(merge w {:alice [(vt/Scale [1.0 1.0 1.0]) (vt/Translation)
(vt/Rotation [0 0 0 1]) [(vt/Transform) :global] (vt/Transform)
Expand Down
33 changes: 17 additions & 16 deletions todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@
- [x] macro to quickly evaluate stuff
- [-] REPL plugin like portal does for cljs?
- [x] https://github.com/pfeodrippe/vybe/issues/4
- [ ] try to VybeC animation-node-player
- [x] try to VybeC animation-node-player
- [x] don't use `-field` for non components
- [x] make vector destructuring work
- [x] get entity corresponding to the position
Expand All @@ -282,7 +282,7 @@
- [x] don't bind `_.*`
- [x] scoped :vf/entity
- [x] tap
- [ ] body of the orignal CLJ function
- [x] body of the orignal CLJ function
- [x] accept 3-arity version of `vp/arr`
- [x] do we have a way to get the component dynamically?
- lerp later
Expand All @@ -308,20 +308,12 @@
- [-] create cond automatically from it?
- [x] fix `idx`
- [x] fix `t`
- [ ] lerp
- [ ] just idx for translation
- [ ] scale
- [ ] rotation
- [ ] use lerp
- [ ] :vf/entity should return a struct?
- [ ] consider making systems `always` by default
- [ ] `def` to a var from C?
- [x] show line/column error correctly for an error before calling the compiler
- [ ] Remove variables starting with a `_` in a `let` (just do the side-effect)
- [ ] optimization (-O3)?
- [ ] how to represent `nil` properly?
- [ ] maybe with nullable
- [ ] should have slices? (support for `count`, `first`, `last`, `nth`, iteration)
- [x] lerp
- [x] just idx for translation
- [x] scale
- [x] rotation
- [x] use lerp
- [ ] move `update-physics` system
- [ ] built-in models
- [x] minimal
- [ ] more complex
Expand Down Expand Up @@ -450,6 +442,7 @@
- [ ] flecs system
- [ ] tap from C into portal
- [ ] VybeC
- [x] show line/column error correctly for an error before calling the compiler
- [ ] better way to jump to definition
- [ ] allocator setting
- [ ] comptime
Expand All @@ -461,6 +454,14 @@
- [ ] make `@, vp/&` etc better
- [ ] create a merge or reset! "protocol" leveraging C generics
- [ ] make recompilation work with an indirection?
- [ ] :vf/entity should return a struct?
- [ ] consider making systems `always` by default
- [ ] `def` to a var from C?
- [ ] Remove variables starting with a `_` in a `let` (just do the side-effect)
- [ ] optimization (-O3)?
- [ ] how to represent `nil` properly?
- [ ] maybe with nullable
- [ ] should have slices? (support for `count`, `first`, `last`, `nth`, iteration)
- [ ] make it easy to DSP in the frequency domain
- [ ] create filters in realtime from clerk
- [ ] wasm
Expand Down

0 comments on commit bfbc2fd

Please sign in to comment.