2727import com .simsilica .lemur .FillMode ;
2828import com .simsilica .lemur .Label ;
2929import com .simsilica .lemur .component .BoxLayout ;
30+ import com .simsilica .lemur .component .QuadBackgroundComponent ;
3031import com .simsilica .lemur .component .TbtQuadBackgroundComponent ;
32+ import com .simsilica .lemur .style .ElementId ;
3133
3234import java .util .ArrayList ;
3335import java .util .HashMap ;
@@ -73,7 +75,7 @@ public class DebugWindowState extends BaseAppState{
7375 VRHandsAppState vrHandsAppState ;
7476 StatsAppState statsAppState ;
7577
76- protected float secondCounter = 0.0f ;
78+ protected long nanosOfCountStart = - 1 ;
7779 protected int frameCounter = 0 ;
7880
7981 boolean connectedToHands = false ;
@@ -91,8 +93,14 @@ public class DebugWindowState extends BaseAppState{
9193
9294 private boolean requestInitialiseStats = false ;
9395
96+ private Optional <ElementId > topLevelContainerId = Optional .empty ();
97+
9498 private Statistics statistics ;
9599
100+ private boolean initialised ;
101+
102+ private long lastNanoTime = 0 ;
103+
96104 public DebugWindowState (){
97105 this (null , null );
98106 }
@@ -108,25 +116,55 @@ public DebugWindowState(ActionHandle hapticAction, ActionHandle grabAction){
108116 this .grabAction = grabAction ;
109117 }
110118
119+ /**
120+ * Allows the top level lemur contain ID to be set (for styling).
121+ * <p>Must be called before initialisation in order to have any effect</p>
122+ * @param elementId the element ID to use as the top level container
123+ */
124+ public DebugWindowState setTopLevelContainerId (ElementId elementId ){
125+ topLevelContainerId = Optional .of (elementId );
126+ return this ;
127+ }
128+
111129 @ Override
112130 protected void initialize (Application app ){
113- lemurWindow = new Container ();
131+ initialise ();
132+ }
133+
134+ private void initialise (){
135+ if (getState (XrBaseAppState .ID , XrBaseAppState .class ) ==null ){
136+ return ;
137+ }
138+
139+ lastNanoTime = System .nanoTime ();
140+
141+ initialised = true ;
142+ lemurWindow = topLevelContainerId .map (Container ::new ).orElseGet (Container ::new );
114143 lemurWindow .addChild (new Label ("Debug window" ));
115144 debugWindowNode .attachChild (lemurWindow );
116145 lemurWindow .setLocalScale (0.0015f );
117146
118147 lemurWindow .setLocalTranslation (-0.25f , -0.25f , 0 ); //a bit arbitrary, but likely to be about correct so a normal-sized window looks at the player right
119148
120- Material material = ((TbtQuadBackgroundComponent )lemurWindow .getBackground ()).getMaterial ().getMaterial ();
121- material .getAdditionalRenderState ().setFaceCullMode (RenderState .FaceCullMode .Off );
149+ if (lemurWindow .getBackground ()!=null && lemurWindow .getBackground () instanceof TbtQuadBackgroundComponent ) {
150+ Material material = null ;
151+ if (lemurWindow .getBackground () instanceof TbtQuadBackgroundComponent ){
152+ material = ((TbtQuadBackgroundComponent ) lemurWindow .getBackground ()).getMaterial ().getMaterial ();
153+ }
154+ if (lemurWindow .getBackground () instanceof QuadBackgroundComponent ){
155+ material = ((QuadBackgroundComponent ) lemurWindow .getBackground ()).getMaterial ().getMaterial ();
156+ }
157+ if (material !=null ) {
158+ material .getAdditionalRenderState ().setFaceCullMode (RenderState .FaceCullMode .Off );
159+ }
160+ }
122161
123162 AbstractGrabControl control = new RelativeMovingGrabControl ();
124163 debugWindowNode .addControl (control );
125164
126165 xrAppState = getState (XrBaseAppState .ID , XrBaseAppState .class );
127- vrHandsAppState = getState (VRHandsAppState .class );
128166 statsAppState = getState (StatsAppState .class );
129- ((SimpleApplication )app ).getRootNode ().attachChild (debugWindowNode );
167+ ((SimpleApplication )getApplication () ).getRootNode ().attachChild (debugWindowNode );
130168
131169 //attach press functions to the bound hands so buttons are guaranteed to be pressable (If other mouse support
132170 //is on that can also be used)
@@ -136,6 +174,11 @@ protected void initialize(Application app){
136174 }
137175
138176 private void connectToHands (){
177+ vrHandsAppState = getState (VRHandsAppState .ID , VRHandsAppState .class );
178+ if (vrHandsAppState == null ){
179+ return ;
180+ }
181+
139182 List <BoundHand > handControls = vrHandsAppState .getHandControls ();
140183
141184 if (!handControls .isEmpty ()){
@@ -271,6 +314,14 @@ public void log(String logMessage){
271314 public void update (float tpf ){
272315 super .update (tpf );
273316
317+ if (!initialised ){
318+ initialise ();
319+ }
320+ if (!initialised ){
321+ return ;
322+ }
323+
324+
274325 if (!connectedToHands ){
275326 connectToHands ();
276327 }
@@ -279,12 +330,13 @@ public void update(float tpf){
279330 initialiseStats ();
280331 }
281332
282- secondCounter += getApplication ().getTimer ().getTimePerFrame ();
283333 frameCounter ++;
284- if (secondCounter >= 1.0f ) {
334+ if (frameCounter >= 60 ) {
335+ long timeNowNanos = System .nanoTime ();
336+ float secondCounter = (timeNowNanos - nanosOfCountStart ) / 1000000000f ;
285337 int fps = (int ) (frameCounter / secondCounter );
286338 setData ("FPS" , "" +fps );
287- secondCounter = 0.0f ;
339+ nanosOfCountStart = timeNowNanos ;
288340 frameCounter = 0 ;
289341
290342 if (statistics !=null ){
0 commit comments