Skip to content

Commit

Permalink
update method for drawing slider bars (#6297)
Browse files Browse the repository at this point in the history
* update method for drawing slider bars

Instead of calling ofPath tessellation on each draw call for sliders,
slider knows how to generate mesh for bar rectangles itself. The mesh is
cached, and only updated iff the slider value changes.

Rect mesh caching works similarly to the slider's internal caching of
text meshes.

You might notice a slight perfomance improvement on GUIs with multiple
sliders with this PR.

As an additional check/optimisation, slider fill rectangles with either
width or height < 1 pixels will also not be drawn (they would not be
visible anyway).

By *not* using ofPath (and by implication the tessellator) to draw the
slider we avoid having to ask the tessellator to tessellate extremely
small paths, in which case it had a tendency to throw its hands up in
despair or disgust (hard to tell from a stack trace) and cause crashes
(see issue #6294).

#changelog #addons #ofxGui
  • Loading branch information
tgfrerer authored and arturoc committed May 23, 2019
1 parent 860f265 commit 35ff092
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 6 deletions.
80 changes: 80 additions & 0 deletions addons/ofxGui/src/ofxGuiUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#pragma once

#include "ofColor.h"
#include "ofRectangle.h"
#include "ofVboMesh.h"

/*
* Internal helper to generate and cache rectangle meshes for ofxGui.
*/
class ofxGuiRectMesh {
ofColor mColorFill = {};
ofRectangle mRect = {};
ofVboMesh mMesh = {};
bool isDirty = true;
bool mHasMesh = false;

public:
void clear() {
mColorFill = {};
mRect = {};
mMesh.clear();
mHasMesh = false;
isDirty = false;
}

void draw() {

if ( isDirty && mHasMesh ) {
mMesh.clear();
mHasMesh = false;
isDirty = false;
}

if ( mRect.width < 1.f || mRect.height < 1.f ) {
// We will not draw a mesh for rectangles
// which are smaller than one pixel for
// either w, or height.
return;
}

if ( mHasMesh == false ) {

mMesh.addVertex( mRect.getBottomLeft() );
mMesh.addVertex( mRect.getBottomRight() );
mMesh.addVertex( mRect.getTopLeft() );
mMesh.addVertex( mRect.getTopRight() );

mMesh.addColor( mColorFill );
mMesh.addColor( mColorFill );
mMesh.addColor( mColorFill );
mMesh.addColor( mColorFill );

mMesh.addIndex( 0 );
mMesh.addIndex( 1 );
mMesh.addIndex( 2 );
mMesh.addIndex( 2 );
mMesh.addIndex( 1 );
mMesh.addIndex( 3 );

mMesh.setMode( ofPrimitiveMode::OF_PRIMITIVE_TRIANGLES );
mHasMesh = true;
}

mMesh.draw();
}

void setFillColor( ofColor const &color ) {
isDirty |= ( color != mColorFill );
mColorFill = color;
}

void setExtents( ofRectangle const &rect ) {
isDirty |= ( rect != mRect );
mRect = rect;
}

void setExtents( float x, float y, float w, float h ) {
setExtents( {x, y, w, h} );
}
};
6 changes: 2 additions & 4 deletions addons/ofxGui/src/ofxSlider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,11 @@ void ofxSlider<Type>::generateDraw(){
bar.clear();

bg.setFillColor(thisBackgroundColor);
bg.setFilled(true);
bg.rectangle(b);
bg.setExtents(b);

float valAsPct = ofMap( value, value.getMin(), value.getMax(), 0, b.width-2, true );
bar.setFillColor(thisFillColor);
bar.setFilled(true);
bar.rectangle(b.x+1, b.y+1, valAsPct, b.height-2);
bar.setExtents(b.x+1, b.y+1, valAsPct, b.height-2);

generateText();
input.generateDraw();
Expand Down
8 changes: 6 additions & 2 deletions addons/ofxGui/src/ofxSlider.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "ofxBaseGui.h"
#include "ofParameter.h"
#include "ofxInputField.h"
#include "ofxGuiUtils.h"

template<typename Type>
class ofxSlider : public ofxBaseGui{
Expand Down Expand Up @@ -51,9 +52,12 @@ class ofxSlider : public ofxBaseGui{
virtual void setShape(ofRectangle r);
virtual void setShape(float x, float y, float w, float h);


ofAbstractParameter & getParameter();

private:

ofxGuiRectMesh bg, bar;

protected:
virtual void render();
ofParameter<Type> value;
Expand All @@ -65,7 +69,7 @@ class ofxSlider : public ofxBaseGui{
virtual void generateDraw();
virtual void generateText();
void valueChanged(Type & value);
ofPath bg, bar;

ofVboMesh textMesh;
ofxInputField<Type> input{ofxInputField<Type>::InsideSlider};

Expand Down

0 comments on commit 35ff092

Please sign in to comment.