Siv3D / OpenSiv3D

C++20 framework for creative coding 🎮🎨🎹 / Cross-platform support (Windows, macOS, Linux, and the Web)
https://siv3d.github.io/
MIT License
1.02k stars 140 forks source link

NinePatch クラス #1030

Closed Reputeless closed 1 year ago

Reputeless commented 1 year ago

20230713-182853-750

Reputeless commented 1 year ago

サンプル

# include <Siv3D.hpp>

Texture MakeExample9PatchTexture()
{
    // 描画された最大のアルファ成分を保持するブレンドステートを作成する関数
    auto MakeBlendState = []()
    {
        BlendState blendState = BlendState::Default2D;
        blendState.srcAlpha = Blend::SrcAlpha;
        blendState.dstAlpha = Blend::DestAlpha;
        blendState.opAlpha = BlendOp::Max;
        return blendState;
    };

    MSRenderTexture renderTexture{ Size{ 128, 128 }, ColorF{ 0.5, 0.0 } };
    {
        // レンダーターゲットを renderTexture に変更する
        const ScopedRenderTarget2D target{ renderTexture };

        // 描画された最大のアルファ成分を保持するブレンドステート
        const ScopedRenderStates2D blend{ MakeBlendState() };

        Triangle{ 32, 0, 32, 32, 0, 32 }.draw(ColorF{ 1.0 });
        Triangle{ 96, 0, 128, 32, 96, 32 }.draw(ColorF{ 1.0 });
        Triangle{ 32, 96, 32, 128, 0, 96 }.draw(ColorF{ 1.0 });
        Triangle{ 96, 96, 128, 96, 96, 128 }.draw(ColorF{ 1.0 });

        for (int32 x = 0; x < 4; ++x)
        {
            Rect{ (32 + x * 16), (x % 2 * 16), 16 }.draw(HSV{ 20.0, 0.4, 1.0 });
            Rect{ (32 + x * 16), ((x + 1) % 2 * 16), 16 }.draw(HSV{ 40.0, 0.4, 1.0 });

            Rect{ (32 + x * 16), (96 + x % 2 * 16), 16 }.draw(HSV{ 60.0, 0.4, 1.0 });
            Rect{ (32 + x * 16), (96 + (x + 1) % 2 * 16), 16 }.draw(HSV{ 80.0, 0.4, 1.0 });
        }

        for (int32 y = 0; y < 4; ++y)
        {
            Rect{ (y % 2 * 16), (32 + y * 16), 16 }.draw(HSV{ 100.0, 0.4, 1.0 });
            Rect{ ((y + 1) % 2 * 16), (32 + y * 16), 16 }.draw(HSV{ 120.0, 0.4, 0.9 });

            Rect{ (96 + y % 2 * 16), (32 + y * 16), 16 }.draw(HSV{ 140.0, 0.4, 1.0 });
            Rect{ (96 + (y + 1) % 2 * 16), (32 + y * 16), 16 }.draw(HSV{ 160.0, 0.4, 0.9 });
        }

        for (int32 y = 0; y < 4; ++y)
        {
            for (int32 x = 0; x < 4; ++x)
            {
                Rect{ (32 + x * 16), (32 + y * 16), 16 }.draw(HSV{ (IsEven(x + y) ? 180.0 : 200.0), 0.4, 1.0 });
            }
        }
    }
    Graphics2D::Flush();
    renderTexture.resolve();

    return renderTexture;
}

void Main()
{
    Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
    const Font font{ FontMethod::MSDF, 48, Typeface::Bold };

    const Texture ninePatchTexture = MakeExample9PatchTexture();
    constexpr int32 TextureCornerSize = 32;

    const NinePatch ninePatch{ ninePatchTexture, TextureCornerSize, NinePatch::Style::Default() };
    const NinePatch ninePatchTiled{ ninePatchTexture, TextureCornerSize, NinePatch::Style::TileAll() };

    bool repeat = true;
    bool linearFilter = true;
    size_t textureScaleIndex = 2;
    double width = 400.0;
    double height = 300.0;

    while (System::Update())
    {
        RoundRect{ 40, 40, 500, 180, 10 }.draw(ColorF{ 0.25 });
        font(U"9-patch texture").draw(30, Vec2{ 60, 60 }, ColorF{ 0.98 });
        ninePatchTexture.draw(Vec2{ 320, 70 });

        const double textureScale = Math::Exp2(textureScaleIndex - 2.0);
        const TextureFilter textureFilter = (linearFilter ? TextureFilter::Linear : TextureFilter::Nearest);

        if (repeat)
        {
            ninePatchTiled.draw(RectF{ 40, 240, width, height }, textureScale, textureFilter);
        }
        else
        {
            ninePatch.draw(RectF{ 40, 240, width, height }, textureScale, textureFilter);
        }

        SimpleGUI::CheckBox(repeat, U"Tiled", Vec2{ 560, 40 }, 200);
        SimpleGUI::CheckBox(linearFilter, U"LinearFilter", Vec2{ 560, 80 }, 200);
        SimpleGUI::RadioButtons(textureScaleIndex, { U"0.25", U"0.5", U"1.0", U"2.0" }, Vec2{ 560, 120 }, 200);
        SimpleGUI::Slider(width, 64.0, 480.0, Vec2{ 560, 280 }, 200);
        SimpleGUI::Slider(height, 64.0, 320.0, Vec2{ 560, 320 }, 200);
    }
}
Reputeless commented 1 year ago

サンプル 2

# include <Siv3D.hpp>

void Main()
{
    Scene::SetBackground(ColorF{ 0.7 });
    constexpr int32 CellSize = 20;
    const Font font{ FontMethod::MSDF, 48, U"example/font/RocknRoll/RocknRollOne-Regular.ttf" };
    Stopwatch stopwatch{ StartImmediately::Yes };

    Array<NinePatch> ninePatches =
    {
        NinePatch{ U"patch0.png", 64 },
        NinePatch{ U"patch1.png", 64 },
        NinePatch{ U"patch2.png", 64 },
        NinePatch{ U"patch3.png", 30 },
        NinePatch{ U"patch4.png", 8 },
    };

    size_t index = 0;
    double width = 640;
    double height = 220;

    while (System::Update())
    {
        for (int32 y = 0; y < (Scene::Height() / CellSize); ++y)
        {
            for (int32 x = 0; x < (Scene::Width() / CellSize); ++x)
            {
                if (IsEven(y + x))
                {
                    Rect{ (x * CellSize), (y * CellSize), CellSize }.draw(ColorF{ 0.65 });
                }
            }
        }

        {
            const Transformer2D transformer(Mat3x2::Translate(80, 40));

            ninePatches[index].getTexture().draw();
            const auto& patchSize = ninePatches[index].getPatchSize();

            patchSize.topLeftRect().drawFrame(1, 0);
            patchSize.topRect().drawFrame(1, 0);
            patchSize.topRightRect().drawFrame(1, 0);
            patchSize.leftRect().drawFrame(1, 0);
            patchSize.centerRect().drawFrame(1, 0);
            patchSize.rightRect().drawFrame(1, 0);
            patchSize.bottomLeftRect().drawFrame(1, 0);
            patchSize.bottomRect().drawFrame(1, 0);
            patchSize.bottomRightRect().drawFrame(1, 0);
        }

        if (SimpleGUI::RadioButtons(index, { U"patch0", U"patch1", U"patch2", U"patch3", U"patch4" }, Vec2{ 460, 40 }, 120))
        {
            stopwatch.restart();
        }

        SimpleGUI::Slider(width, 100.0, 800.0, Vec2{ 600, 40 }, 120);
        SimpleGUI::Slider(height, 100.0, 320.0, Vec2{ 600, 80 }, 120);

        const RectF rect{ ((800 - width) / 2), 280, width, height };

        if (InRange((int32)index, 0, 2))
        {
            ninePatches[index].draw(rect, 0.5);
        }
        else if (index == 3)
        {
            ninePatches[index].draw(rect, 2.0, TextureFilter::Nearest);
        }
        else if (index == 4)
        {
            ninePatches[index].draw(rect, 8.0, TextureFilter::Nearest);
        }

        font(U"Hello, Siv3D!"_sv.substr(0, stopwatch.ms() / 30)).draw(36, rect.stretched(-60, -48), ColorF{ 0.98 });
    }
}

patch0 patch1 patch2 patch3 patch4