4141import com .jme3 .input .InputManager ;
4242import com .jme3 .input .KeyInput ;
4343import com .jme3 .input .MouseInput ;
44- import com .jme3 .input .controls .* ;
45- import com .jme3 .light . DirectionalLight ;
46- import com .jme3 .math . ColorRGBA ;
44+ import com .jme3 .input .controls .ActionListener ;
45+ import com .jme3 .input . controls . KeyTrigger ;
46+ import com .jme3 .input . controls . MouseButtonTrigger ;
4747import com .jme3 .math .Ray ;
4848import com .jme3 .math .Vector2f ;
4949import com .jme3 .math .Vector3f ;
5656import com .jme3 .scene .Spatial ;
5757import com .jme3 .util .TempVars ;
5858
59- import java .util .*;
59+ import java .util .ArrayList ;
60+ import java .util .HashMap ;
61+ import java .util .List ;
62+ import java .util .Map ;
63+ import java .util .function .Consumer ;
64+ import java .util .logging .Level ;
6065import java .util .logging .Logger ;
6166
6267/**
@@ -85,13 +90,14 @@ public class ArmatureDebugAppState extends BaseAppState {
8590
8691 private Node debugNode = new Node ("debugNode" );
8792 private final Map <Armature , ArmatureDebugger > armatures = new HashMap <>();
88- private final Map < Armature , Joint > selectedBones = new HashMap <>();
93+ private final List < Consumer < Joint >> selectionListeners = new ArrayList <>();
8994 private boolean displayAllJoints = false ;
9095 private float clickDelay = -1 ;
9196 private ViewPort vp ;
9297 private Camera cam ;
9398 private InputManager inputManager ;
9499 private boolean showOnTop = true ;
100+ private boolean enableLogging = true ;
95101
96102 @ Override
97103 protected void initialize (Application app ) {
@@ -107,9 +113,6 @@ protected void initialize(Application app) {
107113 debugger .initialize (app .getAssetManager (), cam );
108114 }
109115
110- debugNode .addLight (new DirectionalLight (new Vector3f (-1f , -1f , -1f ).normalizeLocal ()));
111- debugNode .addLight (new DirectionalLight (new Vector3f (1f , 1f , 1f ).normalizeLocal (), new ColorRGBA (0.5f , 0.5f , 0.5f , 1.0f )));
112-
113116 // Initially disable the viewport until the state is enabled
114117 vp .setEnabled (false );
115118
@@ -134,7 +137,7 @@ protected void cleanup(Application app) {
134137 app .getRenderManager ().removeMainView (vp );
135138 // Clear maps to release references
136139 armatures .clear ();
137- selectedBones .clear ();
140+ selectionListeners .clear ();
138141 debugNode .detachAllChildren ();
139142 }
140143
@@ -260,7 +263,18 @@ public void onAction(String name, boolean isPressed, float tpf) {
260263 } else {
261264 // Get the closest geometry hit by the ray
262265 Geometry target = results .getClosestCollision ().getGeometry ();
263- printJointInfo (target );
266+ logger .log (Level .INFO , "Pick: {0}" , target );
267+
268+ for (ArmatureDebugger ad : armatures .values ()) {
269+ Joint selectedjoint = ad .select (target );
270+
271+ if (selectedjoint != null ) {
272+ // If a joint was selected, notify it and print its properties
273+ notifySelectionListeners (selectedjoint );
274+ printJointInfo (selectedjoint , ad );
275+ break ;
276+ }
277+ }
264278 }
265279 }
266280 }
@@ -272,30 +286,22 @@ else if (name.equals(TOGGLE_JOINTS) && isPressed) {
272286 }
273287 }
274288
275- private void printJointInfo (Geometry target ) {
276-
277- for (ArmatureDebugger ad : armatures .values ()) {
278- Joint selectedjoint = ad .select (target );
279-
280- if (selectedjoint != null ) {
281- // If a joint was selected, store it and print its properties
282- selectedBones .put (ad .getArmature (), selectedjoint );
283- System .err .println ("-----------------------" );
284- System .err .println ("Selected Joint : " + selectedjoint .getName () + " in armature " + ad .getName ());
285- System .err .println ("Root Bone : " + (selectedjoint .getParent () == null ));
286- System .err .println ("-----------------------" );
287- System .err .println ("Local translation: " + selectedjoint .getLocalTranslation ());
288- System .err .println ("Local rotation: " + selectedjoint .getLocalRotation ());
289- System .err .println ("Local scale: " + selectedjoint .getLocalScale ());
290- System .err .println ("---" );
291- System .err .println ("Model translation: " + selectedjoint .getModelTransform ().getTranslation ());
292- System .err .println ("Model rotation: " + selectedjoint .getModelTransform ().getRotation ());
293- System .err .println ("Model scale: " + selectedjoint .getModelTransform ().getScale ());
294- System .err .println ("---" );
295- System .err .println ("Bind inverse Transform: " );
296- System .err .println (selectedjoint .getInverseModelBindMatrix ());
297- break ;
298- }
289+ private void printJointInfo (Joint selectedjoint , ArmatureDebugger ad ) {
290+ if (enableLogging ) {
291+ System .err .println ("-----------------------" );
292+ System .err .println ("Selected Joint : " + selectedjoint .getName () + " in armature " + ad .getName ());
293+ System .err .println ("Root Bone : " + (selectedjoint .getParent () == null ));
294+ System .err .println ("-----------------------" );
295+ System .err .println ("Local translation: " + selectedjoint .getLocalTranslation ());
296+ System .err .println ("Local rotation: " + selectedjoint .getLocalRotation ());
297+ System .err .println ("Local scale: " + selectedjoint .getLocalScale ());
298+ System .err .println ("---" );
299+ System .err .println ("Model translation: " + selectedjoint .getModelTransform ().getTranslation ());
300+ System .err .println ("Model rotation: " + selectedjoint .getModelTransform ().getRotation ());
301+ System .err .println ("Model scale: " + selectedjoint .getModelTransform ().getScale ());
302+ System .err .println ("---" );
303+ System .err .println ("Bind inverse Transform: " );
304+ System .err .println (selectedjoint .getInverseModelBindMatrix ());
299305 }
300306 }
301307
@@ -317,6 +323,42 @@ private Ray screenPointToRay(Camera cam, Vector2f click2d) {
317323 }
318324 };
319325
326+ /**
327+ * Notifies all registered {@code Consumer<Joint>} listeners about the selected joint.
328+ *
329+ * @param selectedJoint The joint that was selected.
330+ */
331+ private void notifySelectionListeners (Joint selectedJoint ) {
332+ for (Consumer <Joint > listener : selectionListeners ) {
333+ listener .accept (selectedJoint );
334+ }
335+ }
336+
337+ /**
338+ * Adds a listener that will be notified when a joint is selected.
339+ *
340+ * @param listener The {@code Consumer<Joint>} listener to add.
341+ */
342+ public void addSelectionListener (Consumer <Joint > listener ) {
343+ selectionListeners .add (listener );
344+ }
345+
346+ /**
347+ * Removes a previously added selection listener.
348+ *
349+ * @param listener The {@code Consumer<Joint>} listener to remove.
350+ */
351+ public void removeSelectionListener (Consumer <Joint > listener ) {
352+ selectionListeners .remove (listener );
353+ }
354+
355+ /**
356+ * Clears all registered selection listeners.
357+ */
358+ public void clearSelectionListeners () {
359+ selectionListeners .clear ();
360+ }
361+
320362 /**
321363 * Returns the root node for debug visualizations.
322364 * This node contains all the `ArmatureDebugger` instances.
@@ -355,6 +397,24 @@ public void setShowOnTop(boolean showOnTop) {
355397 }
356398 }
357399
400+ /**
401+ * Returns whether logging of detailed joint information is currently enabled.
402+ *
403+ * @return true if logging is enabled, false otherwise.
404+ */
405+ public boolean isEnableLogging () {
406+ return enableLogging ;
407+ }
408+
409+ /**
410+ * Sets whether logging of detailed joint information should be enabled.
411+ *
412+ * @param enableLogging true to enable logging, false to disable.
413+ */
414+ public void setEnableLogging (boolean enableLogging ) {
415+ this .enableLogging = enableLogging ;
416+ }
417+
358418 /**
359419 * A utility visitor class to traverse the scene graph and identify
360420 * which joints in a given armature are actually deforming a mesh.
0 commit comments