Implement more flexible state management
This commit is contained in:
parent
81964a0d73
commit
850ef80139
3
deps.edn
3
deps.edn
@ -1,5 +1,6 @@
|
||||
{:deps {org.clojure/clojure {:mvn/version "1.9.0"}
|
||||
org.clojure/clojurescript {:mvn/version "1.10.520"}}
|
||||
org.clojure/clojurescript {:mvn/version "1.10.520"}
|
||||
binaryage/oops {:mvn/version "0.7.0"}}
|
||||
:paths ["src" "resources"]
|
||||
:aliases {:fig {:extra-deps
|
||||
{com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
|
||||
|
@ -1,6 +1,8 @@
|
||||
(ns ^:figwheel-hooks three-playground.core
|
||||
(:require
|
||||
[goog.dom :as gdom]
|
||||
[goog.object :as obj]
|
||||
[oops.core :refer [oset!+]]
|
||||
[three]))
|
||||
|
||||
(defn get-app-element []
|
||||
@ -24,31 +26,53 @@
|
||||
(.setSize renderer (.-innerWidth js/window) (.-innerHeight js/window))
|
||||
(.add scene cube)
|
||||
(atom {:running true
|
||||
:cube {:rotation {:x 0 :y 0}}
|
||||
:renderer renderer
|
||||
:scene scene
|
||||
:camera {:position {:z 5}}
|
||||
:entities {:cube cube
|
||||
:entity-state {:cube {:rotation {:x 0 :y 0}}
|
||||
:camera {:position {:z 5}}}
|
||||
:entities {:scene scene
|
||||
:cube cube
|
||||
:camera camera}})))
|
||||
|
||||
(defonce app-state (init-state))
|
||||
|
||||
(defn update-state [state]
|
||||
(-> state
|
||||
(assoc-in [:cube :rotation :x]
|
||||
(+ (get-in state [:cube :rotation :x])
|
||||
0.01))
|
||||
(assoc-in [:cube :rotation :y]
|
||||
(+ (get-in state [:cube :rotation :y])
|
||||
(assoc-in [:entity-state :cube :rotation :x]
|
||||
(+ (get-in state [:entity-state :cube :rotation :x])
|
||||
0.03))
|
||||
(assoc-in [:entity-state :cube :rotation :y]
|
||||
(+ (get-in state [:entity-state :cube :rotation :y])
|
||||
0.01))))
|
||||
|
||||
(defn map->paths [m]
|
||||
(if (map? m)
|
||||
(vec
|
||||
(mapcat (fn [[k v]]
|
||||
(let [sub (map->paths v)
|
||||
nested (map #(into [k] %) (filter (comp not empty?) sub))]
|
||||
(if (seq nested)
|
||||
nested
|
||||
[[k]])))
|
||||
m))
|
||||
[]))
|
||||
|
||||
(defn update-entities! [state]
|
||||
(doseq [[id entity] (:entities state)]
|
||||
(let [target-state (get-in state [:entity-state id])]
|
||||
(when target-state
|
||||
(doseq [path (map->paths target-state)]
|
||||
(let [str-path (map name path)
|
||||
current (apply aget entity str-path)
|
||||
new (get-in target-state path)]
|
||||
(when-not (= current new)
|
||||
(oset!+ entity str-path new))))))))
|
||||
|
||||
(defn render [state]
|
||||
(let [{:keys [renderer scene]} state
|
||||
(let [renderer (:renderer state)
|
||||
scene (get-in state [:entities :scene])
|
||||
camera (get-in state [:entities :camera])
|
||||
cube (get-in state [:entities :cube])]
|
||||
(set! (-> camera (.-position) (.-z)) (get-in state [:camera :position :z]))
|
||||
(set! (-> cube (.-rotation) (.-x)) (get-in state [:cube :rotation :x]))
|
||||
(set! (-> cube (.-rotation) (.-y)) (get-in state [:cube :rotation :y]))
|
||||
(update-entities! state)
|
||||
(.render renderer scene camera)))
|
||||
|
||||
(defn the-loop []
|
||||
|
@ -1 +1,8 @@
|
||||
(ns three-playground.core-test)
|
||||
(ns three-playground.core-test
|
||||
(:require [cljs.test :refer-macros [deftest testing is]]
|
||||
[three-playground.core :as core]))
|
||||
|
||||
(deftest test-map->paths
|
||||
(testing "Basic case"
|
||||
(is (= (core/map->paths {:foo {:bar 1 :baz 2} :qux 3})
|
||||
[[:foo :bar] [:foo :baz] [:qux]]))))
|
||||
|
Loading…
Reference in New Issue
Block a user