概要
この記事では、OpenSiv3DとC++を使って、リドゥ・アンドゥ(やり直し・元に戻す)機能を簡単に実装する方法を紹介します。具体的には、以下のソースコードを使って、シリアライズに対応した任意のクラスの履歴を保存し、リドゥ・アンドゥ機能を実現できます。
template<class Type>
Blob GenerateHistory(const Type& data)
{
return Zlib::Compress(Serializer<MemoryWriter>{}(data)->getBlob());
}
template<class Type>
void RecoverHistory(Type& data, const Blob& blob)
{
Deserializer<MemoryReader>{Zlib::Decompress(blob)}(data);
}
はじめに
この記事では、OpenSiv3DとC++を使用して、簡単にリドゥ・アンドゥ機能を実装する方法を紹介します。リドゥ・アンドゥ機能は、エディターやグラフィックデザインツールなど、ユーザーが操作をやり直したり元に戻したりできる機能が求められるアプリケーションで非常に重要です。OpenSiv3Dは、C++のパワフルさと簡単な使いやすさを兼ね備えたマルチプラットフォーム用のライブラリです。
シリアライズを使って自作アプリにUndo/Redoを実装する方法が既に紹介されていますが、この記事では関数を使ってシリアライズ・デシリアライズを行うことで、より短いコードで他のプロジェクトに適用しやすい方法を提案します。この方法は、特に小規模なプロジェクトやプロトタイピングでの利用に適しています。
実装方法
まず、クラスにシリアライズ機能を追加します。以下のようにSIV3D_SERIALIZE関数を定義し、メンバ変数をシリアライズするように指定してください。
template <class Archive>
void SIV3D_SERIALIZE(Archive& archive)
{
archive(/* メンバ変数 */);
}
次に、履歴を保存するためのGenerateHistory関数を実装します。この関数は、シリアライズされたデータを圧縮し、Blobオブジェクトとして返します。
template<class Type>
Blob GenerateHistory(const Type& data)
{
return Zlib::Compress(Serializer<MemoryWriter>{}(data)->getBlob());
}
そして、履歴を復元するためのRecoverHistory関数を実装します。この関数は、圧縮された履歴データ(Blobオブジェクト)を引数にとり、デシリアライズして元のデータに戻します。
template<class Type>
void RecoverHistory(Type& data, const Blob& blob)
{
Deserializer<MemoryReader>{Zlib::Decompress(blob)}(data);
}
これで、GenerateHistory関数を使ってデータの履歴を保存し、RecoverHistory関数を使って履歴からデータを復元できるようになります。リドゥ・アンドゥ機能を実現するためには、適切なタイミングでこれらの関数を呼び出し、データの履歴を管理する必要があります。例えば、Arrayを使って履歴のスタックを管理することができます。
注意点
この手法のメリットは、シリアライズに対応した任意のクラスで簡単にリドゥ・アンドゥ機能を実装できることです。また、履歴データが圧縮されるため、メモリ消費を抑えることができます。
デメリットとしては、シリアライズやデシリアライズに時間がかかることがあり、パフォーマンスに影響を与える場合があることです。また、シリアライズに対応していないクラスではこの手法を適用できません。
注意点としては、シリアライズやデシリアライズの際にデータ構造が正しく変換されるように注意が必要です。また、履歴データの管理に関しても適切に行うことが重要です。
まとめ
この記事では、OpenSiv3DとC++を使って簡単にリドゥ・アンドゥ機能を実装する方法を紹介しました。シリアライズに対応した任意のクラスで、履歴を保存してリドゥ・アンドゥ機能を実現することができます。ただし、シリアライズやデシリアライズのパフォーマンスやデータ構造の正確性に注意が必要です。この手法を活用して、リドゥ・アンドゥ機能が求められるアプリケーションを開発してみてください。