TexturePackerをOpenSiv3Dで使ってみた

# TexturePackerとは

テクスチャのアトラス化等ができるソフトで、
有料ソフトですが、機能制限ありで無料で利用も可能です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/0940f81e-04f7-8164-0f28-2075f65bd685.png" width="400">

[ココ](https://www.codeandweb.com/texturepacker) でDLできる

減色とか暗号化もできるようです。

# 使ってみる

1. ドラッグドロップで画像ファイルを登録(フォルダごともできる)
2. 今回はFrameworkは**JSON(Array)**にします
3. Publish sprite sheet をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/10e55045-9243-878f-d9cc-1b06efe839c5.png" width="600">

(無料版だとBasicアルゴリズムしか使用できないのでその辺りは触っていない)

# 書き出されたファイル確認

Publishに成功したら画像ファイルとjsonファイルが吐き出されるはずです

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/f703b3a3-a4a4-1748-e45f-55e4ca8f3d48.png" width="150">

```json:test.json
{"frames": [

{
	"filename": "siv3d-kun.png",
	"frame": {"x":0,"y":0,"w":360,"h":480},
	"rotated": false,
	"trimmed": false,
	"spriteSourceSize": {"x":0,"y":0,"w":360,"h":480},
	"sourceSize": {"w":360,"h":480}
},
{
	"filename": "windmill.png",
	"frame": {"x":0,"y":480,"w":480,"h":320},
	"rotated": false,
	"trimmed": false,
	"spriteSourceSize": {"x":0,"y":0,"w":480,"h":320},
	"sourceSize": {"w":480,"h":320}
}],
"meta": {
	"app": "https://www.codeandweb.com/texturepacker",
	"version": "1.0",
	"image": "test.png",
	"format": "RGBA8888",
	"size": {"w":480,"h":800},
	"scale": "1",
	"smartupdate": "$TexturePacker:SmartUpdate:20e31cb64861b1a78f287ed2a8355f62:96d140971d9d4efa50ede3965739f53c:02ab132358d6d8b512e80119463a8329$"
}
}
```

今回はシンプルな書き出しだったので簡潔な情報のみが含まれたjsonになりました。
これをOpenSiv3Dで読み込んでみます。

# OpenSiv3Dで読み込む


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/8e2093bf-dba8-52d4-919d-470fc3590f92.png" width="400">

先ほどのJSONのファイルとテクスチャを読み込んで表示できるようにします。

```cpp:TexturePacker.hpp
#pragma once
#include <Siv3D/Fwd.hpp>
#include <memory>

class TexturePacker
{
	class Impl;
	std::shared_ptr<Impl> pImpl;
public:
	TexturePacker() = default;
	TexturePacker(const s3d::FilePath& json);
	TexturePacker(const s3d::Texture& texture, const s3d::FilePath& json);

	s3d::TextureRegion operator()(const s3d::String& fileName)const;
	s3d::TextureRegion operator()(const s3d::String& fileName, const s3d::Vec2& pos, const s3d::Vec2& size)const;
};
```

```cpp:TexturePacker.cpp
#include "TexturePacker.hpp"
#include <Siv3D.hpp>

class TexturePacker::Impl
{
	struct Info
	{
		Vec2 pos;
		Vec2 size;
	};
	Texture m_texture;
	std::unordered_map<String, Info> m_infos;

	void load(const FilePath& json)
	{
		JSONReader reader(json);
		if (!reader) {
			return;
		}
		for (const auto& elm : reader[U"frames"].arrayView()) {
			const auto& frame = elm[U"frame"];
			Info info;
			info.pos = {
				frame[U"x"].get<double>(),
				frame[U"y"].get<double>(),
			};
			info.size = {
				frame[U"w"].get<double>(),
				frame[U"h"].get<double>(),
			};
			m_infos[elm[U"filename"].getString()] = info;
		}
		if (!m_texture) {
			const FilePath& parent = FileSystem::ParentPath(json);
			m_texture = Texture(parent + reader[U"meta.image"].getString());
		}
	}
public:
	Impl(const FilePath& json)
	{
		this->load(json);
	}

	Impl(const Texture& texture, const FilePath& json) :
		m_texture(texture)
	{
		this->load(json);
	}

	TextureRegion operator()(const String& fileName) const
	{
		const Info& info = m_infos.at(fileName);
		return m_texture(info.pos, info.size);
	}

	TextureRegion operator()(const String& fileName, const Vec2& pos, const Vec2& size) const
	{
		const Info& info = m_infos.at(fileName);
		return m_texture(Math::Ceil(info.pos + pos), Math::Ceil(size));
	}
};
TexturePacker::TexturePacker(const FilePath& json) :
	pImpl(std::make_shared<Impl>(json))
{}
TexturePacker::TexturePacker(const Texture& texture, const FilePath& json) :
	pImpl(std::make_shared<Impl>(texture, json))
{}
TextureRegion TexturePacker::operator()(const String& fileName) const
{
	return (*pImpl)(fileName);
}
TextureRegion TexturePacker::operator()(const String& fileName, const Vec2& pos, const Vec2& size) const
{
	return (*pImpl)(fileName, pos, size);
}
```

```cpp:Main.cpp
# include <Siv3D.hpp> // OpenSiv3D v0.4.1
# include "TexturePacker.hpp"

void Main()
{
	TexturePacker tex(U"test.json");

	while (System::Update())
	{
		tex(U"siv3d-kun.png").draw();
	}
}
```

# まとめ

- TexturePackerでアトラス化したテクスチャをOpenSiv3Dで読み込めた。
- 今回は最小情報のみ読み込んだので別途対応する箇所はまだたくさんあると思います。