Open7

Siv3D v0.6.8 新規追加・更新サンプル

Ryo SuzukiRyo Suzuki

指定したファイルをデフォルトのアプリケーションで開く

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	while (System::Update())
	{
		if (SimpleGUI::Button(U"windmill.png", Vec2{ 80, 40 }, 200))
		{
			Print << System::LaunchFile(U"example/windmill.png");
		}

		if (SimpleGUI::Button(U"LICENSE.txt", Vec2{ 80, 80 }, 200))
		{
			Print << System::LaunchFile(U"example/LICENSE.txt");
		}

		if (SimpleGUI::Button(U"test.mp3", Vec2{ 80, 120 }, 200))
		{
			Print << System::LaunchFile(U"example/test.mp3");
		}

		if (SimpleGUI::Button(U"river.mp4", Vec2{ 80, 160 }, 200))
		{
			Print << System::LaunchFile(U"example/video/river.mp4");
		}
	}
}
Ryo SuzukiRyo Suzuki

指定したファイルをテキストエディタで開く

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	while (System::Update())
	{
		if (SimpleGUI::Button(U"LICENSE.txt", Vec2{ 80, 40 }, 200))
		{
			Print << System::LaunchFileWithTextEditor(U"example/LICENSE.txt");
		}

		if (SimpleGUI::Button(U"config.ini", Vec2{ 80, 80 }, 200))
		{
			Print << System::LaunchFileWithTextEditor(U"example/ini/config.ini");
		}

		if (SimpleGUI::Button(U"cat.svg", Vec2{ 80, 120 }, 200))
		{
			Print << System::LaunchFileWithTextEditor(U"example/svg/cat.svg");
		}

		if (SimpleGUI::Button(U"config.xml", Vec2{ 80, 160 }, 200))
		{
			Print << System::LaunchFileWithTextEditor(U"example/xml/config.xml");
		}
	}
}
Ryo SuzukiRyo Suzuki

カラー絵文字の更新

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	const Font font{ FontMethod::MSDF, 48, Typeface::Bold };
	const Font emojiFont{ 48, Typeface::ColorEmoji };
	font.addFallback(emojiFont);

	while (System::Update())
	{
		font(U"🫨🩷🩵🩶🫏🫎🪿\n🪽🪼🪻🫛🫚🪭🪮\n🪈🪇🪯🛜🫸🫷").draw(100, Vec2{ 40, 20 }, ColorF{ 0.2, 0.4, 0.8 });
	}
}
Ryo SuzukiRyo Suzuki

アイコンの更新

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	Scene::SetBackground(ColorF{ 0.8, 0.9, 1.0 });

	while (System::Update())
	{
		SimpleGUI::Button(U"\U000F1C18 Rename", Vec2{ 20, 20 }, 220);
		SimpleGUI::Button(U"\U000F1B96 Knob", Vec2{ 20, 60 }, 220);
		SimpleGUI::Button(U"\U000F1B4F Button-cursor", Vec2{ 20, 100 }, 220);

		SimpleGUI::Button(U"\U000F1BBB Tooltip-question", Vec2{ 260, 20 }, 220);
		SimpleGUI::Button(U"\U000F1B7C List-box", Vec2{ 260, 60 }, 220);
		SimpleGUI::Button(U"\U000F1B3E Train-car-tank", Vec2{ 260, 100 }, 220);

		SimpleGUI::Button(U"\U000F1A48 Landslide", Vec2{ 500, 20 }, 220);
		SimpleGUI::Button(U"\U000F1A88 Wind-power", Vec2{ 500, 60 }, 220);
		SimpleGUI::Button(U"\U000F1A1B Gas-burner", Vec2{ 500, 100 }, 220);
	}
}
Ryo SuzukiRyo Suzuki

OpenAI の Embeddings API

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

struct Text
{
	String text;

	Array<float> embedding;

	float cosineSimilarity = 0.0f;
};

bool Init(const String API_KEY, Array<Text>& texts)
{
	for (auto& text : texts)
	{
		String error;

		// OpenAI Embeddings API で文章の埋め込みベクトルを取得
		text.embedding = OpenAI::Embedding::Create(API_KEY, text.text, error);

		if (not text.embedding)
		{
			Print << error;

			return false;
		}
	}

	return true;
}

void Main()
{
	Window::Resize(1280, 720);

	Scene::SetBackground(ColorF{ 0.92 });

	const String API_KEY = EnvironmentVariable::Get(U"MY_OPENAI_API_KEY");

	const Font font{ FontMethod::MSDF, 48, Typeface::Medium };

	Array<Text> texts =
	{
		{ U"公園。市街地などに設けられた公共施設としての庭園や遊園地。" },
		{ U"天気。ある場所の、ある時刻の気象状態。気温・湿度・風・雲量などを総合した状態。" },
		{ U"会議。関係者が集まって相談をし、物事を決定すること。" },
		{ U"水泳。スポーツや娯楽として水中を泳ぐこと。" },
		{ U"寿司。酢飯に生鮮魚介の切り身を乗せた料理。" },
		{ U"携帯電話。無線を用いて長距離通信のできる小型の移動電話。" },
		{ U"医者。病人の診察・治療を職業とする人。" },
		{ U"電車。駆動用電動機を装置し、架線あるいは軌道から得る電気を動力源として走行する鉄道車両。" },
		{ U"森林。樹木、特に高木が群生して大きな面積を占めている所。" },
		{ U"火曜日。月曜日と水曜日の間にある週の1日。" },
		{ U"大使館。特命全権大使が駐在国において公務を執行する公館。" },
		{ U"窃盗。人の物をぬすむこと。また、その人。" },
		{ U"地震。地球内部の急激な変動による振動が四方に伝わり大地が揺れる現象。" },
		{ U"手紙。用事などを記して、人に送る文書。" },
		{ U"睡眠。ねむること。ねむり。" },
	};

	AsyncTask initTask = Async(Init, String{ API_KEY }, std::ref(texts));

	TextEditState textEditState;

	float maxCosineSimilarity = 0.0f, minCosineSimilarity = 1.0f;

	AsyncHTTPTask task;

	while (System::Update())
	{
		if (initTask.isValid())
		{
			Circle{ Scene::Center(), 40 }.drawArc(Scene::Time() * 90_deg, 270_deg, 5);

			font(U"テキストの埋め込みベクトルを計算しています。事前に計算しておくことで実行時の処理を省略できます。").drawAt(22, Scene::Center().movedBy(0, 100), ColorF{ 0.11 });

			if (initTask.isReady())
			{
				if (not initTask.get())
				{
					Print << U"埋め込みベクトルの計算に失敗。";
				}
			}

			continue;
		}

		SimpleGUI::TextBox(textEditState, Vec2{ 40, 40 }, 1000);

		if (SimpleGUI::Button(U"検索", Vec2{ 1060, 40 }, 80, (not textEditState.text.isEmpty()) && (not task.isDownloading())))
		{
			task = OpenAI::Embedding::CreateAsync(API_KEY, textEditState.text);
		}

		if (task.isReady() && task.getResponse().isOK())
		{
			const Array<float> inputEmbedding = OpenAI::Embedding::GetVector(task.getAsJSON());

			maxCosineSimilarity = 0.0f; minCosineSimilarity = 1.0f;

			for (auto& text : texts)
			{
				text.cosineSimilarity = OpenAI::Embedding::CosineSimilarity(inputEmbedding, text.embedding);
				maxCosineSimilarity = Max(maxCosineSimilarity, text.cosineSimilarity);
				minCosineSimilarity = Min(minCosineSimilarity, text.cosineSimilarity);
			}
		}

		if (not task.isDownloading())
		{
			for (int32 i = 0; i < texts.size(); ++i)
			{
				const float cosineSimilarity = texts[i].cosineSimilarity;

				const Rect rect{ 40, (100 + i * 38), 1180, 36 };

				// 最も類似度が高いものを強調表示
				rect.draw((cosineSimilarity == maxCosineSimilarity) ? ColorF{ 1.0, 1.0, 0.75 } : ColorF{ 1.0 });

				// コサイン類似度を 0.0 ~ 1.0 に変換
				const double t = Math::Map(cosineSimilarity, minCosineSimilarity, maxCosineSimilarity, 0.0, 1.0);

				RectF{ rect.pos, (50 * t), rect.h }.stretched(0, -2).draw(Colormap01F(t, ColormapType::Turbo));

				// 文章とコサイン類似度を表示
				font(texts[i].text).draw(22, Arg::leftCenter = rect.leftCenter().movedBy(80, 0), ColorF{ 0.11 });
				font(cosineSimilarity).draw(18, Arg::leftCenter = rect.leftCenter().movedBy(1080, 0), ColorF{ 0.11 });
			}
		}
	}

	if (initTask.isValid())
	{
		initTask.wait();
	}
}
Ryo SuzukiRyo Suzuki

ユーザのコンピュータ名や名前、言語を取得する関数

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	Print << U"ComputerName: " << System::ComputerName();

	Print << U"UserName: " << System::UserName();

	Print << U"FullUserName: " << System::FullUserName();

	Print << U"DefaultLocale: " << System::DefaultLocale();

	Print << U"DefaultLanguage: " << System::DefaultLanguage();

	while (System::Update())
	{

	}
}
Ryo SuzukiRyo Suzuki

ドライブの情報を取得する関数(Windows 版のみ)

# include <Siv3D.hpp> // OpenSiv3D v0.6.8

void Main()
{
	// Windows 以外では空の配列
	for (const auto& drive : System::EnumerateDrives())
	{
		Print << U"--------------------------------";
		Print << U"rootPath: " << drive.rootPath;
		Print << U"volumeName: " << drive.volumeName;
		Print << U"fileSystem: " << drive.fileSystem;
		Print << U"driveType: " << FromEnum(drive.driveType);
		Print << U"freeSpaceBytes: " << FormatDataSize(drive.freeSpaceBytes);
		Print << U"totalSizeBytes: " << FormatDataSize(drive.totalSizeBytes);
		Print << U"isSSD: " << drive.isSSD;
	}

	while (System::Update())
	{

	}
}