Skip to content

Commit

Permalink
Backdrop : Improve ordering of nested backdrops
Browse files Browse the repository at this point in the history
We now automatically draw larger backdrops behind smaller ones, so that nested backdrops "just work". An additional `depth` plug allows the user to override this in rare cases where they want a smaller backdrop to appear beneath a larger one.
  • Loading branch information
johnhaddon committed Jan 2, 2024
1 parent e7bbb95 commit 2b109cb
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ Improvements
- Added "Custom" option, to allow strings to be entered manually.
- Added right-click context menu.
- Switch : Added `connectedInputs` output plug.
- Backdrop : Improved drawing order for nested backdrops :
- Larger backdrops are automatically drawn behind smaller ones, so that nested backdrops will always appear on top.
- Added a `depth` plug to assign a manual drawing depth for the rare cases where the automatic depth is unwanted.

Fixes
-----
Expand Down Expand Up @@ -75,6 +78,7 @@ Breaking Changes
----------------

- Render : Changed `render:includedPurposes` default to `"default", "render"`.
- Backdrop : Changed default drawing order. Use the new `depth` plug to override the order if necessary.
- ValuePlug : Removed deprecated `getObjectValue()` overload.
- Preferences : Removed `cache` plug.
- TaskNode :
Expand Down
3 changes: 3 additions & 0 deletions include/Gaffer/Backdrop.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class GAFFER_API Backdrop : public Node
StringPlug *descriptionPlug();
const StringPlug *descriptionPlug() const;

IntPlug *depthPlug();
const IntPlug *depthPlug() const;

private :

static size_t g_firstPlugIndex;
Expand Down
19 changes: 19 additions & 0 deletions python/GafferUI/BackdropUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ def nodeMenuCreateCommand( menu ) :

],

"depth" : [

"description",
"""
Determines the drawing order of overlapping backdrops.
> Note : Larger backdrops are _automatically_ drawn behind smaller ones,
> so it is only necessary to manually assign a depth in rare cases where
> this is not desirable.
""",

"plugValueWidget:type", "GafferUI.PresetsPlugValueWidget",
"preset:Back", -1,
"preset:Middle", 0,
"preset:Front", 1,


],

}

)
11 changes: 11 additions & 0 deletions src/Gaffer/Backdrop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Backdrop::Backdrop( const std::string &name )
addChild( new StringPlug( "title", Plug::In, "Title" ) );
addChild( new FloatPlug( "scale", Plug::In, 1.0f, 1.0f ) );
addChild( new StringPlug( "description" ) );
addChild( new IntPlug( "depth", Plug::In, 0, -1, 1 ) );
}

Backdrop::~Backdrop()
Expand Down Expand Up @@ -86,3 +87,13 @@ const Gaffer::StringPlug *Backdrop::descriptionPlug() const
{
return getChild<StringPlug>( g_firstPlugIndex + 2 );
}

IntPlug *Backdrop::depthPlug()
{
return getChild<IntPlug>( g_firstPlugIndex + 3 );
}

const IntPlug *Backdrop::depthPlug() const
{
return getChild<IntPlug>( g_firstPlugIndex + 3 );
}
59 changes: 57 additions & 2 deletions src/GafferUI/BackdropNodeGadget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,53 @@ void titleAndDescriptionFromPlugs( const StringPlug *titlePlug, const StringPlug
}
}

// Remaps `x` into the range `outMin, outMax`. The initial portion
// of the mapping - for `x < m` - is linear and uses the first proportion
// `q` of the output range. After that the result approaches `outMax`
// asymptotically.
float remap( float x, float m, float q, float outMin, float outMax )
{
if( x < m )
{
return outMin + q * ( x / m ) * ( outMax - outMin );
}
else
{
return outMax - ( outMax - outMin ) * ( 1.0 - 2.0 * q + q * q ) / ( 1.0 - 2.0 * q + q * (x / m) );
}
}

float depth( const Backdrop *backdrop, const Box2f &bound, const V2f &clipping )
{
// We let the user assign a fixed depth from a narrow set of integer
// options. We use this to carve out a range within the clipping planes.

float nodeDepth = 0;
try
{
nodeDepth = backdrop->depthPlug()->getValue();
}
catch( ... )
{
}
const float nodeDepthMin = backdrop->depthPlug()->minValue();
const float nodeDepthMax = backdrop->depthPlug()->maxValue();
const float rangeSize = ( clipping[1] - clipping[0] ) / ( 1.0 + nodeDepthMax - nodeDepthMin );
const float rangeStart = clipping[0] + ( nodeDepthMax - nodeDepth ) * rangeSize;
const float rangeEnd = rangeStart + rangeSize;

// We then choose a depth within that range based on the area of
// the backdrop, with larger backdrops being given larger depths.
// In most cases this means that backdrops automatically order
// themselves, and the user only needs to assign a depth manually
// in unusual cases where they want a smaller backdrop to appear
// behind a larger one.

const float area = bound.size().x * bound.size().y;
const float maxLikelyArea = 1000 * 1000;
return -remap( area, maxLikelyArea, 0.75, rangeStart, rangeEnd );
}

const float g_margin = 3.0f;
const float g_titleBarHeight = 1.0f;
const float g_titleBarMargin = 1.0f;
Expand Down Expand Up @@ -271,13 +318,19 @@ void BackdropNodeGadget::renderLayer( Layer layer, const Style *style, RenderRea

const Backdrop *backdrop = static_cast<const Backdrop *>( node() );
const float scale = backdrop->scalePlug()->getValue();
const float translateZ = depth( backdrop, bound, ancestor<ViewportGadget>()->getCamera()->getClippingPlanes() );

bound.min /= scale;
bound.max /= scale;

glPushMatrix();
glPushAttrib( GL_DEPTH_BUFFER_BIT );

glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );

glScalef( scale, scale, scale );
glScalef( scale, scale, 1.0f );
glTranslatef( 0, 0, translateZ );

const Box3f titleCharacterBound = style->characterBound( Style::HeadingText );
const float titleBaseline = bound.max.y - g_margin - titleCharacterBound.max.y;
Expand Down Expand Up @@ -352,6 +405,7 @@ void BackdropNodeGadget::renderLayer( Layer layer, const Style *style, RenderRea
}
}

glPopAttrib();
glPopMatrix();
}

Expand Down Expand Up @@ -384,7 +438,8 @@ void BackdropNodeGadget::plugDirtied( const Gaffer::Plug *plug )
if(
plug == backdrop->titlePlug() ||
plug == backdrop->scalePlug() ||
plug == backdrop->descriptionPlug()
plug == backdrop->descriptionPlug() ||
plug == backdrop->depthPlug()
)
{
dirty( DirtyType::Render );
Expand Down

0 comments on commit 2b109cb

Please sign in to comment.