@@ -61,6 +61,7 @@ public class Sample : IDisposable
6161 //
6262 private B2Profile m_totalProfile ;
6363 private static bool s_showProfilePlots ;
64+ private static readonly bool [ ] s_profileRowOpen = new bool [ 22 ] ;
6465
6566 //
6667 private bool m_didStep ;
@@ -157,82 +158,89 @@ public virtual void UpdateGui()
157158 {
158159 float fontSize = ImGui . GetFontSize ( ) ;
159160
160- if ( m_context . frameTime )
161- {
162- UpdateFrameTimeGui ( ) ;
163- }
164-
165161 if ( m_context . drawProfile )
166162 {
167163 ImGui . SetNextWindowPos ( new Vector2 ( fontSize , 8.0f * fontSize ) , ImGuiCond . FirstUseEver ) ;
168164 ImGui . Begin ( "Profile (ms)" , ImGuiWindowFlags . NoCollapse | ImGuiWindowFlags . AlwaysAutoResize ) ;
169165
170- B2Profile aveProfile = new B2Profile ( ) ;
166+ int count = ( int ) ( m_profileWriteIndex - m_profileReadIndex ) ;
167+
168+ const int rowCount = 22 ;
169+ float [ ] [ ] histories = new float [ rowCount ] [ ] ;
170+ for ( int row = 0 ; row < rowCount ; ++ row )
171+ {
172+ histories [ row ] = new float [ m_profileCapacity ] ;
173+ }
174+
175+ for ( int i = 0 ; i < count ; ++ i )
176+ {
177+ int index = ( int ) ( ( m_profileReadIndex + ( ulong ) i ) & ( m_profileCapacity - 1 ) ) ;
178+ B2Profile profile = m_profiles [ index ] ;
179+ for ( int row = 0 ; row < rowCount ; ++ row )
180+ {
181+ histories [ row ] [ i ] = GetProfileValue ( profile , row ) ;
182+ }
183+ }
184+
185+ float [ ] avg = new float [ rowCount ] ;
171186 if ( m_stepCount > 0 )
172187 {
173188 float scale = 1.0f / m_stepCount ;
174- aveProfile . step = scale * m_totalProfile . step ;
175- aveProfile . pairs = scale * m_totalProfile . pairs ;
176- aveProfile . collide = scale * m_totalProfile . collide ;
177- aveProfile . solve = scale * m_totalProfile . solve ;
178- aveProfile . solverSetup = scale * m_totalProfile . solverSetup ;
179- aveProfile . constraints = scale * m_totalProfile . constraints ;
180- aveProfile . prepareConstraints = scale * m_totalProfile . prepareConstraints ;
181- aveProfile . integrateVelocities = scale * m_totalProfile . integrateVelocities ;
182- aveProfile . warmStart = scale * m_totalProfile . warmStart ;
183- aveProfile . solveImpulses = scale * m_totalProfile . solveImpulses ;
184- aveProfile . integratePositions = scale * m_totalProfile . integratePositions ;
185- aveProfile . relaxImpulses = scale * m_totalProfile . relaxImpulses ;
186- aveProfile . applyRestitution = scale * m_totalProfile . applyRestitution ;
187- aveProfile . storeImpulses = scale * m_totalProfile . storeImpulses ;
188- aveProfile . transforms = scale * m_totalProfile . transforms ;
189- aveProfile . splitIslands = scale * m_totalProfile . splitIslands ;
190- aveProfile . jointEvents = scale * m_totalProfile . jointEvents ;
191- aveProfile . hitEvents = scale * m_totalProfile . hitEvents ;
192- aveProfile . refit = scale * m_totalProfile . refit ;
193- aveProfile . bullets = scale * m_totalProfile . bullets ;
194- aveProfile . sleepIslands = scale * m_totalProfile . sleepIslands ;
195- aveProfile . sensors = scale * m_totalProfile . sensors ;
189+ for ( int row = 0 ; row < rowCount ; ++ row )
190+ {
191+ avg [ row ] = scale * GetProfileValue ( m_totalProfile , row ) ;
192+ }
196193 }
197194
198- ref readonly B2Profile p = ref m_profiles [ m_currentProfileIndex ] ;
195+ ref readonly B2Profile current = ref m_profiles [ m_currentProfileIndex ] ;
199196 string [ ] names =
200197 [
201- "step" , "pairs" , "collide" , "solve" , "solver setup" , "constraints" , "prepare constraints " ,
202- "integrate velocities" , "warm start" , "solve impulses " , "integrate positions" , "relax impulses " ,
203- "apply restitution" , "store impulses " , "split islands" , "update transforms" , "joint events" ,
204- "hit events" , "refit BVH" , "sleep islands " , "bullets" , "sensors"
198+ "step" , "pairs" , "collide" , "solve" , "setup" , "constraints" , "prepare" ,
199+ "velocities" , "warm start" , "bias " , "positions" , "relax" ,
200+ "restitution" , "store" , "split islands" , "transforms" , "joint events" ,
201+ "hit events" , "refit BVH" , "sleep" , "bullets" , "sensors"
205202 ] ;
206203 int [ ] indents = [ 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ] ;
204+ int [ ] parents = new int [ rowCount ] ;
205+ bool [ ] hasChildren = new bool [ rowCount ] ;
206+ int [ ] stack = new int [ 8 ] ;
207+ int stackSize = 0 ;
208+ for ( int i = 0 ; i < rowCount ; ++ i )
209+ {
210+ while ( stackSize > 0 && indents [ stack [ stackSize - 1 ] ] >= indents [ i ] )
211+ {
212+ stackSize -= 1 ;
213+ }
214+
215+ parents [ i ] = stackSize > 0 ? stack [ stackSize - 1 ] : - 1 ;
216+ stack [ stackSize ] = i ;
217+ stackSize += 1 ;
218+
219+ if ( parents [ i ] >= 0 )
220+ {
221+ hasChildren [ parents [ i ] ] = true ;
222+ }
223+ }
224+
225+ Vector4 colorStep = new Vector4 ( 102.0f / 255.0f , 153.0f / 255.0f , 1.0f , 1.0f ) ;
226+ Vector4 colorCollide = new Vector4 ( 1.0f , 140.0f / 255.0f , 51.0f / 255.0f , 1.0f ) ;
227+ Vector4 colorSolve = new Vector4 ( 102.0f / 255.0f , 204.0f / 255.0f , 102.0f / 255.0f , 1.0f ) ;
228+ Vector4 colorDefault = new Vector4 ( 220.0f / 255.0f , 220.0f / 255.0f , 220.0f / 255.0f , 1.0f ) ;
229+
207230 Vector4 [ ] colors =
208231 [
209- new Vector4 ( 0.85f , 0.85f , 0.85f , 1.0f ) , new Vector4 ( 0.75f , 0.75f , 0.75f , 1.0f ) ,
210- new Vector4 ( 0.95f , 0.65f , 0.20f , 1.0f ) , new Vector4 ( 0.30f , 0.85f , 0.45f , 1.0f ) ,
211- new Vector4 ( 0.55f , 0.75f , 1.0f , 1.0f ) , new Vector4 ( 0.35f , 0.95f , 0.65f , 1.0f ) ,
212- new Vector4 ( 0.35f , 0.75f , 0.95f , 1.0f ) , new Vector4 ( 0.90f , 0.50f , 0.95f , 1.0f ) ,
213- new Vector4 ( 0.95f , 0.85f , 0.35f , 1.0f ) , new Vector4 ( 0.95f , 0.45f , 0.45f , 1.0f ) ,
214- new Vector4 ( 0.45f , 0.95f , 0.90f , 1.0f ) , new Vector4 ( 0.75f , 0.95f , 0.45f , 1.0f ) ,
215- new Vector4 ( 0.95f , 0.70f , 0.45f , 1.0f ) , new Vector4 ( 0.70f , 0.70f , 1.0f , 1.0f ) ,
216- new Vector4 ( 0.80f , 0.80f , 0.55f , 1.0f ) , new Vector4 ( 0.45f , 0.95f , 0.55f , 1.0f ) ,
217- new Vector4 ( 0.95f , 0.55f , 0.75f , 1.0f ) , new Vector4 ( 0.95f , 0.35f , 0.35f , 1.0f ) ,
218- new Vector4 ( 0.55f , 0.85f , 0.95f , 1.0f ) , new Vector4 ( 0.65f , 0.85f , 0.55f , 1.0f ) ,
219- new Vector4 ( 0.85f , 0.65f , 0.95f , 1.0f ) , new Vector4 ( 0.70f , 0.90f , 0.90f , 1.0f )
232+ colorStep , colorDefault , colorCollide , colorSolve , colorDefault , colorDefault ,
233+ colorDefault , colorDefault , colorDefault , colorDefault , colorDefault , colorDefault ,
234+ colorDefault , colorDefault , colorDefault , colorDefault , colorDefault , colorDefault ,
235+ colorDefault , colorDefault , colorDefault , colorDefault
220236 ] ;
221237 float [ ] now =
222238 [
223- p . step , p . pairs , p . collide , p . solve , p . solverSetup , p . constraints , p . prepareConstraints ,
224- p . integrateVelocities , p . warmStart , p . solveImpulses , p . integratePositions , p . relaxImpulses ,
225- p . applyRestitution , p . storeImpulses , p . splitIslands , p . transforms , p . jointEvents ,
226- p . hitEvents , p . refit , p . sleepIslands , p . bullets , p . sensors
227- ] ;
228- float [ ] avg =
229- [
230- aveProfile . step , aveProfile . pairs , aveProfile . collide , aveProfile . solve , aveProfile . solverSetup ,
231- aveProfile . constraints , aveProfile . prepareConstraints , aveProfile . integrateVelocities ,
232- aveProfile . warmStart , aveProfile . solveImpulses , aveProfile . integratePositions ,
233- aveProfile . relaxImpulses , aveProfile . applyRestitution , aveProfile . storeImpulses ,
234- aveProfile . splitIslands , aveProfile . transforms , aveProfile . jointEvents , aveProfile . hitEvents ,
235- aveProfile . refit , aveProfile . sleepIslands , aveProfile . bullets , aveProfile . sensors
239+ current . step , current . pairs , current . collide , current . solve , current . solverSetup ,
240+ current . constraints , current . prepareConstraints , current . integrateVelocities , current . warmStart ,
241+ current . solveImpulses , current . integratePositions , current . relaxImpulses , current . applyRestitution ,
242+ current . storeImpulses , current . splitIslands , current . transforms , current . jointEvents ,
243+ current . hitEvents , current . refit , current . sleepIslands , current . bullets , current . sensors
236244 ] ;
237245
238246 if ( ImGui . Button ( "Reset" ) )
@@ -247,28 +255,41 @@ public virtual void UpdateGui()
247255 int columnCount = s_showProfilePlots ? 6 : 5 ;
248256 if ( ImGui . BeginTable ( "profile" , columnCount , tableFlags ) )
249257 {
250- ImGui . TableSetupColumn ( "section" , ImGuiTableColumnFlags . WidthFixed , 10 .0f * fontSize ) ;
251- ImGui . TableSetupColumn ( "now" , ImGuiTableColumnFlags . WidthFixed , 4 .0f * fontSize ) ;
252- ImGui . TableSetupColumn ( "avg" , ImGuiTableColumnFlags . WidthFixed , 4 .0f * fontSize ) ;
253- ImGui . TableSetupColumn ( "max" , ImGuiTableColumnFlags . WidthFixed , 4 .0f * fontSize ) ;
258+ ImGui . TableSetupColumn ( "section" , ImGuiTableColumnFlags . WidthFixed , 8 .0f * fontSize ) ;
259+ ImGui . TableSetupColumn ( "now" , ImGuiTableColumnFlags . WidthFixed , 3 .0f * fontSize ) ;
260+ ImGui . TableSetupColumn ( "avg" , ImGuiTableColumnFlags . WidthFixed , 3 .0f * fontSize ) ;
261+ ImGui . TableSetupColumn ( "max" , ImGuiTableColumnFlags . WidthFixed , 3 .0f * fontSize ) ;
254262 ImGui . TableSetupColumn ( "% step" , ImGuiTableColumnFlags . WidthFixed , 8.0f * fontSize ) ;
255263 if ( s_showProfilePlots )
256264 {
257265 ImGui . TableSetupColumn ( "history" , ImGuiTableColumnFlags . WidthFixed , 16.0f * fontSize ) ;
258266 }
259267 ImGui . TableHeadersRow ( ) ;
260268
261- int count = ( int ) ( m_profileWriteIndex - m_profileReadIndex ) ;
262- float stepNow = b2MaxFloat ( p . step , 0.001f ) ;
263- float [ ] history = new float [ m_profileCapacity ] ;
269+ float rowHeight = 1.5f * fontSize ;
270+ float stepNow = b2MaxFloat ( current . step , 0.001f ) ;
264271
265- for ( int row = 0 ; row < names . Length ; ++ row )
272+ for ( int row = 0 ; row < rowCount ; ++ row )
266273 {
274+ bool visible = true ;
275+ for ( int parent = parents [ row ] ; parent >= 0 ; parent = parents [ parent ] )
276+ {
277+ if ( s_profileRowOpen [ parent ] == false )
278+ {
279+ visible = false ;
280+ break ;
281+ }
282+ }
283+
284+ if ( visible == false )
285+ {
286+ continue ;
287+ }
288+
289+ float [ ] history = histories [ row ] ;
267290 float rollingMax = 0.0f ;
268291 for ( int i = 0 ; i < count ; ++ i )
269292 {
270- int index = ( int ) ( ( m_profileReadIndex + ( ulong ) i ) & ( m_profileCapacity - 1 ) ) ;
271- history [ i ] = GetProfileValue ( m_profiles [ index ] , row ) ;
272293 rollingMax = b2MaxFloat ( rollingMax , history [ i ] ) ;
273294 }
274295
@@ -278,9 +299,23 @@ public virtual void UpdateGui()
278299 {
279300 ImGui . Indent ( indents [ row ] * fontSize ) ;
280301 }
281- ImGui . PushStyleColor ( ImGuiCol . Text , colors [ row ] ) ;
282- ImGui . TextUnformatted ( names [ row ] ) ;
283- ImGui . PopStyleColor ( ) ;
302+ if ( hasChildren [ row ] )
303+ {
304+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags . OpenOnArrow | ImGuiTreeNodeFlags . OpenOnDoubleClick |
305+ ImGuiTreeNodeFlags . NoTreePushOnOpen ;
306+ ImGui . PushStyleColor ( ImGuiCol . Text , colors [ row ] ) ;
307+ s_profileRowOpen [ row ] = ImGui . TreeNodeEx ( names [ row ] , flags ) ;
308+ ImGui . PopStyleColor ( ) ;
309+ }
310+ else
311+ {
312+ float leafIndent = ImGui . GetTreeNodeToLabelSpacing ( ) ;
313+ ImGui . Indent ( leafIndent ) ;
314+ ImGui . PushStyleColor ( ImGuiCol . Text , colors [ row ] ) ;
315+ ImGui . TextUnformatted ( names [ row ] ) ;
316+ ImGui . PopStyleColor ( ) ;
317+ ImGui . Unindent ( leafIndent ) ;
318+ }
284319 if ( indents [ row ] > 0 )
285320 {
286321 ImGui . Unindent ( indents [ row ] * fontSize ) ;
@@ -305,7 +340,7 @@ public virtual void UpdateGui()
305340 if ( count > 1 )
306341 {
307342 ImGui . PushStyleColor ( ImGuiCol . PlotLines , colors [ row ] ) ;
308- ImGui . PlotLines ( $ "##h{ row } ", ref history [ 0 ] , count , 0 , null , 0.0f , rollingMax * 1.05f + 0.001f , new Vector2 ( - float . Epsilon , 1.5f * fontSize ) ) ;
343+ ImGui . PlotLines ( $ "##h{ row } ", ref history [ 0 ] , count , 0 , null , 0.0f , rollingMax * 1.05f + 0.001f , new Vector2 ( - float . Epsilon , rowHeight ) ) ;
309344 ImGui . PopStyleColor ( ) ;
310345 }
311346 }
@@ -399,6 +434,11 @@ public virtual void UpdateGui()
399434
400435 ImGui . End ( ) ;
401436 }
437+
438+ if ( m_context . frameTime )
439+ {
440+ UpdateFrameTimeGui ( fontSize ) ;
441+ }
402442 }
403443
404444 private static float GetProfileValue ( in B2Profile profile , int row )
@@ -437,16 +477,16 @@ private static Vector4 HexToColor(B2HexColor color)
437477 return new Vector4 ( ( ( hex >> 16 ) & 0xFF ) / 255.0f , ( ( hex >> 8 ) & 0xFF ) / 255.0f , ( hex & 0xFF ) / 255.0f , 1.0f ) ;
438478 }
439479
440- private void UpdateFrameTimeGui ( )
480+ private void UpdateFrameTimeGui ( float fontSize )
441481 {
442- const float frameTimeHeight = 400 .0f;
443- const float frameTimeWidth = 800 .0f;
482+ float frameTimeHeight = 30 .0f * fontSize ;
483+ float frameTimeWidth = 50 .0f * fontSize ;
444484
445- ImGui . SetNextWindowPos ( new Vector2 ( 30 .0f, 30 .0f) , ImGuiCond . FirstUseEver ) ;
485+ ImGui . SetNextWindowPos ( new Vector2 ( 3 .0f * fontSize , 3 .0f * fontSize ) , ImGuiCond . FirstUseEver ) ;
446486 ImGui . SetNextWindowSize ( new Vector2 ( frameTimeWidth , frameTimeHeight ) , ImGuiCond . FirstUseEver ) ;
447487
448488 ImGui . Begin ( "Frame Time" , ref m_context . frameTime , ImGuiWindowFlags . NoCollapse ) ;
449- ImGui . PushItemWidth ( ImGui . GetWindowWidth ( ) - 20 .0f) ;
489+ ImGui . PushItemWidth ( ImGui . GetWindowWidth ( ) - 2 .0f * fontSize ) ;
450490
451491 int count = ( int ) ( m_profileWriteIndex - m_profileReadIndex ) ;
452492 float maxValue = 0.0f ;
@@ -458,7 +498,7 @@ private void UpdateFrameTimeGui()
458498 }
459499
460500 // This is the pixel size, not the range.
461- Vector2 plotSize = new Vector2 ( - 1.0f , 22.0f * ImGui . GetTextLineHeight ( ) ) ;
501+ Vector2 plotSize = new Vector2 ( - 1.0f , 22.0f * fontSize ) ;
462502 DrawProfilePlot ( "Profile" , count , maxValue , plotSize ) ;
463503
464504 ImGui . PopItemWidth ( ) ;
0 commit comments