Search code examples
c++enumslualuabridge

Easiest way to pass an enumerated type from Lua to C++?


I am trying to load textures from a Lua script, to my game engine in C++.

The engine uses a class called "ResourceHolder" and the enumerated type is from a class called "ResourceIdenifiers".

My game scene creates its own ResourceHolder for both Textures & Fonts (as well as anything else I need). So I have namespaces for Textures::ID (enum type) and Fonts::ID.

So I simply create a TextureHolder object 'mTextures'

TextureHolder                       mTextures;

Then I simply load the textures in very easily with a singe line as so:

mTextures.load(Textures::Airplane2, "../GFX/Airplane2.png");

The problem is that I cannot use these enumerated types in Lua, despite my plan to have something like this in my lua.script file:

allTextures
{

--Airplanes
["Airplane1"]       = "../GFX/Airplane1.png",
["Airplane2"]       = "../GFX/Airplane2.png",

--Or something like this instead
["Textures::Airplane3"]         = "../GFX/Airplane3.png"

}

What is the easiest way to allow the Lua script to handle these enumerated types?

Here are my classes for ResourceIdentifier and ResourceHolder.

ResourceIdentifier.h

#ifndef RESOURCEIDENTIFIERS_H
#define RESOURCEIDENTIFIERS_H


// Forward declaration of SFML classes
namespace sf
{
class Texture;
class Font;
}

namespace Textures
{
enum ID
{
    //Airplanes
    Airplane1,
    Airplane2,
    Airplane3,
    Background1,
    Background2,
};
}

namespace Fonts
{
enum ID
{
    Main,
};
}

// Forward declaration and a few type definitions
template <typename Resource, typename Identifier>
class ResourceHolder;

typedef ResourceHolder<sf::Texture, Textures::ID> TextureHolder;
typedef ResourceHolder<sf::Font, Fonts::ID>         FontHolder;

#endif // RESOURCEIDENTIFIERS_H

ResourceHolder.h (less relevant)

#ifndef RESOURCEHOLDER_H
#define RESOURCEHOLDER_H

#include <map>
#include <string>
#include <memory>
#include <stdexcept>
#include <cassert>

#include <SFML/Graphics/Image.hpp>

template <typename Resource, typename Identifier>

//This class stores Identifier so they can be accessed.
class ResourceHolder
{
public:
    //This creates loads the texture from the filename, gives it an ID, and stores it in the std::map container mTextureMap.
    void load(Identifier id, const std::string& filename);

    void loadImage(Identifier id, const sf::Image& image);

    template <typename Parameter>
    void load(Identifier id, const std::string& filename, const Parameter& secondParam);

    //This gets the texture from the std::map container, so it can be used. It gets the Resource based on the texture's ID (name).
    Resource& get(Identifier id);
    const Resource& get(Identifier id) const;
    //^SFML book - Chapter 2 - "Accessing the Identifier" ??? For when you dont want to allow editing of the Texture???


private:
    //A map stores all of the Identifier. The std::map< (1 parameter) 'Name of Resource', (2 parameter) a unique pointer of the Resource).
    std::map<Identifier, std::unique_ptr<Resource> > mResourceMap;

};

#include "ResourceHolder.inl"

#endif // RESOURCEHOLDER_H

Solution

  • Here is the easiest way to do it is to actually just use what is basically a newbie's enumerated types in Lua, by copy/pasting the enumerated types from C++ to Lua (and deleting the commas) and then loading the textures into the image by name and path.

    I am using "LuaPlus" instead of LuaBridge. While LuaPlus is a PITA to install, it is superior (easier to use and understand) when correctly added to your project.

    Here are my enumerated types:

    namespace Textures
    {
        enum ID
        {
            //Airplanes
            Airplane1 = 1,
            Airplane2 = 2,
            Airplane3 = 3,
            //Backgrounds
            Background1 = 100,
            Background2 = 101,
        };
    }
    

    My lua script ends up looking like this:

    --Copy/Paste the Enumerated Types here, deleting the "," commas.
    Airplane1 = 1
    Airplane2 = 2
    Airplane3 = 3
    Background1 = 100
    Background2 = 101
    
    --All Textures are registered here.
    allTextures =
    {
    
    --Airplanes
    [Airplane1]         = "../GFX/Airplane1.png",
    [Airplane2]         = "../GFX/Airplane2.png",
    --Backgrounds
    [Background]        = "../GFX/Background.png",
    
    }
    

    Then in C++, call a function

    //LOAD GAME TEXTURES HERE
    void Scene::loadTextures()
    {
    LuaState* pLuaState = LuaState::Create();
    pLuaState->DoFile("../GFX/test.lua");
    LuaObject table = pLuaState->GetGlobals()["allTextures"];
    
    for(LuaTableIterator it(table); it; it.Next())
    {
        int key = it.GetKey().GetInteger();
        const char* value = it.GetValue().GetString();
        //std::cout<<"Key: "<<key<<", Value: "<<value<<std::endl;
        mTextures.load(static_cast<Textures::ID>(key), value);
    }
    
    }