Design Issue - Making a Font Global (C++, Marmalade)

151 views Asked by At

I have a Marmalade C++ project where the built in font doesn't scale to screen size. To deal with this issue I'm making a custom font, which is basically a png and a .xml file, containing the (0,0) vector of each character, and each character's size. I'm then creating an instance of the png, and drawing regions of it in a for loop to write on the screen.

The issue I'm having is the scope of this class. I want it to be used throughout the entire project. So the static DebugLogger would use this font, any UI's, or GameObjects, anything which need characters, would use this font. Almost like it's pre-built into the system.

The Logger in this project is a static class, with static functions. The custom font class I currently have is a Singleton, as is my understanding, it must be an instantiated object for the program to draw images of it. So I did not make it static. Is there a clear cut answer to this type of problem? The issue is the static class won't create a reference to a singleton, and I've been told the singleton is to be avoided from a design perspective anyway!

Thanks in advance guys!

Here's the code for reference:

CustomFontClass

#ifndef _CHARACTER_SET_H_
#define _CHARACTER_SET_H_

#include "Iw2D.h"
#include "Singleton.h"
#include "BaseImage.h"
#include <map>
#include <string>

typedef CIwArray<std::string> STR_ARR;

class CharacterSet : public Singleton<CharacterSet>
{
public:
    CharacterSet();

    void Write(std::string, CIwFVec2, float);
    void Write(std::string, float, float, float);
    void Write(char, CIwFVec2, float);
    void Write(char, float, float, float);

    bool IsInitialised() const { return mIsInitialised; }

    // Space between characters is equivalent to 1 character width. This float multiplies that number. Default is .55f
    void SetFontSpacing(float);

protected:
    BaseImage* mspCharacters;
    bool Initialise();

private:
    std::map<const char, CIwFVec2> mFontMap;
    static const std::string TEXTURE_PATH;
    static const std::string TEXTURE_NAME;
    static const CIwFVec2 mFontSize;
        float mFontSpacing;
        STR_ARR maTextureLocations;
        bool mIsInitialised;
};


    #define CHARACTERSET Singleton<CharacterSet>::GetInstance()

    #endif

cpp

#include "Iw2D.h"
#include "Singleton.h"
#include "BaseImage.h"
#include "CharacterSet.h"
#include "IwLogger.h"
#include <map>
#include <sstream>
#include <string>

const std::string CharacterSet::TEXTURE_PATH = "textures/";
const std::string CharacterSet::TEXTURE_NAME = "font_main.png";
const CIwFVec2 CharacterSet::mFontSize = CIwFVec2(50, 63);


CharacterSet::CharacterSet() : Singleton<CharacterSet>()
{
    mFontSpacing = 0.55f;
    mIsInitialised = Initialise();
};

void CharacterSet::SetFontSpacing(float spacing)
{
    if (spacing != NULL)
    {
        mFontSpacing = spacing;
    }
};

void CharacterSet::Write(std::string text, CIwFVec2 position = CIwFVec2(50,50), float fontSize = 25.0f)
{
    if (!text.empty())
    {
        mspCharacters->SetSize(CIwFVec2(fontSize, fontSize));

        float newPosition = 0;
        for (char& c : text)
        {
            mspCharacters->SetPosition(CIwFVec2((position.x + newPosition), position.y));

            if (mFontMap.find(c) == mFontMap.end())
            {
                std::stringstream ss;
                std::string mCharRef;
                ss << c;
                ss >> mCharRef;

                std::string error = "CharacterSet::mFontMap[" + mCharRef + "] - Does not exist!";
                IW_LOG_ERROR(error);
            }
            else
            {
                mspCharacters->Render(mFontMap[c], mFontSize);
            }

            newPosition += (fontSize * mFontSpacing);
        }
    }
    else
    {
        IW_LOG_ERROR("CharacterSet::Write - std::string text is empty!");
    }

};

bool CharacterSet::Initialise()
{
    maTextureLocations.push_back(std::string(TEXTURE_PATH + TEXTURE_NAME));
    mspCharacters = new BaseImage(maTextureLocations[0].c_str());

    if (mspCharacters == NULL)
    {
        IW_LOG_ERROR("CharacterSet::mspCharacters - Failed to create BaseImage!");
        return false;
    }

    //Numerical symbols
    mFontMap['1'] = CIwFVec2(0, 0);
    mFontMap['2'] = CIwFVec2(50, 0);
    mFontMap['3'] = CIwFVec2(100, 0);
    mFontMap['4'] = CIwFVec2(150, 0);
    mFontMap['5'] = CIwFVec2(200, 0);
// ect... lots of these

IwLogger

#ifndef _IW_LOGGER_H_
#define _IW_LOGGER_H_

#include "IwDebug.h"
#include <string>

class IwLogger
{
    public:
        IwLogger();

        enum LogLevel
        {
            INFO,
            WARN,
            ERROR
        };

        static void Log(LogLevel level, std::string msg);
        static void Log(LogLevel level, std::string callingFunc, std::string msg);

        static void LogFailedResource(std::string callingFunc, std::string resourcePath);

        static void LogError(std::string msg) { Log(ERROR, msg); }
        static void LogWarn(std::string msg) { Log(WARN, msg); }
        static void LogInfo(std::string msg) { Log(INFO, msg); }

        static void LogError(std::string callingFunc, std::string msg) { Log(ERROR, callingFunc, msg); }
        static void LogWarn(std::string callingFunc, std::string msg) { Log(WARN, callingFunc, msg); }
        static void LogInfo(std::string callingFunc, std::string msg) { Log(INFO, callingFunc, msg); }
};

#define IW_LOG_ERROR(msg) IwLogger::LogError(__FUNCTION__, msg)
#define IW_LOG_WARN(msg) IwLogger::LogWarn(__FUNCTION__, msg)
#define IW_LOG_INFO(msg) IwLogger::LogInfo(__FUNCTION__, msg)

#define IW_LOG_FAILED_RES(resPath) IwLogger::LogFailedResource(__FUNCTION__, resPath)

#endif

cpp

#include "CharacterSet.h"
#include "IwLogger.h"

void IwLogger::Log(IwLogger::LogLevel level, std::string msg)
{
    switch (level)
    {
        case INFO:
            IwTrace(INFO, (msg.c_str()));
            break;
        case WARN:
            IwTrace(WARN, (msg.c_str()));
            break;
        case ERROR:
            IwTrace(ERROR, (msg.c_str()));
            break;
        default:
            IwTrace(ERROR, ("IwLogger::Log() - Uncatered for case! Nothing to log!"));
            break;
    }
}

void IwLogger::Log(IwLogger::LogLevel level, std::string callingFunc, std::string msg)
{
    std::string finalMsg = callingFunc + "() - " + msg;
    switch (level)
    {
        case INFO:
            IwTrace(INFO, (finalMsg.c_str()));
            break;
        case WARN:
            IwTrace(WARN, (finalMsg.c_str()));
            break;
        case ERROR:
            IwTrace(ERROR, (finalMsg.c_str()));
            break;
        default:
            IwTrace(ERROR, ("IwLogger::Log() - Uncatered for case! Nothing to log!"));
            break;
    }
}

void IwLogger::LogFailedResource(std::string callingFunc, std::string resourcePath)
{
    std::string msg = "Failed to load resource: " + resourcePath;
    LogError(callingFunc, msg);
}

The error messages:

1>c:\users\...\source\framework\customfont.h(12): error C2504: 'Singleton' : base class undefined (..\source\framework\BaseObject.cpp)  
1>c:\users\...\source\framework\customfont.h(12): error C2143: syntax error : missing ',' before '<' (..\source\framework\BaseObject.cpp)  
1>c:\users\nigel\...\source\framework\customfont.h(12): error C2504: 'Singleton' : base class undefined (..\source\framework\CustomFont.cpp)  
0

There are 0 answers