Skip to content

Commit

Permalink
Merge pull request #5596 from johnhaddon/backdropDepth
Browse files Browse the repository at this point in the history
Backdrop : Improve ordering of nested backdrops
  • Loading branch information
johnhaddon authored Jan 2, 2024
2 parents e7bbb95 + d42c572 commit 8f8f992
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 7 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
10 changes: 5 additions & 5 deletions src/GafferUI/StandardStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,11 +1499,6 @@ static const std::string &fragmentSource()
" OUTCOLOR.a *= ieFilteredPulse( 0.2, 0.8, gl_TexCoord[0].x );"
" }"

" if( OUTCOLOR.a == 0.0 )"
" {"
" discard;"
" }"

/// \todo Deal with all colourspace nonsense outside of the shader. Ideally the shader would accept only linear"
/// textures and output only linear data."

Expand All @@ -1524,6 +1519,11 @@ static const std::string &fragmentSource()
" OUTCOLOR = vec4( OUTCOLOR.rgb, OUTCOLOR.a * texture2D( texture, gl_TexCoord[0].xy ).a );"
" }\n"

" if( OUTCOLOR.a == 0.0 )"
" {"
" discard;"
" }\n"

"#if __VERSION__ >= 330\n"
" ieCoreGLNameOut = ieCoreGLNameIn;\n"
"#endif\n"
Expand Down

0 comments on commit 8f8f992

Please sign in to comment.