Commits

Christian Fischer committed f3c2717

added label, font & bitmap font classes

  • Participants
  • Parent commits 4065c9a

Comments (0)

Files changed (7)

File src/common/wiesel/platform/sdl/sdl_gl.h

 
 #if WIESEL_USE_LIBSDL
 
+// don't define min/max macros - we're using the C++ template functions instead
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
 // include SDL OpenGL headers
 #include <GLee.h>
 

File src/common/wiesel/ui/bitmapfont.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "bitmapfont.h"
+
+#include "wiesel/gl/shaders.h"
+#include "wiesel/gl/texture/spritesheet.h"
+#include "wiesel/graph/2d/multisprite_node.h"
+
+#include "wiesel/util/log.h"
+
+#include <algorithm>
+
+
+using namespace wiesel;
+
+
+BitmapFont::BitmapFont() {
+	this->shader			= NULL;
+	this->spritesheet		= NULL;
+	this->char_spacing		= 0.0f;
+	this->line_spacing		= 0.0f;
+	return;
+}
+
+BitmapFont::BitmapFont(SpriteSheet *ss) {
+	this->shader			= NULL;
+	this->spritesheet		= NULL;
+	this->char_spacing		= 0.0f;
+	this->line_spacing		= 0.0f;
+
+	setSpriteSheet(ss);
+
+	return;
+}
+
+BitmapFont::~BitmapFont() {
+	setSpriteSheet(NULL);
+	setShader(NULL);
+	return;
+}
+
+
+void BitmapFont::setSpriteSheet(SpriteSheet* ss) {
+	if (ss != this->spritesheet) {
+		if (this->spritesheet) {
+			this->spritesheet->release();
+			this->spritesheet = NULL;
+		}
+
+		if (ss) {
+			this->spritesheet = ss;
+			this->spritesheet->retain();
+		}
+	}
+
+	return;
+}
+
+
+void BitmapFont::setShader(ShaderProgram* shader) {
+	if (shader != this->shader) {
+		if (this->shader) {
+			this->shader->release();
+			this->shader = NULL;
+		}
+
+		if (shader) {
+			this->shader = shader;
+			this->shader->retain();
+		}
+	}
+
+	return;
+}
+
+
+
+
+void BitmapFont::onAssignToNode(MultiSpriteNode* node) const {
+	// when the node does not already have a valid shader,
+	// set the preferred shader of this font.
+	if (node->getShader() == NULL) {
+		node->setShader(this->getShader());
+	}
+
+	return;
+}
+
+
+void BitmapFont::onDeassignFromNode(MultiSpriteNode* node) const {
+	// when the node's shader was not altered,
+	// remove the default shader from this node
+	if (node->getShader() == this->getShader()) {
+		node->setShader(NULL);
+	}
+
+	return;
+}
+
+
+float BitmapFont::getCharWidth(char c) const {
+	SpriteFrame *frame = findSpriteForChar(c);
+	if (frame) {
+		return frame->getSize().width;
+	}
+
+	return 0.0f;
+}
+
+
+float BitmapFont::getCharHeight(char c) const {
+	SpriteFrame *frame = findSpriteForChar(c);
+	if (frame) {
+		return frame->getSize().height;
+	}
+
+	return 0.0f;
+}
+
+
+void BitmapFont::fillLabelNode(
+					MultiSpriteNode* msn,
+					const std::vector<std::string>& text,
+					float align
+) const {
+	float max_width = 0.0f;
+	float y = 0.0f;
+
+	float line_h  = 0.0f;
+	float space_w = 0.0f;
+	std::string test = " 0Aa";
+
+	// find some special frames
+	SpriteFrame *frame_questionmark	= findSpriteForChar('?');
+
+	// determine "typical" character width and height by using some default characters
+	for(std::string::iterator it=test.begin(); it!=test.end(); it++) {
+		SpriteFrame *frame = findSpriteForChar(*it);
+
+		if (frame) {
+			space_w = std::max(space_w, frame->getSize().width);
+			line_h  = std::max(line_h,  frame->getSize().height);
+		}
+	}
+
+	// when the text-align is set, we need to determine the maximum text width
+	if (align != 0.0f) {
+		for(std::vector<std::string>::const_iterator it=text.begin(); it!=text.end(); it++) {
+			float line_width = getStringWidth(*it);
+
+			if (max_width < line_width) {
+				max_width = line_width;
+			}
+		}
+	}
+
+	// start with the bottom line...
+	for(std::vector<std::string>::const_reverse_iterator it=text.rbegin(); it!=text.rend(); it++) {
+		float x = 0.0f;
+
+		// when the text-align is set, compute the required offset.
+		if (align != 0.0f) {
+			float line_width = getStringWidth(*it);
+			x += ((max_width - line_width) * align);
+		}
+
+		// add a frame for each character
+		for(std::string::const_iterator s_it=it->begin(); s_it!=it->end(); s_it++) {
+			SpriteFrame *frame = findSpriteForChar(*s_it);
+
+			if (frame) {
+				msn->addSprite(frame, x, y);
+				x += frame->getSize().width;
+			}
+			else {
+				switch(*s_it) {
+					case ' ': {
+						// space is just a space...
+						x += space_w;
+						break;
+					}
+
+					default: {
+						// when the frame was not found, try to replace it with an question mark
+						if (frame_questionmark) {
+							msn->addSprite(frame_questionmark, x, y);
+							x += frame_questionmark->getSize().width;
+						}
+						else {
+							// when no question mark is available, just leave that part empty
+							x += space_w;
+						}
+
+						break;
+					}
+				}
+			}
+
+			x += getCharSpacing();
+		}
+
+		y += getStringHeight(*it);
+		y += getLineSpacing();
+	}
+
+	return;
+}
+
+
+
+
+
+SpriteFrame *BitmapFont::findSpriteForChar(char c) const {
+	assert(getSpriteSheet());
+	SpriteFrame *frame = NULL;
+
+	if (getSpriteSheet()) {
+		std::string sprite_name(1, c);
+		frame = getSpriteSheet()->get(sprite_name);
+	}
+
+	return frame;
+}

File src/common/wiesel/ui/bitmapfont.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_UI_BITMAPFONT_H__
+#define __WIESEL_UI_BITMAPFONT_H__
+
+#include "font.h"
+
+namespace wiesel {
+
+	// predeclaration
+
+	class SpriteFrame;
+	class SpriteSheet;
+	class ShaderProgram;
+
+
+
+	/**
+	 * @brief A font class implementing a bitmap font, provided from a spritesheet.
+	 */
+	class BitmapFont : public Font
+	{
+	public:
+		/**
+		 * @brief Creates a new, empty BitmapFont object.
+		 */
+		BitmapFont();
+
+		/**
+		 * @brief Creates a new BitmapFont object with a SpriteSheet as source.
+		 */
+		BitmapFont(SpriteSheet *ss);
+
+		virtual ~BitmapFont();
+		
+	// setter / getter
+	public:
+		/**
+		 * @brief Set the SpriteSheet, which provides the images for this font.
+		 */
+		void setSpriteSheet(SpriteSheet *ss);
+
+		/**
+		 * @brief Get the SpriteSheet assigned to this node.
+		 */
+		inline SpriteSheet *getSpriteSheet() const {
+			return spritesheet;
+		}
+
+		/**
+		 * @brief Set the preferred shader to be used for rendering.
+		 * Will be set for the target label node, if there is not already a shader configured.
+		 */
+		void setShader(ShaderProgram *shader);
+
+		/**
+		 * @brief Get the preferred shader for this font.
+		 */
+		inline ShaderProgram *getShader() const {
+			return shader;
+		}
+
+		/**
+		 * @brief Sets an additional distance between characters.
+		 * This value can be negative to make characters overlap.
+		 */
+		void setCharSpacing(float w);
+
+		/**
+		 * @brief Get the current spacing between characters.
+		 */
+		inline float getCharSpacing() const {
+			return char_spacing;
+		}
+
+		/**
+		 * @brief Sets an additional distance between lines.
+		 */
+		void setLineSpacing(float w);
+
+		/**
+		 * @brief Get the current spacing between lines.
+		 */
+		inline float getLineSpacing() const {
+			return line_spacing;
+		}
+
+	// implement Font members
+	public:
+		virtual void onAssignToNode(MultiSpriteNode *node) const;
+		virtual void onDeassignFromNode(MultiSpriteNode *node) const;
+
+		virtual float getCharWidth(char c) const;
+		virtual float getCharHeight(char c) const;
+
+		virtual void fillLabelNode(
+						MultiSpriteNode *msn,
+						const std::vector<std::string> &text,
+						float align=0.0f
+		) const;
+
+	protected:
+		/**
+		 * @brief Find a SpriteFrame within the current SpriteSheet,
+		 * which represents the given character.
+		 * @return The matching SpriteFrame, or NULL, if no SpriteFrame was found.
+		 */
+		virtual SpriteFrame *findSpriteForChar(char c) const;
+
+	private:
+		SpriteSheet*		spritesheet;
+		ShaderProgram*		shader;
+
+		float				char_spacing;
+		float				line_spacing;
+	};
+
+}
+
+#endif	// __WIESEL_UI_BITMAPFONT_H__

File src/common/wiesel/ui/font.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "font.h"
+
+
+using namespace wiesel;
+using namespace std;
+
+
+Font::Font() {
+	return;
+}
+
+Font::~Font() {
+	return;
+}
+
+
+void Font::onAssignToNode(MultiSpriteNode* node) const {
+	return;
+}
+
+
+void Font::onDeassignFromNode(MultiSpriteNode* node) const {
+	return;
+}
+
+
+float Font::getStringWidth(const std::string &text) const {
+	float width = 0.0f;
+
+	for(string::const_iterator it=text.begin(); it!=text.end(); it++) {
+		width += getCharWidth(*it);
+	}
+
+	return width;
+}
+
+
+float Font::getStringHeight(const std::string &text) const {
+	float height = 0.0f;
+
+	for(string::const_iterator it=text.begin(); it!=text.end(); it++) {
+		float char_height = getCharHeight(*it);
+
+		if (height < char_height) {
+			height = char_height;
+		}
+	}
+
+	return height;
+}
+
+
+void Font::fillLabelNode(MultiSpriteNode* msn, const std::string& text, float align) const {
+	string::size_type current	= 0;
+	string::size_type next		= 0;
+	vector<string> lines;
+
+	while((next = text.find('\n', current)) != string::npos) {
+		lines.push_back(text.substr(current, next - current));
+		current = next + 1;
+	}
+
+	if (current) {
+		// add the last part of the string
+		lines.push_back(text.substr(current));
+	}
+	else {
+		// there was no linebreak in this string, so we can take the full text
+		lines.push_back(text);
+	}
+
+	fillLabelNode(msn, lines, align);
+}
+

File src/common/wiesel/ui/font.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_UI_FONT_H__
+#define	__WIESEL_UI_FONT_H__
+
+#include "wiesel/util/shared_object.h"
+
+#include <string>
+#include <vector>
+
+
+namespace wiesel {
+
+	// predeclaration
+
+	class MultiSpriteNode;
+
+
+	/**
+	 * @brief A class used by \ref LabelNode
+	 */
+	class Font : public virtual SharedObject
+	{
+	protected:
+		Font();
+
+	private:
+		Font(const Font&) {};
+
+	public:
+		virtual ~Font();
+
+	public:
+		/**
+		 * @brief This font will be assigned to a specific node.
+		 * The font object may perform some initialization here.
+		 * @param node	The node this font will be assigned to.
+		 */
+		virtual void onAssignToNode(MultiSpriteNode *node) const;
+
+		/**
+		 * @brief This font will be deassigned from a node, which has previously used this font.
+		 * The font object may undo some settings, which were initialized in onAssignToNode.
+		 * @param node	The node this font will be unassigned from.
+		 */
+		virtual void onDeassignFromNode(MultiSpriteNode *node) const;
+
+		/**
+		 * @brief Measure a character's width.
+		 */
+		virtual float getCharWidth(char c) const = 0;
+
+		/**
+		 * @brief Measure a string's width.
+		 */
+		virtual float getStringWidth(const std::string &text) const;
+
+
+		/**
+		 * @brief Measure a character's height.
+		 */
+		virtual float getCharHeight(char c) const = 0;
+
+		/**
+		 * @brief Measure a string's height.
+		 */
+		virtual float getStringHeight(const std::string &text) const;
+
+
+		/**
+		 * @brief Fills a Label node with image content to display the given text.
+		 * The text may contain linebreaks.
+		 * @param msn		A MultiSpriteNode (usually a LabelNode), which should display the text.
+		 * @param text		The text to be displayed.
+		 * @param align		A float value controlling the alignment of the text.
+		 *						0.0 means left aligned
+		 *						0.5 means centered
+		 *						1.0 means right aligned
+		 */
+		virtual void fillLabelNode(
+						MultiSpriteNode *msn,
+						const std::string &text,
+						float align=0.0f
+		) const;
+
+		/**
+		 * @brief Fills a Label node with image content to display the given text.
+		 * @param msn		A MultiSpriteNode (usually a LabelNode), which should display the text.
+		 * @param text		A vector containing mulitple lines of text.
+		 * @param align		A float value controlling the alignment of the text.
+		 *						0.0 means left aligned
+		 *						0.5 means centered
+		 *						1.0 means right aligned
+		 */
+		virtual void fillLabelNode(
+						MultiSpriteNode *msn,
+						const std::vector<std::string> &text,
+						float align=0.0f
+		) const = 0;
+
+	};
+
+}
+
+#endif	// __WIESEL_UI_FONT_H__
+

File src/common/wiesel/ui/label_node.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "label_node.h"
+#include "font.h"
+
+using namespace wiesel;
+
+LabelNode::LabelNode() {
+	this->font		= NULL;
+	this->align		= 0.0f;
+}
+
+LabelNode::~LabelNode() {
+	setFont(NULL);
+	return;
+}
+
+
+
+void LabelNode::setFont(Font* font) {
+	if (this->font != font) {
+		if (this->font) {
+			this->font->release();
+			this->font = NULL;
+		}
+
+		if (font) {
+			this->font = font;
+			this->font->retain();
+		}
+
+		updateLabelContent();
+	}
+
+	return;
+}
+
+
+void LabelNode::setText(const std::string& text) {
+	if (this->text != text) {
+		this->text  = text;
+
+		updateLabelContent();
+	}
+
+	return;
+}
+
+
+void LabelNode::setTextAlign(float align) {
+	if (this->align != align) {
+		this->align  = align;
+
+		updateLabelContent();
+	}
+
+	return;
+}
+
+
+
+void LabelNode::updateLabelContent() {
+	this->clear();
+
+	if (
+			getFont() != NULL
+		&&	getText().empty() == false
+	) {
+		getFont()->fillLabelNode(this, getText(), getTextAlign());
+	}
+
+	return;
+}
+

File src/common/wiesel/ui/label_node.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_UI_LABELNODE_H__
+#define	__WIESEL_UI_LABELNODE_H__
+
+#include "wiesel/graph/2d/multisprite_node.h"
+
+#include <string>
+
+
+namespace wiesel {
+
+	// predeclaration
+	class Font;
+
+
+	/**
+	 * @brief A node which can display multiline texts.
+	 */
+	class LabelNode : public MultiSpriteNode
+	{
+	public:
+		LabelNode();
+		virtual ~LabelNode();
+
+		/**
+		 * @brief Set the current font which will be used to display text for this label.
+		 */
+		void setFont(Font *font);
+
+		/**
+		 * @brief Get the current font of this label.
+		 */
+		inline const Font *getFont() const {
+			return font;
+		}
+		
+		/**
+		 * @brief Set the text to be displayed.
+		 * @param text
+		 */
+		void setText(const std::string &text);
+		
+		/**
+		 * @brief Get the current text of this node.
+		 */
+		inline const std::string &getText() const {
+			return text;
+		}
+
+		/**
+		 * @brief Set the align of the text within this node.
+		 * @param align		The text's align:
+		 *					0.0 means left aligned.
+		 *					0.5 means centered.
+		 *					1.0 means right aligned.
+		 */
+		void setTextAlign(float align);
+
+		/**
+		 * @brief Get the current align of this label.
+		 */
+		inline float getTextAlign() const {
+			return align;
+		}
+
+	protected:
+		/**
+		 * @brief Update the label's content, if possible.
+		 */
+		void updateLabelContent();
+
+	private:
+		Font*			font;
+
+		std::string		text;
+		float			align;
+	};
+
+}
+
+#endif	// __WIESEL_UI_LABELNODE_H__
+