diff --git a/deploy_docs b/deploy_docs new file mode 100755 index 0000000..c1bf7a7 --- /dev/null +++ b/deploy_docs @@ -0,0 +1,11 @@ +set -e + +git checkout gh-pages +git merge main --commit +lein codox +rm -rf docs +mv target/doc docs +git add docs +git commit -m 'Update docs' +git push +git checkout main diff --git a/src/gdl/app.clj b/src/gdl/app.clj index 834dfba..0ce19e3 100644 --- a/src/gdl/app.clj +++ b/src/gdl/app.clj @@ -2,40 +2,141 @@ (:require [clojure.string :as str] [x.x :refer [defcomponent update-map]] [gdl.lc :as lc] + [gdl.draw :as draw] [gdl.graphics.viewport :as viewport] - [gdl.graphics.shape-drawer :as shape-drawer] [gdl.scene2d.ui :as ui]) (:import (com.badlogic.gdx Gdx ApplicationAdapter) com.badlogic.gdx.audio.Sound com.badlogic.gdx.assets.AssetManager com.badlogic.gdx.files.FileHandle - com.badlogic.gdx.utils.ScreenUtils - (com.badlogic.gdx.graphics Color Texture OrthographicCamera) - com.badlogic.gdx.graphics.g2d.SpriteBatch + (com.badlogic.gdx.utils Align ScreenUtils) + (com.badlogic.gdx.graphics Color Texture OrthographicCamera Pixmap Pixmap$Format) + (com.badlogic.gdx.graphics.g2d Batch SpriteBatch BitmapFont TextureRegion) (com.badlogic.gdx.backends.lwjgl3 Lwjgl3Application Lwjgl3ApplicationConfiguration) com.badlogic.gdx.utils.SharedLibraryLoader - (com.badlogic.gdx.utils.viewport Viewport FitViewport))) + (com.badlogic.gdx.utils.viewport Viewport FitViewport) + space.earlygrey.shapedrawer.ShapeDrawer)) -(defn render-with [{:keys [^SpriteBatch batch +(defn- degree->radians [degree] + (* degree (/ (Math/PI) 180))) + +(defn- text-height [^BitmapFont font text] + (-> text + (str/split #"\n") + count + (* (.getLineHeight font)))) + +(defn- draw-texture [^Batch batch texture [x y] [w h] rotation color] + (if color (.setColor batch color)) + (.draw batch texture + x + y + (/ w 2) ; rotation origin + (/ h 2) + w ; width height + h + 1 ; scaling factor + 1 + rotation) + (if color (.setColor batch Color/WHITE))) + +(defn- unit-dimensions [unit-scale image] + (if (= unit-scale 1) + (:pixel-dimensions image) + (:world-unit-dimensions image))) + +(defrecord Drawer [batch unit-scale default-font ^ShapeDrawer shape-drawer] + draw/Drawer + (text [_ {:keys [font text x y h-align up?]}] + (let [^BitmapFont font (or font default-font) + data (.getData font) + old-scale (.scaleX data)] + (.setScale data (float (* old-scale unit-scale))) + (.draw font + batch + (str text) + (float x) + (float (+ y (if up? (text-height font text) 0))) + (float 0) ; target-width + (case (or h-align :center) + :center Align/center + :left Align/left + :right Align/right) + false) ; wrap false, no need target-width + (.setScale data (float old-scale)))) + (image [_ {:keys [texture color] :as image} position] + (draw-texture batch texture position (unit-dimensions unit-scale image) 0 color)) + (image [this image x y] + (image this image [x y])) + (rotated-centered-image [_ {:keys [texture color] :as image} rotation [x y]] + (let [[w h] (unit-dimensions unit-scale image)] + (draw-texture batch + texture + [(- x (/ w 2)) + (- y (/ h 2))] + [w h] + rotation + color))) + (centered-image [this image position] + (draw/rotated-centered-image this image 0 position)) + (ellipse [_ [x y] radius-x radius-y color] + (.setColor shape-drawer ^Color color) + (.ellipse shape-drawer (float x) (float y) (float radius-x) (float radius-y)) ) + (filled-ellipse [_ [x y] radius-x radius-y color] + (.setColor shape-drawer ^Color color) + (.filledEllipse shape-drawer (float x) (float y) (float radius-x) (float radius-y))) + (circle [_ [x y] radius color] + (.setColor shape-drawer ^Color color) + (.circle shape-drawer (float x) (float y) (float radius))) + (filled-circle [_ [x y] radius color] + (.setColor shape-drawer ^Color color) + (.filledCircle shape-drawer (float x) (float y) (float radius))) + (arc [_ [centre-x centre-y] radius start-angle degree color] + (.setColor shape-drawer ^Color color) + (.arc shape-drawer centre-x centre-y radius start-angle (degree->radians degree))) + (sector [_ [centre-x centre-y] radius start-angle degree color] + (.setColor shape-drawer ^Color color) + (.sector shape-drawer centre-x centre-y radius start-angle (degree->radians degree))) + (rectangle [_ x y w h color] + (.setColor shape-drawer ^Color color) + (.rectangle shape-drawer x y w h) ) + (filled-rectangle [_ x y w h color] + (.setColor shape-drawer ^Color color) + (.filledRectangle shape-drawer (float x) (float y) (float w) (float h)) ) + (line [_ [x y] [ex ey] color] + (draw/line shape-drawer x y ex ey color)) + (line [_ x y ex ey color] + (.setColor shape-drawer ^Color color) + (.line shape-drawer (float x) (float y) (float ex) (float ey))) + (with-line-width [this width draw-fn] + (let [old-line-width (.getDefaultLineWidth shape-drawer)] + (.setDefaultLineWidth shape-drawer (float (* width old-line-width))) + (draw-fn this) + (.setDefaultLineWidth shape-drawer (float old-line-width))))) + +(defn render-with [{:keys [^Batch batch + shape-drawer gui-camera world-camera world-unit-scale] :as context} gui-or-world - renderfn] + draw-fn] (let [^OrthographicCamera camera (case gui-or-world :gui gui-camera :world world-camera) unit-scale (case gui-or-world :gui 1 - :world world-unit-scale)] - (shape-drawer/set-line-width unit-scale) + :world world-unit-scale) + drawer (-> context + (select-keys [:batch :default-font :shape-drawer]) + (assoc :unit-scale unit-scale) + map->Drawer)] (.setColor batch Color/WHITE) ; fix scene2d.ui.tooltip flickering (.setProjectionMatrix batch (.combined camera)) (.begin batch) - (renderfn (assoc context :unit-scale unit-scale)) - (.end batch) - (shape-drawer/set-line-width 1))) + (draw/with-line-width drawer unit-scale draw-fn) + (.end batch))) (defn- update-viewports [{:keys [gui-viewport world-viewport]} w h] (let [center-camera? true] @@ -55,17 +156,10 @@ (defn- recursively-search-files [folder extensions] (loop [[^FileHandle file & remaining] (.list (.internal Gdx/files folder)) result []] - (cond (nil? file) - result - - (.isDirectory file) - (recur (concat remaining (.list file)) result) - - (extensions (.extension file)) - (recur remaining (conj result (str/replace-first (.path file) folder ""))) - - :else - (recur remaining result)))) + (cond (nil? file) result + (.isDirectory file) (recur (concat remaining (.list file)) result) + (extensions (.extension file)) (recur remaining (conj result (str/replace-first (.path file) folder ""))) + :else (recur remaining result)))) (defn- load-assets [^AssetManager manager folder file-extensions ^Class klass log-load-assets?] (doseq [file (recursively-search-files folder file-extensions)] @@ -94,22 +188,33 @@ (defcomponent :batch batch (lc/dispose [_] - (.dispose ^SpriteBatch batch))) + (.dispose ^Batch batch))) (defcomponent :assets manager (lc/dispose [_] (.dispose ^AssetManager manager))) +(defcomponent :shape-drawer-texture texture + (lc/dispose [_] + (.dispose ^Texture texture))) + (defn- default-components [{:keys [tile-size]}] (let [batch (SpriteBatch.)] (merge {:batch batch - :gdl.graphics.shape-drawer batch :assets (load-all-assets {:folder "resources/" ; TODO these are classpath settings ? :sound-files-extensions #{"wav"} :image-files-extensions #{"png" "bmp"} :log-load-assets? false}) ; this is the gdx default skin - copied from libgdx project, check not included in libgdx jar somewhere? :gdl.scene2d.ui (ui/skin (.internal Gdx/files "scene2d.ui.skin/uiskin.json"))} + (let [texture (let [pixmap (doto (Pixmap. 1 1 Pixmap$Format/RGBA8888) + (.setColor Color/WHITE) + (.drawPixel 0 0)) + texture (Texture. pixmap)] + (.dispose pixmap) + texture)] + {:shape-drawer (ShapeDrawer. batch (TextureRegion. texture 0 0 1 1)) + :shape-drawer-texture texture}) (let [gui-camera (OrthographicCamera.) gui-viewport (FitViewport. (.getWidth Gdx/graphics) (.getHeight Gdx/graphics) diff --git a/src/gdl/draw.clj b/src/gdl/draw.clj new file mode 100644 index 0000000..edf35ec --- /dev/null +++ b/src/gdl/draw.clj @@ -0,0 +1,31 @@ +(ns gdl.draw) + +(defprotocol Drawer + (text [_ {:keys [font text x y h-align up?]}]) + (image [_ image position] + [_ image x y]) + (centered-image [_ image position]) + (rotated-centered-image [_ image rotation position]) + (ellipse [_ position radius-x radius-y color]) + (filled-ellipse [_ position radius-x radius-y color]) + (circle [_ position radius color]) + (filled-circle [_ position radius color]) + (arc [_ center-position radius start-angle degree color]) + (sector [_ center-position radius start-angle degree color]) + (rectangle [_ x y w h color]) + (filled-rectangle [_ x y w h color]) + (line [_ start-position end-position color] + [_ x y ex ey color]) + (with-line-width [_ width draw-fn])) + +(defn grid [drawer leftx bottomy gridw gridh cellw cellh color] + (let [w (* gridw cellw) + h (* gridh cellh) + topy (+ bottomy h) + rightx (+ leftx w)] + (doseq [idx (range (inc gridw)) + :let [linex (+ leftx (* idx cellw))]] + (line drawer linex topy linex bottomy color)) + (doseq [idx (range (inc gridh)) + :let [liney (+ bottomy (* idx cellh))]] + (line drawer leftx liney rightx liney color)))) diff --git a/src/gdl/graphics/font.clj b/src/gdl/graphics/font.clj deleted file mode 100644 index 259d92c..0000000 --- a/src/gdl/graphics/font.clj +++ /dev/null @@ -1,28 +0,0 @@ -(ns gdl.graphics.font - (:require [clojure.string :as str]) - (:import com.badlogic.gdx.utils.Align - com.badlogic.gdx.graphics.g2d.BitmapFont)) - -(defn- text-height [^BitmapFont font text] - (-> text - (str/split #"\n") - count - (* (.getLineHeight font)))) - -(defn draw-text [{:keys [default-font unit-scale batch]} {:keys [font text x y h-align up?]}] - (let [^BitmapFont font (or font default-font) - data (.getData font) - old-scale (.scaleX data)] - (.setScale data (float (* old-scale unit-scale))) - (.draw font - batch - (str text) - (float x) - (float (+ y (if up? (text-height font text) 0))) - (float 0) ; target-width - (case (or h-align :center) - :center Align/center - :left Align/left - :right Align/right) - false) ; wrap false, no need target-width - (.setScale data (float old-scale)))) diff --git a/src/gdl/graphics/image.clj b/src/gdl/graphics/image.clj index 1af5eb4..45fe4d1 100644 --- a/src/gdl/graphics/image.clj +++ b/src/gdl/graphics/image.clj @@ -1,5 +1,5 @@ (ns gdl.graphics.image - (:import (com.badlogic.gdx.graphics Color Texture) + (:import (com.badlogic.gdx.graphics Texture) (com.badlogic.gdx.graphics.g2d Batch TextureRegion))) ; TODO @@ -19,45 +19,6 @@ ; * -> I cache only dimensions & scale for my texture-regions ; * color & rotation applied on rendering -(defn- draw-texture [^Batch batch texture [x y] [w h] rotation color] - (if color (.setColor batch color)) - (.draw batch texture - x - y - (/ w 2) ; rotation origin - (/ h 2) - w ; width height - h - 1 ; scaling factor - 1 - rotation) - (if color (.setColor batch Color/WHITE))) - -(defn- unit-dimensions [{:keys [unit-scale world-unit-scale] :as context} image] - {:pre [(number? unit-scale)]} - (cond - (= unit-scale world-unit-scale) (:world-unit-dimensions image) - (= unit-scale 1) (:pixel-dimensions image))) - -(defn draw - ([{:keys [batch] :as context} {:keys [texture color] :as image} position] - (draw-texture batch texture position (unit-dimensions context image) 0 color)) - ([context image x y] - (draw context image [x y]))) - -(defn draw-rotated-centered - [{:keys [batch] :as context} {:keys [texture color] :as image} rotation [x y]] - (let [[w h] (unit-dimensions context image)] - (draw-texture batch - texture - [(- x (/ w 2)) - (- y (/ h 2))] - [w h] - rotation - color))) - -(defn draw-centered [context image position] - (draw-rotated-centered context image 0 position)) (defn- texture-dimensions [^TextureRegion texture] [(.getRegionWidth texture) diff --git a/src/gdl/graphics/shape_drawer.clj b/src/gdl/graphics/shape_drawer.clj deleted file mode 100644 index ad0bf97..0000000 --- a/src/gdl/graphics/shape_drawer.clj +++ /dev/null @@ -1,91 +0,0 @@ -(ns gdl.graphics.shape-drawer - (:require [x.x :refer [defmodule]] - [gdl.lc :as lc]) - (:import [com.badlogic.gdx.graphics Texture Pixmap Pixmap$Format Color] - com.badlogic.gdx.graphics.g2d.TextureRegion - space.earlygrey.shapedrawer.ShapeDrawer)) - -(defn- gen-drawer-texture ^Texture [] - (let [pixmap (doto (Pixmap. 1 1 Pixmap$Format/RGBA8888) - (.setColor Color/WHITE) - (.drawPixel 0 0)) - texture (Texture. pixmap)] - (.dispose pixmap) - texture)) - -(declare ^ShapeDrawer drawer) - -(defmodule texture - (lc/create [[_ batch] _ctx] - (let [texture (gen-drawer-texture)] - (.bindRoot #'drawer (ShapeDrawer. batch (TextureRegion. texture 0 0 1 1))) - texture)) - (lc/dispose [_] - (.dispose ^Texture texture))) - -(defn- set-color [^Color color] - (.setColor drawer color)) - -(defn set-line-width [width] - (.setDefaultLineWidth drawer (float width))) - -(defmacro with-line-width [width & exprs] - `(let [old-line-width# (.getDefaultLineWidth drawer)] - (set-line-width (* ~width old-line-width#)) - ~@exprs - (set-line-width old-line-width#))) - -(defn ellipse [[x y] radius-x radius-y color] - (set-color color) - (.ellipse drawer (float x) (float y) (float radius-x) (float radius-y))) - -(defn filled-ellipse [[x y] radius-x radius-y color] - (set-color color) - (.filledEllipse drawer (float x) (float y) (float radius-x) (float radius-y))) - -(defn circle [[x y] radius color] - (set-color color) - (.circle drawer (float x) (float y) (float radius))) - -(defn filled-circle [[x y] radius color] - (set-color color) - (.filledCircle drawer (float x) (float y) (float radius))) - -(defn- degree->radians [degree] ; TODO not here - (* degree (/ (Math/PI) 180))) - -(defn arc [[centre-x centre-y] radius start-angle degree color] - (set-color color) - (.arc drawer centre-x centre-y radius start-angle (degree->radians degree))) - -(defn sector [[centre-x centre-y] radius start-angle degree color] - (set-color color) - (.sector drawer centre-x centre-y radius start-angle (degree->radians degree))) - -(defn rectangle [x y w h color] - (set-color color) - (.rectangle drawer x y w h)) - -(defn filled-rectangle [x y w h color] - (set-color color) - (.filledRectangle drawer (float x) (float y) (float w) (float h))) - -(defn line - ([[x y] [ex ey] color] - (line x y ex ey color)) - ([x y ex ey color] - (set-color color) - (.line drawer (float x) (float y) (float ex) (float ey)))) - -(defn grid - [leftx bottomy gridw gridh cellw cellh color] - (let [w (* gridw cellw) - h (* gridh cellh) - topy (+ bottomy h) - rightx (+ leftx w)] - (doseq [idx (range (inc gridw)) - :let [linex (+ leftx (* idx cellw))]] - (line linex topy linex bottomy color)) - (doseq [idx (range (inc gridh)) - :let [liney (+ bottomy (* idx cellh))]] - (line leftx liney rightx liney color)))) diff --git a/src/gdl/scene2d/ui.clj b/src/gdl/scene2d/ui.clj index 6e2383d..7abfe81 100644 --- a/src/gdl/scene2d/ui.clj +++ b/src/gdl/scene2d/ui.clj @@ -6,15 +6,11 @@ com.badlogic.gdx.graphics.g2d.TextureRegion com.badlogic.gdx.scenes.scene2d.Actor (com.badlogic.gdx.scenes.scene2d.utils ChangeListener TextureRegionDrawable Drawable) - ; TODO unused objects remove... VisUI & also remove default-skin then (com.badlogic.gdx.scenes.scene2d.ui Cell Table Skin WidgetGroup TextButton CheckBox Window Button - Button$ButtonStyle ImageButton ImageButton$ImageButtonStyle Label TooltipManager Tooltip - TextTooltip TextField SplitPane Stack Image) + Label TooltipManager Tooltip TextTooltip TextField SplitPane Stack Image) (com.kotcrab.vis.ui VisUI VisUI$SkinScale) (com.kotcrab.vis.ui.widget VisTextField VisTable VisTextButton VisImageButton VisWindow VisLabel VisSplitPane VisCheckBox))) -; TODO use VisToolTip -> remove default-skin - (declare ^Skin default-skin) (defmodule user-skin @@ -68,12 +64,10 @@ (.row table)) table) -(defn pack [^WidgetGroup widget-group] - (.pack widget-group)) - (defn set-widget-group-opts [^WidgetGroup widget-group {:keys [fill-parent? pack?]}] (.setFillParent widget-group (boolean fill-parent?)) - (when pack? (pack widget-group)) + (when pack? + (.pack widget-group)) widget-group) (defn set-table-opts [^Table table {:keys [rows cell-defaults]}] @@ -109,7 +103,7 @@ ; TODO give directly texture-region ; TODO check how to make toggle-able ? with hotkeys for actionbar trigger ? -(defn image-button ^ImageButton [image on-clicked] +(defn image-button ^VisImageButton [image on-clicked] (let [button (VisImageButton. (TextureRegionDrawable. ^TextureRegion (:texture image)))] (.addListener button (proxy [ChangeListener] [] @@ -161,7 +155,6 @@ (TextTooltip. "" (instant-show-tooltip-manager textfn) default-skin)) ; TODO is not decendend of SplitPane anymore => check all type hints here - (defn split-pane ^VisSplitPane [& {:keys [^Actor first-widget ^Actor second-widget ^Boolean vertical?] :as opts}] @@ -171,6 +164,7 @@ (defn stack ^Stack [] (Stack.)) +; TODO VisImage, check other widgets too replacements ? (defn image ^Image [^Drawable drawable & opts] (-> (Image. drawable) (set-opts opts))) diff --git a/test/gdl/simple_test.clj b/test/gdl/simple_test.clj index 00e0fde..c7a1ecf 100644 --- a/test/gdl/simple_test.clj +++ b/test/gdl/simple_test.clj @@ -2,9 +2,10 @@ (:require [x.x :refer [defmodule]] [gdl.lc :as lc] [gdl.app :as app] - [gdl.graphics.font :as font] + [gdl.draw :as draw] [gdl.graphics.freetype :as freetype]) (:import com.badlogic.gdx.Gdx + com.badlogic.gdx.graphics.Color com.badlogic.gdx.graphics.g2d.BitmapFont)) (defmodule {:keys [special-font default-font]} @@ -18,20 +19,21 @@ (lc/render [_ {:keys [gui-mouse-position world-mouse-position] :as context}] (app/render-with (assoc context :default-font default-font) :gui - (fn [context] + (fn [drawer] (let [[wx wy] (map #(format "%.2f" %) world-mouse-position) [gx gy] gui-mouse-position the-str (str "World x " wx "\n" "World y " wy "\n" "GUI x " gx "\n" "GUI y " gy "\n")] - (font/draw-text context - {:text (str "default-font\n" the-str) - :x gx,:y gy,:h-align nil,:up? true}) - (font/draw-text context - {:font special-font - :text (str "exl-font\n" the-str) - :x gx,:y gy,:h-align :left,:up? false})))))) + (draw/circle drawer gui-mouse-position 200 Color/WHITE) + (draw/text drawer + {:text (str "default-font\n" the-str) + :x gx,:y gy,:h-align nil,:up? true}) + (draw/text drawer + {:font special-font + :text (str "exl-font\n" the-str) + :x gx,:y gy,:h-align :left,:up? false})))))) (defn app [] (app/start {:app {:title "gdl demo"