From 6f3948d62e6ee1da7b5fb50a1d73db0ad54ce0ca Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 29 Aug 2026 18:24:59 +0700 Subject: [PATCH] Drag LMB to select tiles, draw bottom bar, wip file picker --- src/game.clj | 1 - src/sprite_atlas.clj | 138 ++++++++++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/game.clj b/src/game.clj index b841c40..8f6719d 100644 --- a/src/game.clj +++ b/src/game.clj @@ -287,7 +287,6 @@ (reset! e/game-state (init-game {})) (swap! e/game-state :assoc {}) - hello (:tilemaps @e/game-state) :-) diff --git a/src/sprite_atlas.clj b/src/sprite_atlas.clj index f1489c8..7ade459 100644 --- a/src/sprite_atlas.clj +++ b/src/sprite_atlas.clj @@ -5,32 +5,56 @@ [clojure.java.io :as io] [engine :as e] [rl :as rl] - [watch :as w])) + [watch :as w]) + (:import (java.awt FileDialog Frame))) -(def ^:const screen-width 1280) -(def ^:const screen-height 630) +(def screen-width 1280) +(def screen-height 630) +;; (def screen-width 960) +;; (def screen-height 490) +(def cell-size 16) (defn sprite-atlas-path [] (let [asset-path "./source-assets/Sprout Lands Premium/" level-deco "Objects/Mushrooms, Flowers, Stones.png"] (str asset-path level-deco))) -(defn init-sprite-atlas [config] - {:zoom 1 - :atlas (e/load-texture-once :main-atlas (sprite-atlas-path)) - :atlas-pos [0 0] - :drag-delta [0 0]}) +(defn zoom-to-fit [{:keys [width height]}] + (min (/ screen-width (double width)) + (/ screen-height (double height)))) -(defn- auto-tile [game cell-size cell-count] - (assoc game :auto-tile-info {:cell-size 16 :cell-count 11})) +(defn init-sprite-atlas [config] + (let [atlas (e/load-texture-once :main-atlas (sprite-atlas-path))] + {:zoom (zoom-to-fit atlas) + :selected-cells #{} + :atlas atlas + :atlas-pos [0 0] + :drag-delta [0 0]})) (defn handle-input [_ game] (update-as-> [g game] (when (rl/key-pressed? rl/key-r) (assoc g :atlas-pos [0 0])) + ;; TODO: We want to add auto sprite sheet gen, so first detect non-empty, and we populate with that + ;; then we have a selection box that allows grouping + (when (rl/key-pressed? rl/key-enter) + (let [d (doto (FileDialog. (Frame.) "Open" FileDialog/LOAD) + ;; TODO: Maybe add a check if the directory exists? + (.setDirectory (str (System/getProperty "user.dir") "/assets")) + (.setVisible true))] + (when-let [f (.getFile d)] + (println (str (.getDirectory d) f))) + game) + #_(this should be to write the sprite sheet to some path)) + (when (rl/key-pressed? rl/key-zero) + (assoc g :zoom (zoom-to-fit (:atlas g)))) (when (rl/mouse-button-pressed? rl/mouse-button-left) - (assoc g :drag-start-pos (rl/get-mouse-position) :drag-mode :zooming)) + (assoc g + :drag-start-pos (rl/get-mouse-position) + :current-mouse-pos (rl/get-mouse-position) + :drag-mode :selecting + :selected-cells #{})) (when (rl/mouse-button-released? rl/mouse-button-left) (-> g (assoc :selected-sprite (get-selection-rect (:drag-start-pos g) (:current-mouse-pos g))) @@ -64,41 +88,70 @@ (handle-input {} g) (when (contains? g :drag-start-pos) (case (:drag-mode g) - :zooming (assoc g :current-mouse-pos (rl/get-mouse-position)) + :selecting (assoc g + :current-mouse-pos (rl/get-mouse-position) + ;; TODO: I have to fix this algorith, I'm pretty sure there's a way to make it O(1) + :selected-cells + (let [zoom (:zoom g) + {:keys [drag-start-pos current-mouse-pos atlas-pos]} g + {dsp-x :x dsp-y :y} drag-start-pos + {mx :x my :y} current-mouse-pos + [ax ay] atlas-pos + x0 (- (min dsp-x mx) ax) + y0 (- (min dsp-y my) ay) + x1 (- (max dsp-x mx) ax) + y1 (- (max dsp-y my) ay) + curr-cell-size (* cell-size zoom) + start-row (quot y0 curr-cell-size) + start-col (quot x0 curr-cell-size) + start-x (* start-col curr-cell-size) + start-y (* start-row curr-cell-size) + w (+ (- x0 start-x) (- x1 x0)) + h (+ (- y0 start-y) (- y1 y0)) + row-count (inc (quot h curr-cell-size)) + col-count (inc (quot w curr-cell-size))] + (w/spy :info [row-count col-count]) + (when (> (* w h) 256) + (set (for [r (range row-count) + c (range col-count)] + [(+ start-row r) (+ start-col c)]))))) + :dragging (assoc g :drag-delta (let [{mx :x my :y} (rl/get-mouse-position) {:keys [x y]} (:drag-start-pos g)] [(- mx x) (- my y)])))))) -(swap! e/game-state assoc :atlas-pos [0 0]) -(defn draw-sprite-atlas [_ {:keys [atlas atlas-pos drag-delta zoom drag-start current-mouse-pos selected-sprite auto-tile-info]}] +(defn draw-sprite-atlas [_ {:keys [atlas atlas-pos drag-delta zoom drag-mode drag-start-pos current-mouse-pos selected-cells]}] (rl/clear-background!* rl/black) - (let [current-scale (* (/ screen-height (:height atlas)) (max 0.1 (* zoom 0.1))) - [ax ay] atlas-pos + (let [[ax ay] atlas-pos [dx dy] (or drag-delta [0 0]) ax (+ ax dx) - ay (+ ay dy)] + ay (+ ay dy) + curr-cell-size (* cell-size zoom)] (when atlas (let [] - (rl/draw-texture-ex!* (:seg atlas) (rl/vec2-seg ax ay) 0.0 current-scale rl/white)) - (when drag-start - (let [start-x (:x drag-start) - start-y (:y drag-start) + (rl/draw-texture-ex!* (:seg atlas) (rl/vec2-seg ax ay) 0.0 zoom rl/white)) + (when (= :selecting drag-mode) + (let [start-x (:x drag-start-pos) + start-y (:y drag-start-pos) end-x (:x current-mouse-pos) end-y (:y current-mouse-pos)] (rl/draw-rectangle-lines!* start-x start-y (- end-x start-x) (- end-y start-y) rl/white))) #_(when selected-sprite - (let [{:keys [x y w h]} selected-sprite] - (rl/draw-texture-rec!* (:seg atlas) (rl/rect-seg x y w h) (rl/vec2-seg 30 30) rl/white))) - (let [cell-size 16 - rows 11 - cols 12] + (let [{:keys [x y w h]} selected-sprite] + (rl/draw-texture-rec!* (:seg atlas) (rl/rect-seg x y w h) (rl/vec2-seg 30 30) rl/white))) + (let [rows (quot (:height atlas) cell-size) + cols (quot (:width atlas) cell-size)] (doseq [row (range rows) col (range cols)] - (rl/draw-rectangle-lines!* (+ ax (* col cell-size current-scale)) - (+ ay (* row cell-size current-scale)) - (* cell-size current-scale) - (* cell-size current-scale) - rl/gray))))) + (rl/draw-rectangle-lines!* (+ ax (* col curr-cell-size)) + (+ ay (* row curr-cell-size)) + curr-cell-size + curr-cell-size + rl/gray))) + (doseq [[row col] selected-cells] + (rl/draw-rectangle-lines!* (+ ax (* col curr-cell-size)) (+ ay (* row curr-cell-size)) + (* cell-size zoom) (* cell-size zoom) + rl/white)))) (let [font-size 28 width (quot screen-width 2) height 30 @@ -110,26 +163,29 @@ (rl/draw-text!* (format "Y: %d" (int my)) (+ x 150) y font-size rl/black))) (defn watch-sprite-atlas [config game] - {:zoom (:zoom game) + {#_#_:zoom (:zoom game) + :selected-cells (:selected-cells game) + :mouse-pos (:current-mouse-pos game) :atlas-pos (:atlas-pos game) - :drag-delta (:drag-delta game)}) + #_#_:drag-delta (:drag-delta game)}) (defn unload-sprite-atlas [game] (rl/unload-texture! (:atlas game))) (defn -main [& _args] (engine/run-game! - {:title "Sprite Atlas" - :width screen-width - :height screen-height - :init #'init-sprite-atlas - :update #'update-sprite-atlas - :draw #'draw-sprite-atlas - :unload #'unload-sprite-atlas - :watch-fn #'watch-sprite-atlas})) + {:title "Sprite Atlas" + :width screen-width + :height screen-height + :init #'init-sprite-atlas + :update #'update-sprite-atlas + :draw #'draw-sprite-atlas + :unload #'unload-sprite-atlas + :watch-fn #'watch-sprite-atlas})) (comment (future (-main)) (reset! e/game-state (init-sprite-atlas {})) (rl/set-clipboard-text!* "foo bar") + (swap! e/game-state assoc :atlas-pos [0 0]) :-)