Skip to content

Commit

Permalink
Add corner options to rectangles
Browse files Browse the repository at this point in the history
  • Loading branch information
Chadnaut committed Jan 10, 2025
1 parent 946da86 commit e416eb8
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 5 deletions.
12 changes: 12 additions & 0 deletions Layouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,16 @@ Properties:
Range is [0.0 ... 1.0]. Default value is 0.0, centre is 0.5
* `rotation_origin_y` - Get/set the y position of the midpoint for rotation.
Range is [0.0 ... 1.0]. Default value is 0.0, centre is 0.5
* `corner_radius` - Get/set the corner radius as a fraction of the smallest side.
This property will preserve corner roundness when set.
Range is [0.0 ... 0.5]. Default value is 0.0.
* `corner_radius_x` - Get/set the corner x radius as a fraction of the width.
Range is [0.0 ... 0.5]. Default value is 0.0.
* `corner_radius_y` - Get/set the corner y radius as a fraction of the height.
Range is [0.0 ... 0.5]. Default value is 0.0.
* `corner_points` - Get/set the number of points used to draw the corner radius.
More points produce smooth curves, while fewer points result in flat bevels.
Range is [1 ... 32]. Default value is 1, which draws a rectangle.
* `shader` - Get/set the GLSL shader for this rectangle. This can only be set to
an instance of the class `fe.Shader` (see: `fe.add_shader()`).
* `zorder` - Get/set the rectangles's order in the applicable draw list. Objects
Expand Down Expand Up @@ -2171,6 +2181,8 @@ Member Functions:
x and y are in [0.0 ... 1.0] range, centre is ( 0.5, 0.5 )
* `set_rotation_origin( x, y )` - Set the midpoint for rotation
x and y are in [0.0 ... 1.0] range, centre is ( 0.5, 0.5 )
* `set_corner_radius( x, y )` - Set the corner x and y radius as a fraction of the width and height.
Range is [0.0 ... 0.5].

 
<a name="Sound"></a>
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ _DEP =\
tp.hpp \
fe_text.hpp \
fe_listbox.hpp \
rounded_rectangle_shape.hpp \
fe_rectangle.hpp \
fe_vm.hpp \
fe_blend.hpp \
Expand Down Expand Up @@ -197,6 +198,7 @@ _OBJ =\
tp.o \
fe_text.o \
fe_listbox.o \
rounded_rectangle_shape.o \
fe_rectangle.o \
fe_vm.o \
fe_blend.o \
Expand Down Expand Up @@ -422,7 +424,7 @@ LIBS += -lfreetype
ifeq ($(FE_WINDOWS_COMPILE),1)
LIBS += -lboost_system-mt -lboost_filesystem-mt
else ifeq ($(FE_MACOSX_COMPILE),1)
LIBS +=-L$(shell brew --prefix)/lib
LIBS +=-L$(shell brew --prefix)/lib
LIBS += -lboost_system -lboost_filesystem
else
LIBS += -l:libboost_filesystem.a -l:libboost_system.a
Expand Down
84 changes: 81 additions & 3 deletions src/fe_rectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ FeRectangle::FeRectangle( FePresentableParent &p,
m_anchor_type( TopLeft ),
m_rotation_origin_type( TopLeft ),
m_blend_mode( FeBlend::Alpha ),
m_corner_radius( 0.f, 0.f ),
m_corner_radius_auto( true ),
m_corner_point_count( 1 ),
m_rect( sf::Vector2f( w, h ))
{
setColor( sf::Color::White );
// setSize( w, h );
// setPosition( x, y );
m_rect.setTextureRect( sf::IntRect( sf::Vector2i( 0, 0 ), sf::Vector2i( 1, 1 )));
scale();
}
Expand Down Expand Up @@ -335,6 +336,72 @@ void FeRectangle::set_blend_mode( int b )
m_blend_mode = (FeBlend::Mode)b;
}

float FeRectangle::get_corner_radius() const
{
return m_corner_radius.x;
}

float FeRectangle::get_corner_radius_x() const
{
return m_corner_radius.x;
}

float FeRectangle::get_corner_radius_y() const
{
return m_corner_radius.y;
}

void FeRectangle::set_corner_radius_x( float rx )
{
update_corner_radius( rx, m_corner_radius.y, false );
}

void FeRectangle::set_corner_radius_y( float ry )
{
update_corner_radius( m_corner_radius.x, ry, false );
}

void FeRectangle::set_corner_radius( float rx, float ry )
{
update_corner_radius( rx, ry, false );
}

void FeRectangle::set_corner_radius( float r )
{
update_corner_radius( r, r, true );
}

void FeRectangle::update_corner_radius( float rx, float ry, bool r_auto )
{
if ( rx < 0.0 ) rx = 0.0;
if ( rx > 0.5 ) rx = 0.5;
if ( ry < 0.0 ) ry = 0.0;
if ( ry > 0.5 ) ry = 0.5;
if ( rx != m_corner_radius.x || ry != m_corner_radius.y || r_auto != m_corner_radius_auto )
{
m_corner_radius.x = rx;
m_corner_radius.y = ry;
m_corner_radius_auto = r_auto;
scale();
}
}

int FeRectangle::get_corner_point_count() const
{
return m_corner_point_count;
}

void FeRectangle::set_corner_point_count( int n )
{
if ( n < 1 ) n = 1;
if ( n > 32 ) n = 32; // arbitrary limit
if ( n != m_corner_point_count )
{
m_corner_point_count = n;
scale();
}
}

sf::Vector2f FeRectangle::alignTypeToVector( int type )
{
switch( type )
Expand Down Expand Up @@ -398,4 +465,15 @@ void FeRectangle::scale()
m_rect.setRotation( m_rotation );
m_rect.setSize( m_size );
m_rect.setOrigin(( m_origin.x + m_rotation_origin.x * m_size.x ), ( m_origin.y + m_rotation_origin.y * m_size.y ));
}
m_rect.setCornerPointCount( ( m_corner_radius.x > 0 || m_corner_radius.y > 0 ) ? m_corner_point_count : 1 );

if ( m_corner_radius_auto )
{
float s = m_corner_radius.x * std::min( m_size.x, m_size.y );
m_rect.setCornerRadius( sf::Vector2f( s, s ) );
}
else
{
m_rect.setCornerRadius( sf::Vector2f( m_corner_radius.x * m_size.x, m_corner_radius.y * m_size.y ) );
}
}
16 changes: 15 additions & 1 deletion src/fe_rectangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <SFML/Graphics.hpp>
#include "fe_presentable.hpp"
#include "fe_blend.hpp"
#include "rounded_rectangle_shape.hpp"

class FeSettings;

Expand Down Expand Up @@ -77,6 +78,10 @@ class FeRectangle : public sf::Drawable, public FeBasePresentable
int get_olg() const;
int get_olb() const;
int get_ola() const;
float get_corner_radius() const;
float get_corner_radius_x() const;
float get_corner_radius_y() const;
int get_corner_point_count() const;

void set_origin_x( float x );
void set_origin_y( float y );
Expand All @@ -93,6 +98,11 @@ class FeRectangle : public sf::Drawable, public FeBasePresentable
void set_olb( int b );
void set_ola( int a );
void set_olrgb( int r, int g, int b );
void set_corner_radius( float r );
void set_corner_radius( float rx, float ry );
void set_corner_radius_x( float rx );
void set_corner_radius_y( float ry );
void set_corner_point_count( int n );

int get_blend_mode() const;
void set_blend_mode( int b );
Expand All @@ -103,7 +113,7 @@ class FeRectangle : public sf::Drawable, public FeBasePresentable
void draw( sf::RenderTarget &target, sf::RenderStates states ) const;

private:
sf::RectangleShape m_rect;
sf::RoundedRectangleShape m_rect;
FeRectangle( const FeRectangle & );
FeRectangle &operator=( const FeRectangle & );

Expand All @@ -116,8 +126,12 @@ class FeRectangle : public sf::Drawable, public FeBasePresentable
FeRectangle::Alignment m_rotation_origin_type;
FeBlend::Mode m_blend_mode;
float m_rotation;
int m_corner_point_count;
sf::Vector2f m_corner_radius;
bool m_corner_radius_auto;

void scale();
void update_corner_radius( float rx, float ry, bool r_auto );
sf::Vector2f alignTypeToVector( int a );
};

Expand Down
5 changes: 5 additions & 0 deletions src/fe_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,11 @@ bool FeVM::on_new_layout()
.Prop(_SC("outline_green"), &FeRectangle::get_olg, &FeRectangle::set_olg )
.Prop(_SC("outline_blue"), &FeRectangle::get_olb, &FeRectangle::set_olb )
.Prop(_SC("outline_alpha"), &FeRectangle::get_ola, &FeRectangle::set_ola )
.Prop(_SC("corner_points"), &FeRectangle::get_corner_point_count, &FeRectangle::set_corner_point_count )
.Prop(_SC("corner_radius_x"), &FeRectangle::get_corner_radius_x, &FeRectangle::set_corner_radius_x )
.Prop(_SC("corner_radius_y"), &FeRectangle::get_corner_radius_y, &FeRectangle::set_corner_radius_y )
.Prop(_SC("corner_radius"), &FeRectangle::get_corner_radius, &FeRectangle::set_corner_radius )
.Overload<void (FeRectangle::*)(float, float)>(_SC("set_corner_radius"), &FeRectangle::set_corner_radius)
.Prop(_SC("blend_mode"), &FeRectangle::get_blend_mode, &FeRectangle::set_blend_mode )
.Func(_SC("set_outline_rgb"), &FeRectangle::set_olrgb )
.Func(_SC("set_anchor"), &FeRectangle::set_anchor )
Expand Down
128 changes: 128 additions & 0 deletions src/rounded_rectangle_shape.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
////////////////////////////////////////////////////////////
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

//
// https://github.com/SFML/SFML/wiki/Source%3A-Draw-Rounded-Rectangle
//
// ALTERATIONS FROM ORIGINAL
// - Added pragma to silence conversion warnings
// - Radius as Vector2f
// - Fallback to rectangle when corner point count is 1
// - Math in radians
//

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "rounded_rectangle_shape.hpp"
#include <cmath>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wdouble-promotion"
#pragma GCC diagnostic ignored "-Wfloat-conversion"

namespace sf
{
////////////////////////////////////////////////////////////
RoundedRectangleShape::RoundedRectangleShape(const Vector2f& size, const Vector2f& radius, unsigned int cornerPointCount)
{
m_size = size;
m_radius = radius;
m_corner_point_count = cornerPointCount;
update();
}

////////////////////////////////////////////////////////////
void RoundedRectangleShape::setSize(const Vector2f& size)
{
m_size = size;
update();
}

////////////////////////////////////////////////////////////
const Vector2f& RoundedRectangleShape::getSize() const
{
return m_size;
}

////////////////////////////////////////////////////////////
void RoundedRectangleShape::setCornerRadius(const Vector2f& radius)
{
m_radius = radius;
update();
}

////////////////////////////////////////////////////////////
const Vector2f& RoundedRectangleShape::getCornerRadius() const
{
return m_radius;
}

////////////////////////////////////////////////////////////
void RoundedRectangleShape::setCornerPointCount(unsigned int count)
{
m_corner_point_count = count;
update();
}

////////////////////////////////////////////////////////////
std::size_t RoundedRectangleShape::getPointCount() const
{
return m_corner_point_count*4;
}

////////////////////////////////////////////////////////////
sf::Vector2f RoundedRectangleShape::getPoint(std::size_t index) const
{
if(m_corner_point_count == 1)
{
switch (index)
{
default:
case 0: return Vector2f(0, 0);
case 1: return Vector2f(m_size.x, 0);
case 2: return Vector2f(m_size.x, m_size.y);
case 3: return Vector2f(0, m_size.y);
}
}

if(index >= m_corner_point_count*4)
return sf::Vector2f(0,0);

sf::Vector2f center;
unsigned int centerIndex = index/m_corner_point_count;
static const float half_pi = 3.141592654f / 2.0f;
float angle = (index-centerIndex) * half_pi / (m_corner_point_count-1);

switch(centerIndex)
{
case 0: center.x = m_size.x - m_radius.x; center.y = m_radius.y; break;
case 1: center.x = m_radius.x; center.y = m_radius.y; break;
case 2: center.x = m_radius.x; center.y = m_size.y - m_radius.y; break;
case 3: center.x = m_size.x - m_radius.x; center.y = m_size.y - m_radius.y; break;
}

return sf::Vector2f(m_radius.x*cos(angle)+center.x, -m_radius.y*sin(angle)+center.y);
}
} // namespace sf

#pragma GCC diagnostic pop
Loading

0 comments on commit e416eb8

Please sign in to comment.