oakes / play-clj

A Clojure game library
The Unlicense
940 stars 72 forks source link

NullPointerException On Dialog Close #70

Closed Yoshiyuka closed 9 years ago

Yoshiyuka commented 9 years ago

I've come across what I'm interpreting to be a bug with the dialog ui element (#ui.dialog). I've added a button to dialogs that close their parent dialog when clicked with (dialog! popup :button "Close") where popup is (dialog "Test" (skin "uiskin.json")). The dialog closes when the Close button is clicked. However, this immediately causes a NullPointerException in the render code.

    dialog-issue.core=> java.lang.NullPointerException
        at com.badlogic.gdx.scenes.scene2d.ui.Window.draw(Window.java:216)
        at play_clj.entities.ActorEntity.draw_BANG_(entities.clj:76)
        at play_clj.core$fn__576.invoke(core_graphics.clj:493)
        at clojure.lang.MultiFn.invoke(MultiFn.java:233)
        at play_clj.core$render_BANG_.invoke(core_graphics.clj:553)
        at dialog_issue.core$eval1831$fn__1857.invoke(core.clj:22)
        at clojure.lang.Var.invoke(Var.java:383)
        at play_clj.core$defscreen_STAR_$execute_fn_BANG___886$fn__889.invoke(core.clj:83)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.lang.AFunction$1.doInvoke(AFunction.java:29)
        at clojure.lang.RestFn.invoke(RestFn.java:397)
        at dialog_issue.core$eval1910$fn__1911.invoke(core.clj:35)
        at play_clj.core$defscreen_STAR_$execute_fn_BANG___886.doInvoke(core.clj:85)
        at clojure.lang.RestFn.invoke(RestFn.java:439)
        at play_clj.core$defscreen_STAR_$fn__902.invoke(core.clj:120)
        at clojure.lang.AFn.applyToHelper(AFn.java:154)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.core$apply.invoke(core.clj:626)
        at play_clj.core$set_screen_BANG_$run_fn_BANG___943.doInvoke(core.clj:517)
        at clojure.lang.RestFn.invoke(RestFn.java:423)
        at play_clj.core$set_screen_BANG_$reify__951.render(core.clj:526)
        at com.badlogic.gdx.Game.render(Game.java:46)
        at play_clj.core.proxy$com.badlogic.gdx.Game$ff19274a.render(Unknown Source)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:208)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)

This is caused by the following code:

(ns dialog-issue.core
  (:require [ns-tracker.core :refer :all]
            [play-clj.core :refer :all]
            [play-clj.ui :refer :all]))

(def modified-namespaces
  (ns-tracker ["src" "src-common"]))

(defscreen main-screen
  :on-show
  (fn [screen entities]
    (let [popup (dialog "Test" (skin "uiskin.json"))]
    (update! screen :renderer (stage))
    (dialog! popup :button "Close")
    popup))

  :on-render
  (fn [screen entities]
    (clear!)
    (doseq [ns-sym (modified-namespaces)]
      (require ns-sym :reload))
    (render! screen entities)))

(defgame dialog-issue
  :on-create
  (fn [this]
    (set-screen! this main-screen)))

(defscreen blank-screen
  :on-render
  (fn [screen entities]
    (clear!)))

(set-screen-wrapper! (fn [screen screen-fn]
                       (try (screen-fn)
                         (catch Exception e
                           (.printStackTrace e)
                           (set-screen! dialog-issue blank-screen)))))

I've gotten around this error by manually removing the dialog entity from the entities vector in :on-ui-changed such that:

     :on-ui-changed
     (fn [screen entities]
       (let [actor (-> (actor! (:actor screen) :get-parent)
                             (actor! :get-parent))]
       (vector (filter #(not(identical? actor (:object %))) entities))))

My project.clj:

    (defproject dialog-issue "0.0.1-SNAPSHOT"
      :description "FIXME: write description"

      :dependencies [[com.badlogicgames.gdx/gdx "LATEST"]
                 [com.badlogicgames.gdx/gdx-backend-lwjgl "LATEST"]
                 [com.badlogicgames.gdx/gdx-box2d "LATEST"]
                 [com.badlogicgames.gdx/gdx-box2d-platform "LATEST"
                  :classifier "natives-desktop"]
                 [com.badlogicgames.gdx/gdx-bullet "LATEST"]
                 [com.badlogicgames.gdx/gdx-bullet-platform "LATEST"
                  :classifier "natives-desktop"]
                 [com.badlogicgames.gdx/gdx-platform "LATEST"
                  :classifier "natives-desktop"]
                 [org.clojure/clojure "LATEST"]
                 [play-clj "LATEST"]
                 [ns-tracker "LATEST"]]

      :source-paths ["src" "src-common"]
      :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
      :aot [dialog-issue.core.desktop-launcher]
      :main dialog-issue.core.desktop-launcher)
oakes commented 9 years ago

Fixed in eabdaa3339ca3da7d715f9bd37d354be0feacfa7. I pushed 0.4.5-SNAPSHOT so you can try the fix for yourself.

Yoshiyuka commented 9 years ago

Thank you for the incredibly fast response. I've pulled 0.4.5-SNAPSHOT and can confirm that this has resolved the NullPointerException on closing a dialog.

oakes commented 9 years ago

No problem, there's nothing else to do on a Saturday night, hah.