Skip to content

Commit 7e7f996

Browse files
committed
UI context graph viewer handles recursive graphs (thanks @moldybeats for reporting)
1 parent bca8ac1 commit 7e7f996

File tree

1 file changed

+68
-50
lines changed

1 file changed

+68
-50
lines changed

test/_audio/AudioTests/src/AudioTestsApp.cpp

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)