(ns advent.screens.inventory (:require [play-clj.core :refer :all] [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.g2d :refer :all] [clojure.tools.logging :as log] [advent.pathfind] [advent.actions :as actions] [advent.zone :as zone] [advent.tween :as tween] [advent.utils :as utils]) (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] [com.badlogic.gdx.graphics.g2d TextureRegion] [com.badlogic.gdx.utils.viewport FitViewport] [com.badlogic.gdx.utils Align] [com.badlogic.gdx Application Audio Files Game Gdx Graphics Input InputMultiplexer InputProcessor Net Preferences Screen])) (println "loading " *ns*) (defn interactable? [entities] (and (:shown? entities) (= 1.0 (:opacity entities)))) (defn close [screen {:keys [selected-item] :as entities} script-started? dragged-out?] (log/info "closing inventory") (screen! @(resolve 'advent.screens.scene/scene) :on-reactivate { :came-from-inventory? dragged-out?}) (screen! @(resolve 'advent.screens.scene/hud) :on-reactivate { :script-started? script-started? :item selected-item}) (-> entities (assoc-in [:tweens :fade-out] (tween/tween :fade-out screen [:opacity] 1.0 0.0 0.2 :ease tween/ease-out-cubic :finish #(assoc % :shown? false :hovered-item nil :selected-item nil))))) (defn mouse-down [screen entities options] (when (interactable? entities) (let [[x y] (utils/unproject screen options) selected-entity (first (filter #((:box %) x y) (vals (:items entities))))] (assoc entities :selected-item (:item selected-entity) :down-time (:total-time screen))))) (defn mouse-outside-inventory? [[x y]] (or (< x 140) (> x 1140) (< y 320) (> y 880))) (defn mouse-drag [screen {:keys [selected-item] :as entities} options] (when (interactable? entities) (let [[x y] (utils/unproject screen options) hovered-entity (first (filter #((:box %) x y) (vals (:items entities))))] (cond (and selected-item (mouse-outside-inventory? [x y])) (close screen entities false true) selected-item (-> entities (assoc-in [:items selected-item :x] x) (assoc-in [:items selected-item :y] y) (assoc :dragged? true) (assoc :hovered-item (:item hovered-entity))) :else (assoc entities :hovered-item (:item hovered-entity) :dragged? true))))) (defn mouse-move [screen entities options] (let [[x y] (utils/unproject screen options) hovered-entity (first (filter #((:box %) x y) (vals (:items entities))))] (assoc entities :hovered-item (:item hovered-entity)))) (defn left-click [screen {:keys [selected-item hovered-item dragged?] :as entities} options] (let [room-entities (-> @(resolve 'advent.screens.scene/scene) :entities deref)] (log/info "chose inventory item" selected-item) (println selected-item hovered-item dragged?) (cond (not selected-item) (close screen entities false false) (and (> (- (:total-time screen) (:down-time entities)) 0.5) (= selected-item hovered-item) dragged?) (dissoc entities :selected-item :hovered-item :dragged?) (and (or (not hovered-item) (= selected-item hovered-item))) (do (screen! @(resolve 'advent.screens.scene/scene) :on-chose-item { :item selected-item}) (close screen entities false false)) :else (when-let [interaction-script (or ((or (:scripts selected-item) (constantly nil)) (:value hovered-item)) (actions/get-script entities (actions/talk entities :ego "I'm not sure how those go together.")))] (interaction-script room-entities) (close screen entities true false))))) (defn right-click [screen {:keys [selected-item] :as entities} options] (let [ room-entities (-> @(resolve 'advent.screens.scene/scene) :entities deref ) ego (get-in room-entities [:room :entities :ego])] (when selected-item (((:get-script ego) selected-item [0 0]) room-entities) (close screen entities true false)))) (defn update-hovered-text [screen {:keys [hovered-text hovered-item selected-item] :as entities}] (cond (and hovered-item selected-item (not= hovered-item selected-item)) (label! (:hovered-text entities) :set-text (str "Use " (:name selected-item) " with " (:name hovered-item))) hovered-item (label! (:hovered-text entities) :set-text (:name hovered-item)) :else (label! (:hovered-text entities) :set-text ""))) (defscreen inventory-screen :on-show (fn [screen entities options] (let [[screen atlas] (utils/acquire-atlas screen "packed/global.atlas") screen (utils/setup-viewport screen 1280 960) hovered-text (assoc (label "" (style :label (utils/get-font "ego/font.fnt") (color :white)) :set-font-scale 0.25) :x 0 :y 850 :width 1280 )] (label! hovered-text :set-alignment Align/bottom) (utils/add-actor-to-stage screen hovered-text) {:overlay (assoc (utils/atlas->texture atlas "inventory-overlay" ) :x 0 :y 0 :scale-x 4 :scale-y 4 :origin-x 0 :origin-y 0 :opacity 0.0) :fade (assoc (utils/atlas->texture atlas "black.png") :scale-x 80 :scale-y 80 :opacity 0.7 :origin-x 0 :origin-y 0) :all-items (texture! (texture (pixmap "cursor.png")) :split 18 16) :items [] :shown? false :hovered-item nil :opacity 0.0 :tweens {} :hovered-text hovered-text})) :on-render (fn [{:keys [^FitViewport viewport] :as screen} {:keys [shown? tweens] :as entities} options] (.apply viewport) (let [entities (utils/apply-tweens screen entities tweens) opacity (get-in entities [:opacity]) entities (-> entities (assoc-in [:overlay :opacity] opacity) (assoc-in [:fade :opacity] (* 0.6 opacity)) (assoc-in [:hovered-text :opacity] opacity) (update-in [:items] (fn [items] (reduce-kv (fn [c k i] (assoc c k (assoc i :opacity opacity))) items items))))] (when shown? (doto (:hovered-text entities) (label! :set-color (color 1 1 1 opacity))) (render! screen [(:fade entities) (:overlay entities)]) (render! screen (vals (:items entities))) (render! screen [(get-in entities [:items (:selected-item entities)])]) (update-hovered-text screen entities) (render! screen [(:hovered-text entities)])) entities)) :show-screen (fn [screen entities {:keys [items]}] (log/info "showing inventory") (when-not (:shown? entities) (label! (entities :hovered-text) :set-text "") (-> entities (assoc-in [:hovered-text :text] "") (assoc :shown? true :opacity 0.0 :items (into {} (for [[item index] (map vector items (range)) :let [row (int (/ index (Math/floor (/ 8 utils/ui-scale)))) column (mod index (Math/floor (/ 8 utils/ui-scale))) base-x (* 79 4) base-y (* 180 4) item-width (* utils/ui-scale 4 18) padding (/ item-width 4) item-height (* utils/ui-scale 4 16) padding-height (/ item-height 4) x (+ base-x (* column (+ padding item-width))) y (- base-y (* row (+ padding item-width))) offset-x (+ x (/ item-width 2)) offset-y (+ y (/ item-width 2)) padded-width (/ (+ item-width padding padding) 2) padded-height (/ (+ item-height padding-height padding-height) 2) #_#_padding (* 4 padding)]] [item (assoc (texture (aget (:all-items entities) 0 (.indexOf utils/+all-cursors+ (:cursor item)))) :x (+ x (/ padding 2)) :y y :scale-x (* utils/ui-scale 4) :scale-y (* utils/ui-scale 4) :origin-x 9 :origin-y 8 :item item :box (zone/box (- x padded-width) (- y padded-height) (+ x padded-width) (+ y padded-height)))]))) (assoc-in [:tweens :fade-in] (tween/tween :fade-in screen [:opacity] 0.0 1.0 0.2 :ease tween/ease-out-cubic))))) :on-mouse-moved mouse-move :on-touch-dragged mouse-drag :on-touch-down mouse-down :on-touch-up (fn [screen entities options] (when (interactable? entities) (if (= (button-code :left) (:button options)) (left-click screen entities options) (right-click screen entities options)))) :on-resize (fn [{:keys [^FitViewport viewport] :as screen} entities {:keys [width height]}] (.update viewport width height true)) :on-hide (fn [screen entities options] (utils/release-resources screen)))