Browse Source

this is a big one

* reworked some resource loading and mod init stuff
* texetures are now configured at runtime via .toml files
* moved from SRF to messagepack
* changed folder structures
* added the fmt library (for later)
opengl-renderer-broken
Martin Dørum 4 years ago
parent
commit
d808b8bcfb

+ 3
- 0
.gitmodules View File

@@ -16,3 +16,6 @@
[submodule "third_party/imgui-plot"]
path = third_party/imgui-plot
url = https://github.com/soulthreads/imgui-plot.git
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/fmtlib/fmt.git

+ 1
- 1
CMakeLists.txt View File

@@ -39,7 +39,7 @@ endif()

add_subdirectory(third_party)

set(libraries imgui SDL2 SDL2_image dl z)
set(libraries imgui fmt cpptoml msgpack SDL2 SDL2_image dl z)

# We want to be able to use C++20 designated initializers,
# but Clang doesn't support them yet.

+ 10
- 8
core.mod/CMakeLists.txt View File

@@ -7,14 +7,16 @@ set_target_properties(core.mod PROPERTIES OUTPUT_NAME mod PREFIX "")
target_link_libraries(core.mod libswan ${libraries})

set(assets
assets/entities/player-still.png
assets/entities/player-running.png
assets/tiles/grass.png
assets/tiles/air.png
assets/tiles/stone.png
assets/tiles/dirt.png
assets/tiles/leaves.png
assets/tiles/tree-trunk.png
assets/entity/player-still.png
assets/entity/player-still.toml
assets/entity/player-running.png
assets/entity/player-running.toml
assets/tile/grass.png
assets/tile/air.png
assets/tile/stone.png
assets/tile/dirt.png
assets/tile/leaves.png
assets/tile/tree-trunk.png
assets/misc/background-cave.png)
foreach(a ${assets})
configure_file("${a}" "${a}" COPYONLY)

core.mod/assets/entities/player-running.png → core.mod/assets/entity/player-running.png View File


+ 1
- 0
core.mod/assets/entity/player-running.toml View File

@@ -0,0 +1 @@
height = 64

core.mod/assets/entities/player-still.png → core.mod/assets/entity/player-still.png View File


+ 1
- 0
core.mod/assets/entity/player-still.toml View File

@@ -0,0 +1 @@
height = 64

core.mod/assets/tiles/air.png → core.mod/assets/tile/air.png View File


core.mod/assets/tiles/dirt.png → core.mod/assets/tile/dirt.png View File


core.mod/assets/tiles/grass.png → core.mod/assets/tile/grass.png View File


core.mod/assets/tiles/leaves.png → core.mod/assets/tile/leaves.png View File


core.mod/assets/tiles/stone.png → core.mod/assets/tile/stone.png View File


core.mod/assets/tiles/tree-trunk.png → core.mod/assets/tile/tree-trunk.png View File


+ 5
- 3
core.mod/src/DefaultWorldGen.cc View File

@@ -2,6 +2,8 @@

#include <algorithm>

#include "entities/PlayerEntity.h"

static int grassLevel(const siv::PerlinNoise &perlin, int x) {
return (int)(perlin.noise(x / 50.0, 0) * 13);
}
@@ -72,9 +74,9 @@ void DefaultWorldGen::genChunk(Swan::WorldPlane &plane, Swan::Chunk &chunk) {
}
}

Swan::BodyTrait::HasBody *DefaultWorldGen::spawnPlayer(Swan::WorldPlane &plane) {
Swan::BodyTrait::HasBody *DefaultWorldGen::spawnPlayer(const Swan::Context &ctx) {
int x = 0;
return dynamic_cast<Swan::BodyTrait::HasBody *>(
plane.spawnEntity("core::player", Swan::SRFFloatArray{
(float)x, (float)grassLevel(perlin_, x) - 4 }));
ctx.plane.spawnEntity(std::make_unique<PlayerEntity>(
ctx, Swan::Vec2{ (float)x, (float)grassLevel(perlin_, x) - 4 })));
}

+ 2
- 7
core.mod/src/DefaultWorldGen.h View File

@@ -6,11 +6,6 @@

class DefaultWorldGen: public Swan::WorldGen {
public:
class Factory: public Swan::WorldGen::Factory {
public:
WorldGen *create(Swan::World &world) override { return new DefaultWorldGen(world); }
};

DefaultWorldGen(Swan::World &world):
tGrass_(world.getTileID("core::grass")),
tDirt_(world.getTileID("core::dirt")),
@@ -18,12 +13,12 @@ public:
tAir_(world.getTileID("core::air")),
tTreeTrunk_(world.getTileID("core::tree-trunk")),
tLeaves_(world.getTileID("core::leaves")),
bgCave_(world.resources_.getImage("core::background-cave")) {}
bgCave_(world.resources_.getImage("core/misc/background-cave")) {}

void drawBackground(const Swan::Context &ctx, Swan::Win &win, Swan::Vec2 pos) override;
SDL_Color backgroundColor(Swan::Vec2 pos) override;
void genChunk(Swan::WorldPlane &plane, Swan::Chunk &chunk) override;
Swan::BodyTrait::HasBody *spawnPlayer(Swan::WorldPlane &plane) override;
Swan::BodyTrait::HasBody *spawnPlayer(const Swan::Context &ctx) override;

private:
Swan::Tile::ID genTile(Swan::TilePos pos);

+ 9
- 13
core.mod/src/entities/ItemStackEntity.cc View File

@@ -2,11 +2,11 @@

#include <random>

ItemStackEntity::ItemStackEntity(const Swan::Context &ctx, const Swan::SRF &params):
ItemStackEntity::ItemStackEntity(const Swan::Context &ctx, const PackObject &obj):
PhysicsEntity(SIZE, MASS) {
PhysicsEntity::body_.bounciness_ = 0.6;

readSRF(ctx, params);
deserialize(ctx, obj);

static std::uniform_real_distribution vx(-2.3f, 2.3f);
static std::uniform_real_distribution vy(-2.3f, -1.2f);
@@ -31,18 +31,14 @@ void ItemStackEntity::tick(const Swan::Context &ctx, float dt) {
ctx.plane.despawnEntity(*this);
}

void ItemStackEntity::readSRF(const Swan::Context &ctx, const Swan::SRF &srf) {
auto &arr = dynamic_cast<const Swan::SRFArray &>(srf);
auto *pos = dynamic_cast<Swan::SRFFloatArray *>(arr.val[0].get());
auto *name = dynamic_cast<Swan::SRFString *>(arr.val[1].get());

body_.pos_.set(pos->val[0], pos->val[1]);
item_ = &ctx.world.getItem(name->val);
void ItemStackEntity::deserialize(const Swan::Context &ctx, const PackObject &obj) {
body_.pos_ = obj.at("pos").as<Swan::Vec2>();
item_ = &ctx.world.getItem(obj.at("item").as<std::string>());
}

Swan::SRF *ItemStackEntity::writeSRF(const Swan::Context &ctx) {
return new Swan::SRFArray{
new Swan::SRFFloatArray{ body_.pos_.x, body_.pos_.y },
new Swan::SRFString{ item_->name_ },
Swan::Entity::PackObject ItemStackEntity::serialize(const Swan::Context &ctx, msgpack::zone &zone) {
return {
{ "pos", msgpack::object(body_.pos_, zone) },
{ "tile", msgpack::object(item_->name_, zone) },
};
}

+ 3
- 9
core.mod/src/entities/ItemStackEntity.h View File

@@ -4,18 +4,12 @@

class ItemStackEntity: public Swan::PhysicsEntity {
public:
class Factory: public Swan::Entity::Factory {
Swan::Entity *create(const Swan::Context &ctx, const Swan::SRF &params) override {
return new ItemStackEntity(ctx, params);
}
};

ItemStackEntity(const Swan::Context &ctx, const Swan::SRF &params);
ItemStackEntity(const Swan::Context &ctx, const PackObject &obj);

void draw(const Swan::Context &ctx, Swan::Win &win) override;
void tick(const Swan::Context &ctx, float dt) override;
void readSRF(const Swan::Context &ctx, const Swan::SRF &srf) override;
Swan::SRF *writeSRF(const Swan::Context &ctx) override;
void deserialize(const Swan::Context &ctx, const PackObject &obj) override;
PackObject serialize(const Swan::Context &ctx, msgpack::zone &zone) override;

private:
static constexpr float MASS = 80;

+ 24
- 10
core.mod/src/entities/PlayerEntity.cc View File

@@ -4,14 +4,24 @@

#include "ItemStackEntity.h"

PlayerEntity::PlayerEntity(const Swan::Context &ctx, const Swan::SRF &params):
PlayerEntity::PlayerEntity(const Swan::Context &ctx, const PackObject &obj):
PhysicsEntity(SIZE, MASS), inventory_(INVENTORY_SIZE),
anims_{
Swan::Animation(ctx.resources.getImage("core::player-still"), 0.8),
Swan::Animation(ctx.resources.getImage("core::player-running"), 1, SDL_FLIP_HORIZONTAL),
Swan::Animation(ctx.resources.getImage("core::player-running"), 1) } {
Swan::Animation(ctx.resources.getImage("core/entity/player-still"), 0.8),
Swan::Animation(ctx.resources.getImage("core/entity/player-running"), 1, SDL_FLIP_HORIZONTAL),
Swan::Animation(ctx.resources.getImage("core/entity/player-running"), 1) } {

readSRF(ctx, params);
deserialize(ctx, obj);
}

PlayerEntity::PlayerEntity(const Swan::Context &ctx, Swan::Vec2 pos):
PhysicsEntity(SIZE, MASS), inventory_(INVENTORY_SIZE),
anims_{
Swan::Animation(ctx.resources.getImage("core/entity/player-still"), 0.8),
Swan::Animation(ctx.resources.getImage("core/entity/player-running"), 1, SDL_FLIP_HORIZONTAL),
Swan::Animation(ctx.resources.getImage("core/entity/player-running"), 1) } {

body_.pos_ = pos;
}

void PlayerEntity::draw(const Swan::Context &ctx, Swan::Win &win) {
@@ -76,11 +86,15 @@ void PlayerEntity::tick(const Swan::Context &ctx, float dt) {
}
}

void PlayerEntity::readSRF(const Swan::Context &ctx, const Swan::SRF &srf) {
auto pos = dynamic_cast<const Swan::SRFFloatArray &>(srf);
body_.pos_.set(pos.val[0], pos.val[1]);
void PlayerEntity::deserialize(const Swan::Context &ctx, const PackObject &obj) {
//body_.deserialize(obj["body"]);
}

Swan::SRF *PlayerEntity::writeSRF(const Swan::Context &ctx) {
return new Swan::SRFFloatArray{ body_.pos_.x, body_.pos_.y };
Swan::Entity::PackObject PlayerEntity::serialize(const Swan::Context &ctx, msgpack::zone &zone) {
return {};
/*
return Swan::MsgPackObject{
{ "body", body_.serialize(w) },
};
*/
}

+ 4
- 10
core.mod/src/entities/PlayerEntity.h View File

@@ -5,22 +5,16 @@

class PlayerEntity: public Swan::PhysicsEntity, public Swan::InventoryTrait::HasInventory {
public:
class Factory: public Swan::Entity::Factory {
public:
Swan::Entity *create(const Swan::Context &ctx, const Swan::SRF &params) override {
return new PlayerEntity(ctx, params);
}
};

PlayerEntity(const Swan::Context &ctx, const Swan::SRF &params);
PlayerEntity(const Swan::Context &ctx, const PackObject &obj);
PlayerEntity(const Swan::Context &ctx, Swan::Vec2 pos);

Swan::InventoryTrait::Inventory &getInventory() override { return inventory_; }

void draw(const Swan::Context &ctx, Swan::Win &win) override;
void update(const Swan::Context &ctx, float dt) override;
void tick(const Swan::Context &ctx, float dt) override;
void readSRF(const Swan::Context &ctx, const Swan::SRF &srf) override;
Swan::SRF *writeSRF(const Swan::Context &ctx) override;
void deserialize(const Swan::Context &ctx, const PackObject &obj) override;
PackObject serialize(const Swan::Context &ctx, msgpack::zone &zone) override;

private:
static constexpr int INVENTORY_SIZE = 18;

+ 22
- 23
core.mod/src/main.cc View File

@@ -7,66 +7,65 @@
extern "C" void mod_init(Swan::Mod &mod) {
mod.init("core");

mod.registerImage({ "air", "tiles/air.png" });
mod.registerImage({ "stone", "tiles/stone.png" });
mod.registerImage({ "dirt", "tiles/dirt.png" });
mod.registerImage({ "grass", "tiles/grass.png" });
mod.registerImage({ "tree-trunk", "tiles/tree-trunk.png" });
mod.registerImage({ "leaves", "tiles/leaves.png" });
mod.registerImage({ "player-running", "entities/player-running.png", 64 });
mod.registerImage({ "player-still", "entities/player-still.png", 64 });
mod.registerImage({ "background-cave", "misc/background-cave.png" });
mod.registerImage({ "background-cave-2", "misc/background-cave-2.png" });
mod.registerImage("tile/air");
mod.registerImage("tile/stone");
mod.registerImage("tile/dirt");
mod.registerImage("tile/grass");
mod.registerImage("tile/tree-trunk");
mod.registerImage("tile/leaves");
mod.registerImage("entity/player-running");
mod.registerImage("entity/player-still");
mod.registerImage("misc/background-cave");

mod.registerTile({
.name = "air",
.image = "core::air",
.image = "core/tile/air",
.is_solid = false,
});
mod.registerTile({
.name = "stone",
.image = "core::stone",
.image = "core/tile/stone",
.dropped_item = "core::stone",
});
mod.registerTile({
.name = "dirt",
.image = "core::dirt",
.image = "core/tile/dirt",
.dropped_item = "core::dirt",
});
mod.registerTile({
.name = "grass",
.image = "core::grass",
.image = "core/tile/grass",
.dropped_item = "core::dirt",
});
mod.registerTile({
.name = "tree-trunk",
.image = "core::tree-trunk",
.image = "core/tile/tree-trunk",
.dropped_item = "core::tree-trunk",
});
mod.registerTile({
.name = "leaves",
.image = "core::leaves",
.image = "core/tile/leaves",
});

mod.registerItem({
.name = "stone",
.image = "core::stone",
.image = "core/tile/stone",
});
mod.registerItem({
.name = "dirt",
.image = "core::dirt",
.image = "core/tile/dirt",
});
mod.registerItem({
.name = "grass",
.image = "core::grass",
.image = "core/tile/grass",
});
mod.registerItem({
.name = "tree-trunk",
.image = "core::tree-trunk",
.image = "core/tile/tree-trunk",
});

mod.registerWorldGen("default", std::make_unique<DefaultWorldGen::Factory>());
mod.registerWorldGen<DefaultWorldGen>("default");

mod.registerEntity("player", std::make_unique<PlayerEntity::Factory>());
mod.registerEntity("item-stack", std::make_unique<ItemStackEntity::Factory>());
mod.registerEntity<PlayerEntity>("player");
mod.registerEntity<ItemStackEntity>("item-stack");
}

+ 0
- 1
libswan/CMakeLists.txt View File

@@ -12,7 +12,6 @@ add_library(libswan SHARED
src/OS.cc
src/PerfCounter.cc
src/Resource.cc
src/SRF.cc
src/Tile.cc
src/World.cc
src/WorldPlane.cc)

+ 8
- 8
libswan/include/swan/Entity.h View File

@@ -2,11 +2,11 @@

#include <memory>
#include <optional>
#include <msgpack.hpp>

#include "common.h"
#include "log.h"
#include "traits/BodyTrait.h"
#include "SRF.h"

namespace Swan {

@@ -16,11 +16,11 @@ class Game;

class Entity {
public:
class Factory {
public:
virtual ~Factory() = default;
virtual Entity *create(const Context &ctx, const SRF &params) = 0;
std::string name_;
using PackObject = std::unordered_map<std::string_view, msgpack::object>;
struct Factory {
const std::string name;
std::unique_ptr<Entity> (*create)(const Context &ctx, const PackObject &obj);
};

virtual ~Entity() = default;
@@ -30,8 +30,8 @@ public:
virtual void tick(const Context &ctx, float dt) {}
virtual void despawn() {}

virtual void readSRF(const Swan::Context &ctx, const SRF &srf) {}
virtual SRF *writeSRF(const Swan::Context &ctx) { return new SRFNone(); }
virtual void deserialize(const Swan::Context &ctx, const PackObject &obj) {}
virtual PackObject serialize(const Swan::Context &ctx, msgpack::zone &zone) { return {}; }
};

class PhysicsEntity: public Entity, public BodyTrait::HasBody {

+ 28
- 7
libswan/include/swan/Mod.h View File

@@ -27,26 +27,47 @@ public:

void init(const std::string &name);

void registerImage(ImageResource::Builder image);
void registerImage(const std::string &id);
void registerTile(Tile::Builder tile);
void registerItem(Item::Builder item);
void registerWorldGen(const std::string &name, std::unique_ptr<WorldGen::Factory> gen);
void registerEntity(const std::string &name, std::unique_ptr<Entity::Factory> ent);

template<typename WG>
void registerWorldGen(const std::string &name) {
worldgens_.push_back(WorldGen::Factory{
.name = name_ + "::" + name,
.create = [](World &world) {
return static_cast<std::unique_ptr<WorldGen>>(
std::make_unique<WG>(world));
}
});
}

template<typename Ent>
void registerEntity(const std::string &name) {
entities_.push_back(Entity::Factory{
.name = name_ + "::" + name,
.create = [](const Context &ctx, const Entity::PackObject &obj) {
return static_cast<std::unique_ptr<Entity>>(
std::make_unique<Ent>(ctx, obj));
}
});
}

Iter<std::unique_ptr<ImageResource>> buildImages(SDL_Renderer *renderer);
Iter<std::unique_ptr<Tile>> buildTiles(const ResourceManager &resources);
Iter<std::unique_ptr<Item>> buildItems(const ResourceManager &resources);
Iter<WorldGen::Factory *> getWorldGens();
Iter<Entity::Factory *> getEntities();
Iter<WorldGen::Factory> getWorldGens();
Iter<Entity::Factory> getEntities();

std::string name_ = "@uninitialized";

private:
std::vector<ImageResource::Builder> images_;
std::vector<std::string> images_;
std::vector<Tile::Builder> tiles_;
std::vector<Item::Builder> items_;
std::vector<std::unique_ptr<WorldGen::Factory>> worldgens_;
std::vector<std::unique_ptr<Entity::Factory>> entities_;
std::vector<WorldGen::Factory> worldgens_;
std::vector<Entity::Factory> entities_;

std::string path_;
OS::Dynlib dynlib_;

+ 2
- 8
libswan/include/swan/Resource.h View File

@@ -12,14 +12,8 @@ namespace Swan {

class ImageResource {
public:
struct Builder {
std::string name;
std::string path;
int frame_height = -1;
std::string modpath = "";
};

ImageResource(SDL_Renderer *renderer, const Builder &builder);
ImageResource(
SDL_Renderer *renderer, const std::string &modpath, const std::string &id);
ImageResource(
SDL_Renderer *renderer, const std::string &name,
int w, int h, uint8_t r, uint8_t g, uint8_t b);

+ 0
- 181
libswan/include/swan/SRF.h View File

@@ -1,181 +0,0 @@
#pragma once

#include <ostream>
#include <istream>
#include <vector>
#include <unordered_map>
#include <memory>
#include <string>
#include <initializer_list>
#include <utility>
#include <stdint.h>

namespace Swan {

struct SRF {
virtual ~SRF() = default;

virtual void serialize(std::ostream &os) const = 0;
virtual void parse(std::istream &is) = 0;
virtual std::ostream &pretty(std::ostream &os) const = 0;

static SRF *read(std::istream &is);

friend std::ostream &operator<<(std::ostream &os, const SRF &srf);
};

struct SRFObject: SRF {
SRFObject() {}
SRFObject(std::initializer_list<std::pair<std::string, SRF *>> lst);

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::unordered_map<std::string, std::unique_ptr<SRF>> val;
};

struct SRFArray: SRF {
SRFArray() {}
SRFArray(std::initializer_list<SRF *> lst);

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<std::unique_ptr<SRF>> val;
};

struct SRFString: SRF {
SRFString(): val("") {}
SRFString(const std::string &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::string val;
};

struct SRFByte: SRF {
SRFByte(): val(0) {}
SRFByte(uint8_t v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

uint8_t val;
};

struct SRFWord: SRF {
SRFWord(): val(0) {}
SRFWord(uint16_t v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

uint16_t val;
};

struct SRFInt: SRF {
SRFInt(): val(0) {}
SRFInt(int32_t v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

int32_t val;
};

struct SRFFloat: SRF {
SRFFloat(): val(0) {}
SRFFloat(float v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

float val;
};

struct SRFDouble: SRF {
SRFDouble(): val(0) {}
SRFDouble(double v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

double val;
};

struct SRFNone: SRF {
void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;
};

struct SRFByteArray: SRF {
SRFByteArray() = default;
SRFByteArray(std::initializer_list<uint8_t> lst): val(lst) {}
SRFByteArray(std::vector<uint8_t> &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<uint8_t> val;
};

struct SRFWordArray: SRF {
SRFWordArray() = default;
SRFWordArray(std::initializer_list<uint16_t> v): val(v) {}
SRFWordArray(std::vector<uint16_t> &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<uint16_t> val;
};

struct SRFIntArray: SRF {
SRFIntArray() = default;
SRFIntArray(std::initializer_list<int> v): val(v) {}
SRFIntArray(std::vector<int32_t> &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<int32_t> val;
};

struct SRFFloatArray: SRF {
SRFFloatArray() = default;
SRFFloatArray(std::initializer_list<float> v): val(v) {}
SRFFloatArray(std::vector<float> &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<float> val;
};

struct SRFDoubleArray: SRF {
SRFDoubleArray() = default;
SRFDoubleArray(std::initializer_list<double> v): val(v) {}
SRFDoubleArray(std::vector<double> &v): val(v) {}

void serialize(std::ostream &os) const override;
void parse(std::istream &os) override;
std::ostream &pretty(std::ostream &os) const override;

std::vector<double> val;
};

}

+ 3
- 0
libswan/include/swan/Vector2.h View File

@@ -3,6 +3,7 @@
#include <utility>
#include <ostream>
#include <cmath>
#include <msgpack.hpp>

namespace Swan {

@@ -11,6 +12,8 @@ struct Vector2 {
T x;
T y;

MSGPACK_DEFINE(x, y)

constexpr Vector2(T x = 0, T y = 0): x(x), y(y) {}

constexpr Vector2<T> &set(T x, T y) {

+ 2
- 2
libswan/include/swan/World.h View File

@@ -50,8 +50,8 @@ public:

// The mods themselves retain ownership of world gens and entities,
// the world just has non-owning pointers to them
std::unordered_map<std::string, WorldGen::Factory *> worldgens_;
std::unordered_map<std::string, Entity::Factory *> ents_;
std::unordered_map<std::string, WorldGen::Factory> worldgens_;
std::unordered_map<std::string, Entity::Factory> ents_;

BodyTrait::HasBody *player_;
Game *game_;

+ 4
- 13
libswan/include/swan/WorldGen.h View File

@@ -15,20 +15,11 @@ class World;
class WorldPlane;
class ImageResource;

class WorldGenStructure {
public:
virtual ~WorldGenStructure() = 0;

virtual bool isBase(TilePos pos);
};

class WorldGen {
public:
class Factory {
public:
virtual ~Factory() = default;
virtual WorldGen *create(World &world) = 0;
std::string name_;
struct Factory {
const std::string name;
std::unique_ptr<WorldGen> (*create)(World &world);
};

virtual ~WorldGen() = default;
@@ -37,7 +28,7 @@ public:
virtual SDL_Color backgroundColor(Vec2 pos) = 0;

virtual void genChunk(WorldPlane &plane, Chunk &chunk) = 0;
virtual BodyTrait::HasBody *spawnPlayer(WorldPlane &plane) = 0;
virtual BodyTrait::HasBody *spawnPlayer(const Context &ctx) = 0;
};

}

+ 4
- 3
libswan/include/swan/WorldPlane.h View File

@@ -24,10 +24,11 @@ class WorldPlane: NonCopyable {
public:
using ID = uint16_t;

WorldPlane(ID id, World *world, std::shared_ptr<WorldGen> gen):
WorldPlane(ID id, World *world, std::unique_ptr<WorldGen> gen):
id_(id), world_(world), gen_(std::move(gen)) {}

Entity *spawnEntity(const std::string &name, const SRF &params);
Entity *spawnEntity(const std::string &name, const Entity::PackObject &params);
Entity *spawnEntity(std::unique_ptr<Entity> ent);
void despawnEntity(Entity &ent);

Context getContext();
@@ -62,7 +63,7 @@ public:

ID id_;
World *world_;
std::shared_ptr<WorldGen> gen_;
std::unique_ptr<WorldGen> gen_;

private:
std::map<std::pair<int, int>, Chunk> chunks_;

+ 0
- 1
libswan/include/swan/swan.h View File

@@ -13,7 +13,6 @@
#include <swan/PerfCounter.h>
#include <swan/OS.h>
#include <swan/Resource.h>
#include <swan/SRF.h>
#include <swan/Tile.h>
#include <swan/Vector2.h>
#include <swan/Win.h>

+ 5
- 1
libswan/include/swan/util.h View File

@@ -68,7 +68,11 @@ public:
}

void operator++() {
next_ = std::move(func_());
auto val(func_());
if (val)
next_.emplace(std::move(*val));
else
next_.reset();
}

Ret operator*() {

+ 11
- 25
libswan/src/Mod.cc View File

@@ -23,11 +23,9 @@ void Mod::init(const std::string &name) {
info << "Mod initing: " << name_;
}

void Mod::registerImage(ImageResource::Builder image) {
image.name = name_ + "::" + image.name;
image.modpath = path_;
images_.push_back(image);
info << " Adding image: " << image.name << " (" << image.path << ')';
void Mod::registerImage(const std::string &id) {
images_.push_back(name_ + "/" + id);
info << " Adding image: " << images_.back();
}

void Mod::registerTile(Tile::Builder tile) {
@@ -42,21 +40,9 @@ void Mod::registerItem(Item::Builder item) {
info << " Adding item: " << item.name;
}

void Mod::registerWorldGen(const std::string &name, std::unique_ptr<WorldGen::Factory> gen) {
gen->name_ = name_ + "::" + name;
info << " Adding world gen: " << gen->name_;
worldgens_.push_back(std::move(gen));
}

void Mod::registerEntity(const std::string &name, std::unique_ptr<Entity::Factory> ent) {
ent->name_ = name_ + "::" + name;
info << " Adding entity: " << ent->name_;
entities_.push_back(std::move(ent));
}

Iter<std::unique_ptr<ImageResource>> Mod::buildImages(SDL_Renderer *renderer) {
return map(begin(images_), end(images_), [=](const ImageResource::Builder &builder) {
return std::make_unique<ImageResource>(renderer, builder);
return map(begin(images_), end(images_), [renderer, this](const std::string &id) {
return std::make_unique<ImageResource>(renderer, path_, id);
});
}

@@ -72,15 +58,15 @@ Iter<std::unique_ptr<Item>> Mod::buildItems(const ResourceManager &resources) {
});
}

Iter<WorldGen::Factory *> Mod::getWorldGens() {
return map(begin(worldgens_), end(worldgens_), [](const std::unique_ptr<WorldGen::Factory> &gen) {
return gen.get();
Iter<WorldGen::Factory> Mod::getWorldGens() {
return map(begin(worldgens_), end(worldgens_), [](WorldGen::Factory &fact) {
return fact;
});
}

Iter<Entity::Factory *> Mod::getEntities() {
return map(begin(entities_), end(entities_), [](const std::unique_ptr<Entity::Factory> &ent){
return ent.get();
Iter<Entity::Factory> Mod::getEntities() {
return map(begin(entities_), end(entities_), [](Entity::Factory &fact){
return fact;
});
}


+ 32
- 8
libswan/src/Resource.cc View File

@@ -2,6 +2,10 @@

#include <stdio.h>
#include <SDL2/SDL_image.h>
#include <regex>
#include <cpptoml.h>
#include <string.h>
#include <errno.h>

#include "log.h"
#include "common.h"
@@ -10,7 +14,10 @@

namespace Swan {

ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
ImageResource::ImageResource(
SDL_Renderer *renderer, const std::string &modpath, const std::string &id) {
static std::regex first_part_re("^.*?/");

SDL_RendererInfo rinfo;
if (SDL_GetRendererInfo(renderer, &rinfo) < 0) {
panic << "GetRendererInfo failed: " << SDL_GetError();
@@ -25,12 +32,15 @@ ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
abort();
}

surface_.reset(IMG_Load((builder.modpath + "/assets/" + builder.path).c_str()));
std::string assetpath = modpath + "/assets/" +
std::regex_replace(id, first_part_re, "");

surface_.reset(IMG_Load((assetpath + ".png").c_str()));

// If we have a surface, and it's the wrong pixel format, convert it
if (surface_ && surface_->format->format != format) {
info
<< " " << builder.name << ": Converting from "
<< " " << id << ": Converting from "
<< SDL_GetPixelFormatName(surface_->format->format) << " to "
<< SDL_GetPixelFormatName(format);
surface_.reset(SDL_ConvertSurfaceFormat(surface_.get(), format, 0));
@@ -39,7 +49,7 @@ ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
// If we don't have a surface yet (either loading or conversion failed),
// create a placeholder
if (!surface_) {
warn << "Loading image " << builder.name << " failed: " << SDL_GetError();
warn << "Loading image " << id << " failed: " << SDL_GetError();

surface_.reset(SDL_CreateRGBSurface(
0, TILE_SIZE, TILE_SIZE, bpp, rmask, gmask, bmask, amask));
@@ -47,9 +57,23 @@ ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
PLACEHOLDER_RED, PLACEHOLDER_GREEN, PLACEHOLDER_BLUE));
}

frame_height_ = builder.frame_height;
if (frame_height_ < 0)
frame_height_ = surface_->h;
frame_height_ = 32;

// Load TOML if it exists
errno = ENOENT; // I don't know if ifstream is guaranteed to set errno
std::ifstream tomlfile(assetpath + ".toml");
if (tomlfile) {
cpptoml::parser parser(tomlfile);
try {
auto toml = parser.parse();
frame_height_ = toml->get_as<int>("height").value_or(frame_height_);
} catch (cpptoml::parse_exception &exc) {
warn << "Failed to parse toml file " << assetpath << ".toml: "
<< exc.what();
}
} else if (errno != ENOENT) {
warn << "Couldn't open " << assetpath << ".toml: " << strerror(errno);
}

texture_.reset(SDL_CreateTextureFromSurface(renderer, surface_.get()));
if (!texture_) {
@@ -58,7 +82,7 @@ ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
}

num_frames_ = surface_->h / frame_height_;
name_ = builder.name;
name_ = id;
}

ImageResource::ImageResource(

+ 0
- 467
libswan/src/SRF.cc View File

@@ -1,467 +0,0 @@
#include "SRF.h"

namespace Swan {

enum class Type {
OBJECT = 0,
ARRAY = 1,
STRING = 2,
BYTE = 3,
WORD = 4,
INT = 5,
FLOAT = 6,
DOUBLE = 7,
NONE = 8,
BYTE_ARRAY = 9,
WORD_ARRAY = 10,
INT_ARRAY = 11,
FLOAT_ARRAY = 12,
DOUBLE_ARRAY = 13,
};

static void writeByte(std::ostream &os, uint8_t val) {
os.put(val);
}

static uint8_t readByte(std::istream &is) {
return is.get();
}

static void writeWord(std::ostream &os, uint16_t val) {
os.put((val & 0xff00u) >> 8);
os.put(val & 0x00ffu);
}

static uint16_t readWord(std::istream &is) {
return (uint16_t)(
((uint16_t)is.get()) << 8 |
((uint16_t)is.get()));
}

static void writeInt(std::ostream &os, int32_t val) {
uint32_t uval = val;
os.put((uval & 0xff000000u) << 24);
os.put((uval & 0x00ff0000u) << 16);
os.put((uval & 0x0000ff00u) << 8);
os.put((uval & 0x000000ffu));
}

int32_t readInt(std::istream &is) {
return (int32_t)(
((uint32_t)is.get() << 24) |
((uint32_t)is.get() << 16) |
((uint32_t)is.get() << 8) |
((uint32_t)is.get()));
}

static void writeFloat(std::ostream &os, float val) {
uint32_t uval = (uint32_t)val;
os.put((uval & 0xff000000u) << 24);
os.put((uval & 0x00ff0000u) << 16);
os.put((uval & 0x0000ff00u) << 8);
os.put((uval & 0x000000ffu));
}

static float readFloat(std::istream &is) {
return (float)(
((uint32_t)is.get() << 24) |
((uint32_t)is.get() << 16) |
((uint32_t)is.get() << 8) |
((uint32_t)is.get()));
}

static void writeDouble(std::ostream &os, double val) {
uint64_t uval = (uint64_t)val;
os.put((uval & 0xff00000000000000lu) << 56);
os.put((uval & 0x00ff000000000000lu) << 48);
os.put((uval & 0x0000ff0000000000lu) << 40);
os.put((uval & 0x000000ff00000000lu) << 32);
os.put((uval & 0x00000000ff000000lu) << 24);
os.put((uval & 0x0000000000ff0000lu) << 16);
os.put((uval & 0x000000000000ff00lu) << 8);
os.put((uval & 0x00000000000000fflu));
}

static double readDouble(std::istream &is) {
return (double)(
((uint64_t)is.get() << 56) |
((uint64_t)is.get() << 48) |
((uint64_t)is.get() << 40) |
((uint64_t)is.get() << 32) |
((uint64_t)is.get() << 24) |
((uint64_t)is.get() << 16) |
((uint64_t)is.get() << 8) |
((uint64_t)is.get()));
}

static void writeString(std::ostream &os, const std::string &str) {
writeInt(os, str.size());
os.write(str.c_str(), str.size());
}

static std::string readString(std::istream &is) {
std::string str;
int32_t len = readInt(is);
str.reserve(len);
is.read(str.data(), len);
return str;
}

static char hexchr(uint8_t nibble) {
if (nibble < 10)
return (char)('0' + nibble);
else
return (char)('a' + (nibble - 10));
}

SRF *SRF::read(std::istream &is) {
Type type = (Type)readByte(is);
SRF *srf = nullptr;

switch (type) {
case Type::OBJECT:
srf = new SRFObject(); break;
case Type::ARRAY:
srf = new SRFArray(); break;
case Type::STRING:
srf = new SRFString(); break;
case Type::BYTE:
srf = new SRFByte(); break;
case Type::WORD:
srf = new SRFWord(); break;
case Type::INT:
srf = new SRFInt(); break;
case Type::FLOAT:
srf = new SRFFloat(); break;
case Type::DOUBLE:
srf = new SRFDouble(); break;
case Type::NONE:
srf = new SRFNone(); break;
case Type::BYTE_ARRAY:
srf = new SRFByteArray(); break;
case Type::WORD_ARRAY:
srf = new SRFWordArray(); break;
case Type::INT_ARRAY:
srf = new SRFIntArray(); break;
case Type::FLOAT_ARRAY:
srf = new SRFFloatArray(); break;
case Type::DOUBLE_ARRAY:
srf = new SRFDoubleArray(); break;
}

srf->parse(is);
return srf;
}

std::ostream &operator<<(std::ostream &os, const SRF &srf) {
srf.pretty(os);
return os;
}

SRFObject::SRFObject(std::initializer_list<std::pair<std::string, SRF *>> lst) {
for (auto &[k, v]: lst)
val[k] = std::unique_ptr<SRF>(v);
}

void SRFObject::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::OBJECT);
writeInt(os, val.size());

for (auto &[k, v]: val) {
writeString(os, k);
v->serialize(os);
}
}

void SRFObject::parse(std::istream &is) {
int32_t count = readInt(is);

for (int32_t i = 0; i < count; ++i) {
std::string key = readString(is);
val[key] = std::unique_ptr<SRF>(SRF::read(is));
}
}

std::ostream &SRFObject::pretty(std::ostream &os) const {
os << "{ ";
bool first = true;
for (auto &[k, v]: val) {
if (!first)
os << ", ";

os << '\'' << k << "': ";
v->pretty(os);
first = false;
}

return os << " }";
}

SRFArray::SRFArray(std::initializer_list<SRF *> lst) {
for (auto &v: lst)
val.push_back(std::unique_ptr<SRF>(v));
}

void SRFArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::ARRAY);
writeInt(os, val.size());

for (auto &v: val) {
v->serialize(os);
}
}

void SRFArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);

for (int32_t i = 0; i < count; ++i) {
val[i] = std::unique_ptr<SRF>(SRF::read(is));
}
}

std::ostream &SRFArray::pretty(std::ostream &os) const {
os << "[ ";
bool first = true;
for (auto &v: val) {
if (!first)
os << ", ";

v->pretty(os);
first = false;
}

return os << " ]";
}

void SRFString::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::STRING);
writeString(os, val);
}

void SRFString::parse(std::istream &is) {
val = readString(is);
}

std::ostream &SRFString::pretty(std::ostream &os) const {
return os << '"' << val << '"';
}

void SRFByte::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::BYTE);
writeByte(os, val);
}

void SRFByte::parse(std::istream &is) {
val = readByte(is);
}

std::ostream &SRFByte::pretty(std::ostream &os) const {
return os << "0x"
<< hexchr((val & 0xf0) >> 4)
<< hexchr((val & 0x0f) >> 0);
}

void SRFWord::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::WORD);
writeWord(os, val);
}

void SRFWord::parse(std::istream &is) {
val = readWord(is);
}

std::ostream &SRFWord::pretty(std::ostream &os) const {
return os << "0x"
<< hexchr((val & 0xf000) >> 12)
<< hexchr((val & 0x0f00) >> 8)
<< hexchr((val & 0x00f0) >> 4)
<< hexchr((val & 0x000f) >> 0);
}

void SRFInt::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::INT);
writeInt(os, val);
}

void SRFInt::parse(std::istream &is) {
val = readInt(is);
}

std::ostream &SRFInt::pretty(std::ostream &os) const {
return os << val;
}

void SRFFloat::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::FLOAT);
writeFloat(os, val);
}

void SRFFloat::parse(std::istream &is) {
val = readFloat(is);
}

std::ostream &SRFFloat::pretty(std::ostream &os) const {
return os << val;
}

void SRFDouble::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::DOUBLE);
writeDouble(os, val);
}

void SRFDouble::parse(std::istream &is) {
val = readDouble(is);
}

std::ostream &SRFDouble::pretty(std::ostream &os) const {
return os << val;
}

void SRFNone::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::NONE);
}

void SRFNone::parse(std::istream &is) {}

std::ostream &SRFNone::pretty(std::ostream &os) const {
return os << "(null)";
}

void SRFByteArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::BYTE_ARRAY);
writeInt(os, val.size());
os.write((const char *)val.data(), val.size());
}

void SRFByteArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);
is.read((char *)val.data(), count);
}

std::ostream &SRFByteArray::pretty(std::ostream &os) const {
os << "byte[ " << std::hex;
for (auto v: val) {
os
<< hexchr((v & 0xf0) >> 4)
<< hexchr((v & 0x0f) >> 0) << ' ';
}

return os << ']';
}

void SRFWordArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::WORD_ARRAY);
writeInt(os, val.size());

for (auto &v: val) {
writeWord(os, v);
}
}

void SRFWordArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);

for (int32_t i = 0; i < count; ++i) {
val[i] = readWord(is);
}
}

std::ostream &SRFWordArray::pretty(std::ostream &os) const {
os << "word[ ";
for (auto v: val) {
os
<< hexchr((v & 0xf000) >> 12)
<< hexchr((v & 0x0f00) >> 8)
<< hexchr((v & 0x00f0) >> 4)
<< hexchr((v & 0x000f) >> 0)
<< ' ';
}

return os << ']';
}

void SRFIntArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::INT_ARRAY);
writeInt(os, val.size());

for (auto &v: val) {
writeInt(os, v);
}
}

void SRFIntArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);

for (int32_t i = 0; i < count; ++i) {
val[i] = readInt(is);
}
}

std::ostream &SRFIntArray::pretty(std::ostream &os) const {
os << "int[ ";
for (auto v: val) {
os << v << ' ';
}

return os << ']';
}

void SRFFloatArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::FLOAT_ARRAY);
writeInt(os, val.size());

for (auto &v: val) {
writeFloat(os, v);
}
}

void SRFFloatArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);

for (int32_t i = 0; i < count; ++i) {
val[i] = readFloat(is);
}
}

std::ostream &SRFFloatArray::pretty(std::ostream &os) const {
os << "float[ ";
for (auto v: val) {
os << v << ' ';
}

return os << ']';
}

void SRFDoubleArray::serialize(std::ostream &os) const {
writeByte(os, (uint8_t)Type::DOUBLE_ARRAY);
writeInt(os, val.size());

for (auto &v: val) {
writeDouble(os, v);
}
}

void SRFDoubleArray::parse(std::istream &is) {
int32_t count = readInt(is);
val.resize(count);

for (int32_t i = 0; i < count; ++i) {
val[i] = readDouble(is);
}
}

std::ostream &SRFDoubleArray::pretty(std::ostream &os) const {
os << "double[ ";
for (auto v: val) {
os << v << ' ';
}

return os << ']';
}

}

+ 13
- 7
libswan/src/World.cc View File

@@ -59,12 +59,18 @@ void World::addMod(std::unique_ptr<Mod> mod) {
items_[i->name_] = std::move(i);
}

for (auto *gen: mod->getWorldGens()) {
worldgens_[gen->name_] = gen;
for (auto gen: mod->getWorldGens()) {
worldgens_.emplace(
std::piecewise_construct,
std::forward_as_tuple(gen.name),
std::forward_as_tuple(gen));
}

for (auto *ent: mod->getEntities()) {
ents_[ent->name_] = ent;
for (auto ent: mod->getEntities()) {
ents_.emplace(
std::piecewise_construct,
std::forward_as_tuple(ent.name),
std::forward_as_tuple(ent));
}

mods_.push_back(std::move(mod));
@@ -90,9 +96,9 @@ WorldPlane &World::addPlane(const std::string &gen) {
abort();
}

WorldGen::Factory *factory = it->second;
WorldGen *g = factory->create(*this);
planes_.emplace_back(id, this, std::shared_ptr<WorldGen>(g));
WorldGen::Factory &factory = it->second;
std::unique_ptr<WorldGen> g = factory.create(*this);
planes_.emplace_back(id, this, std::move(g));
return planes_[id];
}


+ 16
- 11
libswan/src/WorldPlane.cc View File

@@ -36,23 +36,27 @@ Context WorldPlane::getContext() {
};
}

Entity *WorldPlane::spawnEntity(const std::string &name, const SRF &params) {
Entity *WorldPlane::spawnEntity(const std::string &name, const Entity::PackObject &obj) {
if (world_->ents_.find(name) == world_->ents_.end()) {
panic << "Tried to spawn a non-existant entity " << name << "!";
abort();
}

Entity *ent = world_->ents_[name]->create(getContext(), params);
if (auto has_body = dynamic_cast<BodyTrait::HasBody *>(ent); has_body) {
return spawnEntity(world_->ents_[name].create(getContext(), obj));
}

Entity *WorldPlane::spawnEntity(std::unique_ptr<Entity> ent) {
Entity *ptr = ent.get();
if (auto has_body = dynamic_cast<BodyTrait::HasBody *>(ent.get()); has_body) {
BodyTrait::Body &body = has_body->getBody();
BodyTrait::Bounds bounds = body.getBounds();

body.move({ 0.5f - bounds.size.x / 2, 0 });
}

spawn_list_.push_back(std::unique_ptr<Entity>(ent));
info << "Spawned " << name << ". SRF: " << params;
return ent;
spawn_list_.push_back(std::move(ent));
info << "Spawned entity.";
return ptr;
}

void WorldPlane::despawnEntity(Entity &ent) {
@@ -138,7 +142,7 @@ Iter<Entity *> WorldPlane::getEntsInArea(Vec2 center, float radius) {
}

BodyTrait::HasBody *WorldPlane::spawnPlayer() {
return gen_->spawnPlayer(*this);
return gen_->spawnPlayer(getContext());
}

void WorldPlane::breakBlock(TilePos pos) {
@@ -154,10 +158,11 @@ void WorldPlane::breakBlock(TilePos pos) {

// Then spawn an item stack entity.
Tile &t = world_->getTileByID(id);
if (t.dropped_item_ != std::nullopt) {
spawnEntity("core::item-stack", SRFArray{
new SRFFloatArray{ (float)pos.x, (float)pos.y },
new SRFString{ *t.dropped_item_ },
if (t.dropped_item_) {
msgpack::zone zone;
spawnEntity("core::item-stack", Entity::PackObject{
{ "pos", msgpack::object(pos, zone) },
{ "item", msgpack::object(*t.dropped_item_, zone) },
});
}
}

+ 12
- 5
third_party/CMakeLists.txt View File

@@ -5,18 +5,25 @@ add_library(imgui SHARED
${PROJECT_SOURCE_DIR}/third_party/imgui/imgui.cpp
${PROJECT_SOURCE_DIR}/third_party/imgui_sdl/imgui_sdl.cpp
${PROJECT_SOURCE_DIR}/third_party/imgui-plot/src/imgui_plot.cpp)
set_target_properties(imgui PROPERTIES CXX_CLANG_TIDY "")
target_include_directories(imgui PUBLIC
${PROJECT_SOURCE_DIR}/third_party/imgui
${PROJECT_SOURCE_DIR}/third_party/imgui-plot/include
${SDL2_INCLUDE_DIRS})
set_target_properties(imgui PROPERTIES CXX_CLANG_TIDY "")
install(TARGETS imgui DESTINATION swan/third_party)

add_library(fmt SHARED
${PROJECT_SOURCE_DIR}/third_party/fmt/src/format.cc
${PROJECT_SOURCE_DIR}/third_party/fmt/src/os.cc)
target_include_directories(fmt PUBLIC
${PROJECT_SOURCE_DIR}/third_party/fmt/include)
install(TARGETS fmt DESTINATION swan/third_party)

add_library(cpptoml INTERFACE)
target_include_directories(cpptoml PUBLIC
target_include_directories(cpptoml INTERFACE
${PROJECT_SOURCE_DIR}/third_party/cpptoml/include)

add_library(msgpack INTERFACE)
target_include_directories(msgpack PUBLIC
${PROJECT_SOURCE_DIR}/third_party/msgpack/include)
target_include_directories(msgpack INTERFACE
${PROJECT_SOURCE_DIR}/third_party/msgpack-c/include)

install(TARGETS imgui DESTINATION swan/third_party)

+ 1
- 0
third_party/fmt

@@ -0,0 +1 @@
Subproject commit 9bdd1596cef1b57b9556f8bef32dc4a32322ef3e

Loading…
Cancel
Save