Skip to content

Instantly share code, notes, and snippets.

@Reputeless
Created December 21, 2024 00:15
Show Gist options
  • Select an option

  • Save Reputeless/0168858830805b8c2f90085869ad45b4 to your computer and use it in GitHub Desktop.

Select an option

Save Reputeless/0168858830805b8c2f90085869ad45b4 to your computer and use it in GitHub Desktop.
# include <Siv3D.hpp> // OpenSiv3D v0.6.15
struct MyClass
{
String name;
int32 id = 0;
};
template <>
MyClass s3d::Parse<MyClass>(StringView s)
{
if (s.isEmpty())
{
return{ U"ERROR", -1 };
}
//
// ここでは、文字列を「(name id)」という形式でパースする。
//
// 先頭の ( を削除する
s.remove_prefix(1);
// 末尾の ) を削除する
s.remove_suffix(1);
// 空白で 2 つに分割する
const Array<String> items = String{ s }.split(U' ');
if (items.size() != 2)
{
return{ U"ERROR", -1 };
}
return{ items[0], ParseOr<int32>(items[1], -1) };
}
template <>
struct SIV3D_HIDDEN fmt::formatter<MyClass, s3d::char32>
{
std::u32string tag;
auto parse(basic_format_parse_context<s3d::char32>& ctx)
{
return s3d::detail::GetFormatTag(tag, ctx);
}
template <class FormatContext>
auto format(const MyClass& value, FormatContext& ctx)
{
// 出力形式を指定する。ここでは「(name id)」という形式で出力。
// これに対応した Parse 関数を定義しておく必要がある。
return format_to(ctx.out(), U"({} {})", value.name, value.id);
}
};
namespace s3d::Productivity
{
class QuickConfig
{
private:
using Variant = std::variant<int8*, int16*, int32*, int64*, uint8*, uint16*, uint32*, uint64*,
float*, double*, bool*, String*, Point*, Float2*, Vec2*, Float3*, Float4*, Vec4*,
Color*, ColorF*, HSV*, Circular*, Rect*, Circle*, Line*, Triangle*, Quad*, Ellipse*, RoundRect*,
MyClass*>;
HashTable<std::string, std::pair<Variant, size_t>> m_data;
FilePath m_iniPath = FileSystem::FullPath(U"QUICK_CONFIG.ini");
DirectoryWatcher m_watcher;
public:
template <class Type>
void capture(Type& value, const std::string& name)
{
m_data.emplace(name, std::pair<Variant, size_t>{ std::addressof(value), m_data.size() });
}
void generateINI()
{
Array<std::pair<std::string, Variant>> values(m_data.size());
for (const auto& data : m_data)
{
values[data.second.second] = { data.first, data.second.first };
}
{
TextWriter writer(m_iniPath);
for (const auto& value : values)
{
std::visit([&](const auto p)
{
writer.writeln(U"{} = {}"_fmt(Unicode::Widen(value.first), *p));
}, value.second);
}
}
m_watcher = DirectoryWatcher{ FileSystem::ParentPath(m_iniPath) };
}
void update()
{
for (auto&& [path, action] : m_watcher.retrieveChanges())
{
if ((path == m_iniPath)
&& ((action == FileAction::Modified) || (action == FileAction::Added)))
{
return read();
}
}
}
void read()
{
const INI ini{ m_iniPath };
for (auto& data : m_data)
{
const String s = ini[Unicode::Widen(data.first)];
std::visit([&](auto p)
{
*p = Parse<std::remove_pointer_t<decltype(p)>>(s);
}, data.second.first);
}
}
};
# define QC_BEGIN() Productivity::QuickConfig _quickConfig;
# define QC(value) _quickConfig.capture(value, #value);
# define QC_END() _quickConfig.generateINI();
# define QC_UPDATE() _quickConfig.update();
}
void Main()
{
const Font font{ FontMethod::MSDF, 48 };
QC_BEGIN();
int32 a = 100; QC(a);
double b = 3.1415; QC(b);
ColorF bg{ 0.1, 0.5, 0.3 }; QC(bg);
String text = U"Siv3D"; QC(text);
Point pos{ 20, 30 }; QC(pos);
ColorF col{ 0.7 }; QC(col);
Rect rect{ 20, 90, 80, 20 }; QC(rect);
RoundRect rrect{ 200, 100, 100, 40, 8 }; QC(rrect);
MyClass myClass{ U"Test", 123 }; QC(myClass);
QC_END();
while (System::Update())
{
QC_UPDATE();
Scene::SetBackground(bg);
font(U"{}, {}, {}"_fmt(a, b, text)).draw(30, pos, col);
rect.draw();
rrect.draw();
font(U"{}"_fmt(myClass)).draw(30, 200);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment