Skip to content

Release 1.4.0

Latest
Compare
Choose a tag to compare
@SSBMTonberry SSBMTonberry released this 01 Oct 18:18
· 24 commits to master since this release
ccc4a3d

Should support the most recent version of Tiled: 1.10.2.

Features

  • Tiled 1.9 support (#68)
  • Tiled 1.8 support (#60)
    • Class and enum properties: When having maps related to a Project, you can use the class property with your own class definitions. Same goes for Tiled `enums``.
fs::path pathToUse = fs::path("path/to/project.tiled-project");
tson::Project project{pathToUse};
auto folderFiles = project.getFolders().at(0).getFiles();

for(fs::path &f: folderFiles)
{
    fs::path path = project.getFolders().at(0).getPath() / f.filename();
    std::string filename = f.filename().generic_string();
    if(filename == "map1.json")
    {
        tson::Tileson t{&project};
        std::unique_ptr<tson::Map> m = t.parse(path);
        tson::Layer *objectLayer = m->getLayer("Da Object Layer");

        //Get class from object
        tson::TiledClass *objectClass = objectLayer->firstObj("TestObject")->getClass(); 
        
        //Asserts as example how to use members
        REQUIRE(objectClass != nullptr);
        REQUIRE(objectClass->getName() == "Enemy");
        REQUIRE(objectClass->get<int>("hp") == 10);
        REQUIRE(objectClass->get<std::string>("name") == "Galderino");

        //Get class from tile
        tson::Tile *tile = m->getTileset("demo-tileset")->getTile(1);
        tson::TiledClass *tileClass = tile->getClass();

        //Example how to get member of different types with asserts
        REQUIRE(objectClass->getMember("Age")->getType() == tson::Type::Int);
        REQUIRE(objectClass->getMember("Age")->getValue<int>() == 49);
        REQUIRE(objectClass->get<int>("Age") == 49);
        REQUIRE(objectClass->getMember("CanDestroy")->getType() == tson::Type::Boolean);
        REQUIRE(objectClass->get<bool>("CanDestroy"));
        REQUIRE(objectClass->getMember("ExtraFile")->getType() == tson::Type::File);
        REQUIRE(objectClass->get<fs::path>("ExtraFile") == fs::path("../ultimate_test.json"));
        REQUIRE(objectClass->getMember("MoneyInBag")->getType() == tson::Type::Float);
        REQUIRE(tson::Tools::Equal(objectClass->get<float>("MoneyInBag"), 16.9344f));
        REQUIRE(objectClass->getMember("MyObject")->getType() == tson::Type::Object);
        REQUIRE(objectClass->get<uint32_t>("MyObject") == 39);
        REQUIRE(objectClass->getMember("Name")->getType() == tson::Type::String);
        REQUIRE(objectClass->get<std::string>("Name") == "James Testolini");
        REQUIRE(objectClass->getMember("ShoeColor")->getType() == tson::Type::Color);
        tson::Colori color = objectClass->get<tson::Colori>("ShoeColor");
        REQUIRE(color == "#ff069504");
        REQUIRE(color.a == 0xff);
        REQUIRE(color.r == 0x06);
        REQUIRE(color.g == 0x95);
        REQUIRE(color.b == 0x04);

        //Example of different enum properties stored within objects
        //Numeric and string based enums with and without flag properties
        tson::Object *enumObj = objectLayer->firstObj("TestObjectEnum");
        tson::TiledClass *objectClassEnum = enumObj->getClass(); //Object is changed from default values
        tson::TiledClass *tileClassEnum = tileClass;
        
        REQUIRE(enumObj->getProp("num_enum") != nullptr);
        tson::EnumValue objPropNumEnum = enumObj->get<tson::EnumValue>("num_enum");
        REQUIRE(enumObj->getProp("num_enum_flags") != nullptr);
        tson::EnumValue objPropNumEnumFlags = enumObj->get<tson::EnumValue>("num_enum_flags");
        REQUIRE(enumObj->getProp("str_enum") != nullptr);
        tson::EnumValue objPropStrEnum = enumObj->get<tson::EnumValue>("str_enum");
        REQUIRE(enumObj->getProp("str_enum_flags") != nullptr);
        tson::EnumValue objPropStrEnumFlags = enumObj->get<tson::EnumValue>("str_enum_flags");


        REQUIRE(objPropNumEnum.getValue() == 3); 
        REQUIRE(objPropNumEnum.getValueName() == "GetNumber"); 
        REQUIRE(objPropNumEnumFlags.getValue() == 9); 
        //Flags enums (numeric and string) may use custom enum classes, as long as they have applied flags logic applied to them. See details how this can be achieved below this code example
        REQUIRE(objPropNumEnumFlags.hasFlag(tson::TestEnumNumberFlags::HasCalculatorFlag | tson::TestEnumNumberFlags::HasInvisibilityFlag)); 
        REQUIRE(objPropStrEnum.getValue() == 2); 
        REQUIRE(objPropStrEnum.getValueName() == "DeletePlayer"); 
        REQUIRE(objPropStrEnumFlags.getValue() == 6); 
        REQUIRE(objPropStrEnumFlags.hasFlag(tson::TestEnumStringFlags::HasJobFlag | tson::TestEnumStringFlags::HasHouseFlag));

        //Another example with flags more in depth
        tson::EnumValue numEnumC2 = someClass.getMember("NumFlag")->getValue<tson::EnumValue>();
        tson::EnumValue strEnumC2 = someClass.getMember("StrFlag")->getValue<tson::EnumValue>(); //Not used here, but will work in the same way

        REQUIRE(someClass.getMember("NumFlag")->getType() == tson::Type::Enum);
        REQUIRE(numEnumC2.getValue() == 10);
        REQUIRE(numEnumC2.hasFlag(tson::TestEnumNumberFlags::HasBombFlag | tson::TestEnumNumberFlags::HasInvisibilityFlag)); //Has both these flags - OK
        REQUIRE(numEnumC2.hasFlag(tson::TestEnumNumberFlags::HasBombFlag)); // Has this flag - OK
        REQUIRE(numEnumC2.hasFlag(tson::TestEnumNumberFlags::HasInvisibilityFlag)); // Has this flag - OK
        REQUIRE(numEnumC2.hasAnyFlag(tson::TestEnumNumberFlags::HasBombFlag | tson::TestEnumNumberFlags::HasHumorFlag)); //hasAnyFlag is okay as long as one of the flags here are set
        REQUIRE(!numEnumC2.hasFlag(tson::TestEnumNumberFlags::HasHumorFlag)); //Doesn't have this flag - OK
    }
}

The enum bitflags used in the examples above, uses a macro defined in include/common/EnumBitflags.hpp to be able to use them for bitflag checks. The only restriction this macro has, it's that it requires the tson namespace of any enums using it. With that in mind, here is an example how to create a flags enum:

namespace tson
{
    enum class ExampleFlags : uint32_t
    {
        None = 0,
        Big = 1 << 0,
        Slippery = 1 << 1,
        Funny = 1 << 2,
        Lazy = 1 << 3,
        All = Big | Slippery | Funny | Lazy
    };
}

TILESON_ENABLE_BITMASK_OPERATORS(ExampleFlags)

If you need the flags to be another namespace: Feel free to just steal the code and modify it for you own use.

  • Added quom as amalgamate tool for OSX (#82) - Thanks to dmlary
  • Now using Github Actions instead of Travis for CI (#50) - Thanks to Laguna1989
  • C++20 support (#53) - Thanks to gamecoder-nz

Improvements

  • Only include external_libs folder if examples or tests are required (#96) - Thanks to Laguna1989
  • Tests are now stricter and treats warnings as errors (#90) - Thanks to dmlary
  • CI improvements: Added MacOS, separated CI by system and added Clang 12 and 13 support on Linux (#88)
  • Fixed some Apple Clang 13 compile warnings (#84) - Thanks to dmlary
  • Updated Catch2 to support GCC 11.2 (#59)
  • Added missing properties to tson::Text (#75)

Breaking changes

  • Should be none.

Bug-fixes

  • Fixed bug where template objects did not correctly override properties (#100) - Thanks to jpeletier
  • Fixed bugs related to not being able to resolve TiledEnums in certain contexts (#98)
  • Tile properties should now be properly loaded when using multiple tilesets. (#54) - Thanks to Laguna1989
  • Added missing virtual destructor to IJson and IDecompressor. (#47) - Thanks to matthew-nagy