Created
May 25, 2024 08:51
-
-
Save comefrombottom/45e685e21da87ea8ee50ebbe040804a0 to your computer and use it in GitHub Desktop.
Transformer2D, Scoped...みたいな感じで使えるWindow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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