@@ -240,8 +240,7 @@ void substituteNodeLabel( std::string &label )
240240 }
241241}
242242
243- // note: recursion level currently only for debugging
244- void printNodeFn ( audio::Node *node, bool expand, audio::Node **hovered )
243+ void showNodeFn ( audio::Node *node, bool expand, audio::Node **hovered, set<audio::Node *> &traversedNodes )
245244{
246245 string label = node->getName ();
247246 substituteNodeLabel ( label );
@@ -253,12 +252,23 @@ void printNodeFn( audio::Node *node, bool expand, audio::Node **hovered )
253252 im::SetNextTreeNodeOpen ( true );
254253
255254 if ( im::TreeNodeEx ( label.c_str (), treeNodeFlags ) ) {
255+
256+ if ( traversedNodes.count ( node ) ) {
257+ im::Text ( " ** recursion detected **" );
258+ im::PopStyleColor ();
259+ im::TreePop ();
260+ return ;
261+ }
262+ else {
263+ traversedNodes.insert ( node );
264+ }
265+
256266 if ( im::IsItemHovered () ) {
257267 *hovered = node;
258268 }
259269
260270 for ( const auto &input : node->getInputs () ) {
261- printNodeFn ( input.get (), expand, hovered );
271+ showNodeFn ( input.get (), expand, hovered, traversedNodes );
262272 }
263273
264274 im::TreePop ();
@@ -276,6 +286,60 @@ void printNodeFn( audio::Node *node, bool expand, audio::Node **hovered )
276286 im::PopStyleColor ();
277287};
278288
289+ // ! util function for showing all nodes in a tree
290+ void showContextGraph ( ci::audio::Context *ctx )
291+ {
292+ set<audio::Node *> traversedNodes;
293+ im::Text ( " Context Graph:" );
294+ im::SameLine ();
295+
296+ static bool expand = false ;
297+ im::Checkbox ( " expand all" , &expand );
298+
299+ im::BeginChild ( " Context Graph" , vec2 ( 0 , im::GetWindowHeight () - 100 ) );
300+ audio::Node *hovered = nullptr ;
301+ showNodeFn ( ctx->getOutput ().get (), expand, &hovered, traversedNodes );
302+
303+ const auto autoPulledNodes = ctx->getAutoPulledNodes ();
304+ if ( autoPulledNodes.size () > 0 ) {
305+ im::Separator ();
306+ im::Text ( " auto pulled nodes: %d" , (int )autoPulledNodes.size () );
307+ for ( const auto & node : autoPulledNodes ) {
308+ showNodeFn ( node, expand, &hovered, traversedNodes );
309+ }
310+ }
311+
312+ im::EndChild ();
313+
314+ // show info at bottom of window for hovered audio::Nodes
315+ im::Separator ();
316+ if ( hovered ) {
317+ string name = hovered->getName ();
318+ substituteNodeLabel ( name );
319+
320+ const char *processMode = hovered->getProcessesInPlace () ? " in-place" : " sum" ;
321+ string channelMode;
322+ switch ( hovered->getChannelMode () ) {
323+ case audio::Node::ChannelMode::SPECIFIED: channelMode = " specified" ; break ;
324+ case audio::Node::ChannelMode::MATCHES_INPUT: channelMode = " matches input" ; break ;
325+ case audio::Node::ChannelMode::MATCHES_OUTPUT: channelMode = " matches output" ; break ;
326+ default : CI_ASSERT_NOT_REACHABLE (); break ;
327+ }
328+
329+ im::Text ( " %s: channels: %d, mode: %s (%s)" , name.c_str (), hovered->getNumChannels (), processMode, channelMode.c_str () );
330+
331+ auto mathNode = dynamic_cast <audio::MathNode *>( hovered );
332+ if ( mathNode ) {
333+ im::SameLine ();
334+ im::Text ( " | value: %0.3f" , mathNode->getValue () );
335+ }
336+ }
337+ else {
338+ im::Text ( " " );
339+ }
340+
341+ }
342+
279343} // anon namespace
280344
281345// called on first render loop, because we need a valid gl::context
@@ -360,53 +424,7 @@ void AudioTestsApp::updateContextUI()
360424
361425 im::Text ( " dsp %s, samplerate: %d, frames per block: %d" , ( ctx->isEnabled () ? " enabled" : " disabled" ), (int )ctx->getSampleRate (), (int )ctx->getFramesPerBlock () );
362426 im::Separator ();
363- im::Text ( " Context Graph:" );
364- im::SameLine ();
365-
366- static bool expand = false ;
367- im::Checkbox ( " expand all" , &expand );
368-
369- im::BeginChild ( " Context Graph" , vec2 ( 0 , im::GetWindowHeight () - 100 ) );
370- audio::Node *hovered = nullptr ;
371- printNodeFn ( ctx->getOutput ().get (), expand, &hovered );
372-
373- const auto autoPulledNodes = ctx->getAutoPulledNodes ();
374- if ( autoPulledNodes.size () > 0 ) {
375- im::Separator ();
376- im::Text ( " auto pulled nodes: %d" , (int )autoPulledNodes.size () );
377- for ( const auto & node : autoPulledNodes ) {
378- printNodeFn ( node, expand, &hovered );
379- }
380- }
381-
382- im::EndChild ();
383-
384- // show info at bottom of window for hovered audio::Nodes
385- im::Separator ();
386- if ( hovered ) {
387- string name = hovered->getName ();
388- substituteNodeLabel ( name );
389-
390- const char *processMode = hovered->getProcessesInPlace () ? " in-place" : " sum" ;
391- string channelMode;
392- switch ( hovered->getChannelMode () ) {
393- case audio::Node::ChannelMode::SPECIFIED: channelMode = " specified" ; break ;
394- case audio::Node::ChannelMode::MATCHES_INPUT: channelMode = " matches input" ; break ;
395- case audio::Node::ChannelMode::MATCHES_OUTPUT: channelMode = " matches output" ; break ;
396- default : CI_ASSERT_NOT_REACHABLE (); break ;
397- }
398-
399- im::Text ( " %s: channels: %d, mode: %s (%s)" , name.c_str (), hovered->getNumChannels (), processMode, channelMode.c_str () );
400-
401- auto mathNode = dynamic_cast <audio::MathNode *>( hovered );
402- if ( mathNode ) {
403- im::SameLine ();
404- im::Text ( " | value: %0.3f" , mathNode->getValue () );
405- }
406- }
407- else {
408- im::Text ( " " );
409- }
427+ showContextGraph ( ctx );
410428
411429 im::End (); // Audio Context
412430}
0 commit comments