From bf0d312388d76a64099715315e46fcc303866a8c Mon Sep 17 00:00:00 2001 From: Paulo Feodrippe Date: Sun, 26 Jan 2025 23:54:20 -0500 Subject: [PATCH] wip --- src/vybe/c.clj | 9 ++++- src/vybe/flecs.clj | 83 ++++++++++++++++++++-------------------- src/vybe/game.clj | 13 ++++--- src/vybe/game/system.clj | 19 +++++---- src/vybe/panama.clj | 5 --- src/vybe/type.clj | 3 +- todo.md | 11 +++++- 7 files changed, 80 insertions(+), 63 deletions(-) diff --git a/src/vybe/c.clj b/src/vybe/c.clj index fc83341..5d6b1e6 100644 --- a/src/vybe/c.clj +++ b/src/vybe/c.clj @@ -1146,7 +1146,10 @@ signal(SIGSEGV, sighandler); (throw (ex-info (str "Unhandled: " (:op v)) {:op (:op v) :raw-forms (:raw-forms v) + :metadata (select-keys (:env v) [:line :column :file]) :form (:form v)}))))))) + (catch clojure.lang.Compiler$CompilerException e + (throw e)) (catch Exception e (when (::transpiler-error? (ex-data e)) (throw e)) @@ -1155,6 +1158,7 @@ signal(SIGSEGV, sighandler); :transpilation *transpilation* :raw-forms (:raw-forms v) :form (:form v) + :metadata (:metadata v) ::transpiler-error? true :exception e} (ex-data e) @@ -1166,7 +1170,10 @@ signal(SIGSEGV, sighandler); (pp/pprint error-map)))) (tap> {:label "Error when transpiling to C" :error error-map}) - (throw (ex-info "Error when transpiling to C" 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))))))) (defn- adapt-schema [schema] diff --git a/src/vybe/flecs.clj b/src/vybe/flecs.clj index 49b6c9b..b27bce8 100644 --- a/src/vybe/flecs.clj +++ b/src/vybe/flecs.clj @@ -2318,47 +2318,48 @@ {:private true})) :- :void [~it :- [:* vf/iter_t]] - (let [~w (:world @~it) - ~c-w ~w] - (let ~ (->> bindings-processed - (apply concat) - vec) - (doseq [~i (range (:count @~it))] - (let ~ (->> bindings-processed - (mapv (fn [k-and-v] - (let [{:keys [sym flags binding-form type idx]} (meta k-and-v) - [k _v] k-and-v - ;; If we are up, it means we are self. - ;; TODO Use `is-self` so we can cover up - ;; all the possibilities (e.g. Prefabs). - i (if (or (contains? flags :up) - (contains? flags :src)) - 0 - i)] - (if type - ;; Component branch. - (let [form (if (contains? flags :maybe) - `(if (= ~k vp/null) - (vp/as vp/null [:* ~type]) - (vp/& (nth ~k ~i))) - `(vp/& (nth ~k ~i))) - res-internal-sym (symbol (str "res-internal--" idx))] - (if (map? binding-form) - ;; Map destructuring. - (vec (concat [res-internal-sym form] - (->> (:keys binding-form) - (mapcat #(vector % - (list (keyword %) - `(deref - ~res-internal-sym))))))) - ;; No destructuring. - [sym form])) - ;; Not a component branch. - ;; TODO support `:maybe` - [sym k])))) - (apply concat) - vec) - ~@body))))) + ~(-> `(let [~w (:world @~it) + ~c-w ~w] + (let ~ (->> bindings-processed + (apply concat) + vec) + (doseq [~i (range (:count @~it))] + (let ~ (->> bindings-processed + (mapv (fn [k-and-v] + (let [{:keys [sym flags binding-form type idx]} (meta k-and-v) + [k _v] k-and-v + ;; If we are up, it means we are self. + ;; TODO Use `is-self` so we can cover up + ;; all the possibilities (e.g. Prefabs). + i (if (or (contains? flags :up) + (contains? flags :src)) + 0 + i)] + (if type + ;; Component branch. + (let [form (if (contains? flags :maybe) + `(if (= ~k vp/null) + (vp/as vp/null [:* ~type]) + (vp/& (nth ~k ~i))) + `(vp/& (nth ~k ~i))) + res-internal-sym (symbol (str "res-internal--" idx))] + (if (map? binding-form) + ;; Map destructuring. + (vec (concat [res-internal-sym form] + (->> (:keys binding-form) + (mapcat #(vector % + (list (keyword %) + `(deref + ~res-internal-sym))))))) + ;; No destructuring. + [sym form])) + ;; Not a component branch. + ;; TODO support `:maybe` + [sym k])))) + (apply concat) + vec) + ~@body)))) + (with-meta (meta &form)))) ;; Defined system builder. (defn ~sys-name diff --git a/src/vybe/game.clj b/src/vybe/game.clj index 4f415fa..2e4d3d3 100644 --- a/src/vybe/game.clj +++ b/src/vybe/game.clj @@ -885,9 +885,8 @@ target-component (case (:path target) "translation" vt/Translation "scale" vt/Scale - "rotation" vt/Rotation) - sym (vf/lookup-symbol w (node->sym (:node target)))] - (when (nil? sym) + "rotation" vt/Rotation)] + (when (nil? target-node) (throw (ex-info "Lookup symbol shouldn't be `nil`" {:node node :node-target (:node target) @@ -895,7 +894,11 @@ {(vf/_) [:vg/channel (vt/AnimationChannel - {:timeline (-> (get accessors input) + {:kind ({vt/Translation 0 + vt/Scale 1 + vt/Rotation 2} + target-component) + :timeline (-> (get accessors input) (-gltf-accessor->data buffer-0 bufferViews) (vp/arr :float)) :values (-> (get accessors output) @@ -903,7 +906,7 @@ vp/arr)}) [:vg.anim/target-node target-node] [:vg.anim/target-component target-component] - (vf/ref w sym target-component)]}))))) + (vf/ref w target-node target-component)]}))))) vec)] (when (seq processed-channels) {(keyword "vg.gltf.anim" name) diff --git a/src/vybe/game/system.clj b/src/vybe/game/system.clj index c12eb4c..31de72e 100644 --- a/src/vybe/game/system.clj +++ b/src/vybe/game/system.clj @@ -214,7 +214,8 @@ (vf/defsystem animation-node-player w [[_ node] [:vg.anim/target-node :*] - [_ c] [:vg.anim/target-component :*] + _ [: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} @@ -223,7 +224,10 @@ parent-e [:vf/entity {:flags #{:up}} :vg.anim/active] _ [:not {:flags #{:up}} :vg.anim/stop]] #_(println :c c) - (let [values (vp/arr values timeline_count 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) @@ -265,10 +269,11 @@ (vf/defsystem-c animation-node-player-2 _w [[_ node] [:vg.anim/target-node :*] + ;; TODO Maybe [:vg.anim/target-component [:vf/component'?c]] ? _ [:vg.anim/target-component '?c] {:keys [id]} [:src '?c vf/VybeComponentId] node-ref vf/Ref - {:keys [timeline_count values timeline]} vt/AnimationChannel + {:keys [kind timeline_count values timeline]} vt/AnimationChannel player [:meta {:flags #{:up :cascade} :inout :mut} vt/AnimationPlayer] @@ -279,7 +284,7 @@ (vp/arr values timeline_count vt/Translation) (vp/arr values timeline_count vt/Scale)) (vp/as [:* :void])) - ;; TODO Should this create a slice? (support for `count`, `first`, `last`, iteration) + ;; TODO Should this create a slice? (support for `count`, `first`, `last`, `nth`, iteration) timeline* (vp/arr timeline timeline_count :float) ;; TODO Fix (first timeline*) idx* (first timeline*) #_(first (indices #(>= % (:current_time player)) timeline)) @@ -291,9 +296,8 @@ (nth timeline* idx)) (- (nth timeline* (inc idx)) (nth timeline* idx))))] - #_(tap> t) - (when (< idx* 0) + #_(when (< idx* 0) (conj parent-e :vg.anim/stop) ;; Just for triggering the `animation-loop` system. @@ -304,8 +308,7 @@ ;; TODO Using `comp-id` is not great as the ID may change ;; after restart. #_(when (= id (vc/comptime (vp/comp-id vt/Translation))) - (tap> (nth (vp/arr values timeline_count vt/Translation) idx))) - + (tap> (nth (vp/arr values timeline_count vt/Translation) idx))) ;; We modify the component from the ref and then we have to notify flecs ;; that it was modified. diff --git a/src/vybe/panama.clj b/src/vybe/panama.clj index f732edf..fb890d4 100644 --- a/src/vybe/panama.clj +++ b/src/vybe/panama.clj @@ -1499,11 +1499,6 @@ [v] (get @*components-cache v)) -(defn comp-id - "Get the id of a component." - [c] - (get @*components-cache c)) - (defmacro defcomp "Creates a component, e.g. diff --git a/src/vybe/type.clj b/src/vybe/type.clj index 8524d7f..6c0211d 100644 --- a/src/vybe/type.clj +++ b/src/vybe/type.clj @@ -150,7 +150,8 @@ (if (:timeline_count v) v (assoc v :timeline_count (count (:timeline v)))))} - [[:timeline_count :long] + [[:kind :long] + [:timeline_count :long] [:values :pointer] [:timeline :pointer]]) diff --git a/todo.md b/todo.md index dca5b1e..68ff324 100644 --- a/todo.md +++ b/todo.md @@ -288,18 +288,25 @@ - lerp later - [x] `parent-e` conj - https://stackoverflow.com/questions/66040677/implementing-basic-vtable-in-c + - https://www.reddit.com/r/ProgrammingLanguages/comments/fpnooj/tradeoffs_of_fat_vs_thin_pointers/ + - https://stackoverflow.com/questions/57754901/what-is-a-fat-pointer + - https://www.reddit.com/r/Zig/comments/13w2cvf/rust_trait_equivalent_in_zig/ - [x] get id from keyword - we can't use a global definition like `ECS_DECLARE` - but we can define it when adding the system (per world) - [x] simple get by name for now - [x] dispatch conj on type (no inheritance) - [x] when modifying a system, delete it first + - [ ] fix `(first timeline*)` + - [ ] need to make some smarter mapping for the timeline + - https://lisyarus.github.io/blog/posts/gltf-animation.html + - [ ] binary search + - [ ] current index + falling back to binary search - [ ] check which component `c` we are dealing with - [x] mapping from entity id to component type + - [x] don't use `comp-id` - [ ] create cond automatically from it? - - [ ] fix `(first timeline*)` - [ ] how to represent `nil` properly? - - [ ] consider vtable or fat pointers for dynamic dispatch - [ ] lerp - [ ] :vf/entity should return a struct? - [ ] consider making systems `always` by default