Skip to content

Nine Patch

Hapaxia edited this page Feb 20, 2025 · 13 revisions

Introduction

A class to draw a "nine patch".

This version of a Nine Patch is a class that takes a single texture (or a part of one) and splits it into nine separate cells/tiles/patches, which are defined by black lines on the outer pixel edge of the (part of the) texture (the texture - when displayed - does not show the single pixel thick edge around the entire texture). When the Nine Patch is resized, the corner tiles stay the same size whereas the other tiles stretch accordingly.

Black lines are drawn on the left and top pixel edges to define which parts of the texture stretch when resized.
Black lines are drawn on the right and bottom pixel edges to define which parts of the texture should be used to display overlapping content, if required.

Usage

Declaration

sw::NinePatch ninePatch;
creates a Nine Patch with the default size

Drawing

This class inherits from sf::Drawable so it is drawn in the same way as all SFML drawables:
window.draw(ninePatch);
where window is an sf::RenderWindow.

Note: actually, window could be any sf::RenderTarget.

Transformations

This class inherits from sf::Transformable so it has all the usual SFML transformations available.

Manipulation

Visual Representation

  • setTexture(sf::Texture texture, bool resetSize, bool resetRect)
    sets the sf::Texture to use. Using this function resets the size to the size of the texture and attempts to extract the new scaling sections from the texture. If resetSize is false, the size of the Nine Patch stays the same size after changing texture. Note that this does not perform minimum size checks. If resetSize is true, the size is set to match the target texture (the entire texture except the pixel border). If resetSize is omitted, it defaults to true. If resetRect is false, the texture rectangle is not changed from its current value. If resetRect is true, the texture rectangle is changed to cover the entire texture. If resetRect is omitted, it default to true.

  • setTexture()
    resets the texture to null. This allows the Nine Patch to be used as a coloured rectangle while it has no texture. Note that the scaling and content area sections are not updated until a new texture is set so the content area persists after removing the texture.

  • setSize(sf::Vector2f)
    sets the size (sf::Vector2f) of the final object (before transformations).

  • resetSize()
    resets the size (sf::Vector2f) of the final object (before transformations) to match the current texture (rectangle).

  • setTextureRect(sf::IntRect, bool resetSize)
    sets the rectangle (sf::IntRect) of the part of the texture to be used. If resetSize is true, the size of the Nine Patch is altered to match the texture rectangle otherwise the size stays the same size. Note that this does not perform minimum size checks. If resetSize is omitted, it defaults to true.

  • setColor(color)
    sets the colour (sf::Color) of the Nine Patch.

Information

  • getSize()
    returns a sf::Vector2f of the current size of the final object (before transformations)

  • getLocalBounds()
    returns an sf::FloatRect that contains the Nine Patch before any SFML transformations.

  • getGlobalBounds()
    returns an sf::FloatRect that contains the Nine Patch after any SFML transformations.

  • getLocalContentArea()
    returns an sf::FloatRect that contains the target area designed for content - before any SFML transformations.

  • getGlobalContentArea()
    returns an sf::FloatRect that contains the target area designed for content - after any SFML transformations.

  • isPointInsideTransformedContentArea(point)
    returns a bool representing if the transformated content area contains the passed point (sf::Vector2f). Note that this does not use the axis-aligned global content area; instead, it uses the actual non-axis-aligned content area.

  • getColor()
    returns an sf::Color of the current colour.

Simple Example

#include <SFML/Graphics.hpp>
#include <SelbaWard/NinePatch.hpp>
#include <iostream>
int main()
{
	sf::Texture texture{};
	if (!texture.loadFromFile("resources/pixelcyan9patch.png"))
	{
		std::cerr << "Unable to load texture." << std::endl;
		return EXIT_FAILURE;
	}
	sf::RenderWindow window(sf::VideoMode({ 800u, 600u }), "Nine Patch simple example");
	sw::NinePatch ninePatch{};
	ninePatch.setTexture(texture);
	while (window.isOpen())
	{
		while (const auto event{ window.pollEvent() }) if (event->is<sf::Event::Closed>()) window.close();
		ninePatch.setSize(window.mapPixelToCoords(sf::Mouse::getPosition(window)));
		window.clear(sf::Color(196u, 128u, 64u));
		window.draw(ninePatch);
		window.display();
	}
	return EXIT_SUCCESS;
}

The code above displays (it stretches to reach the mouse cursor):
Simple Example

The texture used for this example: Nine Patch texture

Note: the texture for this example is available, along with more examples, in the examples folder, although you can use your own images.

(NinePatch v1.4)