Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Created May 25, 2024 08:51
Show Gist options
  • Save comefrombottom/45e685e21da87ea8ee50ebbe040804a0 to your computer and use it in GitHub Desktop.
Save comefrombottom/45e685e21da87ea8ee50ebbe040804a0 to your computer and use it in GitHub Desktop.
Transformer2D, Scoped...みたいな感じで使えるWindow
# include <Siv3D.hpp> // OpenSiv3D v0.6.14
//宣言
class MiniWindow {
public:
MiniWindow(const Rect& rect, double scale ,const Color& backgroundColor = ColorF(0.4));
void update(const Size parentSceneSize);
void resolve() { renderTexture.resolve(); }
void draw();
void flushResolveDraw();
RectF titleBarRect() { return RectF(Arg::bottomLeft = m_pos, renderTexture.size().x, titleBarHeight); }
Size windowSize() const { return renderTexture.size(); }
Size sceneSize() const { return (renderTexture.size() / m_scale).asPoint(); }
Point m_pos;
double m_scale;
Color m_backgroundColor = ColorF(0.4);
MSRenderTexture renderTexture;
Optional<Point> windowGrabbedOffset;
double titleBarHeight = 20;
double windowRound = 5;
class ScopedMiniWindow createScopedMiniWindow() const;
class ScopedMiniWindowUpdateDraw use(const Size parentSceneSize);
};
class ScopedMiniWindow :Uncopyable {
public:
explicit ScopedMiniWindow(const MiniWindow& miniWindow);
private:
ScopedRenderTarget2D renderTarget;
Transformer2D transformer;
Transformer2D cursorTransformer;
Transformer2D cameraTransformer;
};
class ScopedMiniWindowUpdateDraw {
public:
ScopedMiniWindowUpdateDraw(MiniWindow& miniWindow,const Size parentSceneSize);
private:
class OnlyUpdateDrawer {
public:
OnlyUpdateDrawer(MiniWindow& miniWindow, const Size parentSceneSize);
~OnlyUpdateDrawer();
private:
MiniWindow& m_miniWindow;
};
OnlyUpdateDrawer m_onlyUpdateDrawer;
ScopedMiniWindow m_scopedMiniWindow;
};
//実装
//MiniWindow
MiniWindow::MiniWindow(const Rect& rect, double scale, const Color& backgroundColor)
{
m_pos = rect.pos;
m_scale = scale;
m_backgroundColor = backgroundColor;
renderTexture = MSRenderTexture(rect.size);
}
void MiniWindow::update(const Size parentSceneSize)
{
renderTexture.clear(m_backgroundColor);
if (windowGrabbedOffset)
{
m_pos = Cursor::Pos() + *windowGrabbedOffset;
m_pos.x = Clamp(m_pos.x, windowGrabbedOffset->x, parentSceneSize.x + windowGrabbedOffset->x);
m_pos.y = Clamp(m_pos.y, windowGrabbedOffset->y, parentSceneSize.y + windowGrabbedOffset->y);
}
if (titleBarRect().leftClicked())
{
windowGrabbedOffset = m_pos - Cursor::Pos();
}
if (MouseL.up())
{
windowGrabbedOffset.reset();
}
}
void MiniWindow::draw()
{
RectF(m_pos, renderTexture.size()).rounded(0, 0, windowRound, windowRound).toBuffer2D(m_pos, renderTexture.size()).draw(renderTexture);
//renderTexture.draw(pos);
titleBarRect().rounded(windowRound, windowRound, 0, 0).draw();
}
void MiniWindow::flushResolveDraw()
{
Graphics2D::Flush();
resolve();
draw();
}
ScopedMiniWindow MiniWindow::createScopedMiniWindow() const
{
return ScopedMiniWindow(*this);
}
ScopedMiniWindowUpdateDraw MiniWindow::use(const Size parentSceneSize = Scene::Size())
{
return ScopedMiniWindowUpdateDraw(*this, parentSceneSize);
}
//ScopedMiniWindow
ScopedMiniWindow::ScopedMiniWindow(const MiniWindow& miniWindow)
:renderTarget(ScopedRenderTarget2D(miniWindow.renderTexture))
,transformer(Transformer2D(Mat3x2::Scale(miniWindow.m_scale), TransformCursor::No, Transformer2D::Target::SetLocal))
,cursorTransformer(Transformer2D(Mat3x2::Identity(), Mat3x2::Scale(miniWindow.m_scale).translated(miniWindow.m_pos)))
,cameraTransformer(Transformer2D(Mat3x2::Identity(), Transformer2D::Target::SetCamera))
{
}
//ScopedMiniWindowUpdateDraw
ScopedMiniWindowUpdateDraw::ScopedMiniWindowUpdateDraw(MiniWindow& miniWindow, const Size parentSceneSize)
:m_onlyUpdateDrawer(miniWindow,parentSceneSize)
,m_scopedMiniWindow(miniWindow)
{
}
ScopedMiniWindowUpdateDraw::OnlyUpdateDrawer::OnlyUpdateDrawer(MiniWindow& miniWindow, const Size parentSceneSize)
:m_miniWindow(miniWindow)
{
m_miniWindow.update(parentSceneSize);
}
ScopedMiniWindowUpdateDraw::OnlyUpdateDrawer::~OnlyUpdateDrawer()
{
m_miniWindow.flushResolveDraw();
}
class SampleCode {
public:
void update() {
TextureAsset(U"windmill").draw(20, 20);
FontAsset(U"48")(U"Hello, Siv3D!🎮").draw(64, Vec2{ 20, 340 }, ColorF{ 0.2, 0.4, 0.8 });
FontAsset(U"48")(U"Siv3D (シブスリーディー) は、ゲームやアプリを楽しく簡単な C++ コードで開発できるフレームワークです。")
.draw(18, Rect{ 20, 430, 480, 200 }, Palette::Black);
Rect{ 540, 20, 80, 80 }.draw();
RoundRect{ 680, 20, 80, 200, 20 }.draw(ColorF{ 0.0, 0.4, 0.6 });
Circle{ 580, 180, 40 }.draw(Palette::Seagreen);
Line{ 540, 330, 760, 260 }.drawArrow(8, SizeF{ 20, 20 }, ColorF{ 0.4 });
Circle{ Cursor::Pos(), 40 }.draw(ColorF{ 1.0, 0.0, 0.0, 0.5 });
if (SimpleGUI::Button(U"count: {}"_fmt(count), Vec2{ 520, 370 }, 120, (checked == false)))
{
++count;
}
SimpleGUI::CheckBox(checked, U"Lock \U000F033E", Vec2{ 660, 370 }, 120);
SimpleGUI::Slider(U"speed: {:.1f}"_fmt(speed), speed, 100, 400, Vec2{ 520, 420 }, 140, 120);
if (KeyLeft.pressed())
{
playerPosX = Max((playerPosX - speed * Scene::DeltaTime()), 60.0);
isPlayerFacingRight = false;
}
if (KeyRight.pressed())
{
playerPosX = Min((playerPosX + speed * Scene::DeltaTime()), 740.0);
isPlayerFacingRight = true;
}
TextureAsset(U"emoji").scaled(0.75).mirrored(isPlayerFacingRight).drawAt(playerPosX, 540);
}
private:
int32 count = 0;
bool checked = false;
double speed = 200.0;
double playerPosX = 400;
bool isPlayerFacingRight = true;
};
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
TextureAsset::Register(U"windmill", U"example/windmill.png");
TextureAsset::Register(U"emoji", U"🦖"_emoji);
FontAsset::Register(U"48", FontMethod::MSDF, 48, Typeface::Bold);
Font emojiFont(48,Typeface::ColorEmoji);
FontAsset(U"48").addFallback(emojiFont);
SampleCode sampleCode0;
SampleCode sampleCode1;
SampleCode sampleCode2;
SampleCode sampleCode3;
MiniWindow miniWindow1{ Rect{ 100, 100, 400, 300 }, 0.5 ,ColorF(0.7,0.6,0.8)};
MiniWindow miniWindow2{ Rect{ 100, 100, 400, 300 }, 0.5,ColorF(0.8,0.6,0.7) };
MiniWindow miniWindow3{ Rect{ 400, 300, 400, 300 }, 0.5,ColorF(0.6,0.7,0.8) };
while (System::Update())
{
sampleCode0.update();
{
auto _ = miniWindow1.use();
sampleCode1.update();
{
auto _ = miniWindow2.use(miniWindow1.sceneSize());
sampleCode2.update();
}
}
{
auto _ = miniWindow3.use();
sampleCode3.update();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment