-
-
Save Reputeless/47c8949f6337d25c17d22ebbe11fdbc4 to your computer and use it in GitHub Desktop.
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> // Siv3D August 2016 v2 | |
namespace s3d | |
{ | |
inline constexpr int32 CaluculateFanQuality(const double r) noexcept | |
{ | |
return r <= 1.0 ? 3 | |
: r <= 6.0 ? 5 | |
: r <= 12.0 ? 8 | |
: static_cast<int32>(std::min(64.0, r * 0.2 + 6)); | |
} | |
struct TexturedRoundRect | |
{ | |
RoundRect rect; | |
Texture texture; | |
FloatRect uvRect; | |
TexturedRoundRect() = default; | |
TexturedRoundRect( | |
const Texture& _texture, | |
float l, | |
float t, | |
float r, | |
float b, | |
const RoundRect& _rect) | |
: rect(_rect) | |
, texture(_texture) | |
, uvRect(l, t, r, b) {} | |
TexturedRoundRect( | |
const Texture& _texture, | |
const FloatRect& _uvRect, | |
const RoundRect& _rect) | |
: rect(_rect) | |
, texture(_texture) | |
, uvRect(_uvRect) {} | |
const RoundRect& draw(const ColorF& diffuse = Palette::White) const | |
{ | |
const double rr = std::min({ rect.w * 0.5, rect.h * 0.5, rect.r }); | |
const float scale = static_cast<float>(Graphics2D::GetMaxScaling()); | |
const int32 quality = CaluculateFanQuality(rr * scale); | |
const double radDelta = Math::HalfPi / (quality - 1); | |
Array<Float2> fanPositions(quality); | |
for (int32 i = 0; i < quality; ++i) | |
{ | |
fanPositions[i] = Vec2(Circular(rr, radDelta * i)); | |
} | |
const bool uniteV = (rect.h * 0.5 == rr); | |
const bool uniteH = (rect.w * 0.5 == rr); | |
const std::array<Float2, 4> centers = | |
{ { | |
{ rect.x + rect.w - rr, rect.y + rr }, | |
{ rect.x + rect.w - rr, rect.y + rect.h - rr }, | |
{ rect.x + rr, rect.y + rect.h - rr }, | |
{ rect.x + rr, rect.y + rr }, | |
} }; | |
const uint32 vertexSize = (quality - uniteV + quality - uniteH) * 2; | |
const uint32 indexSize = (vertexSize - 2) * 3; | |
Sprite sprite(vertexSize, indexSize); | |
{ | |
SpriteVertex* pVertex = sprite.vertices.data(); | |
for (int32 i = 0; i < quality - uniteV; ++i) | |
{ | |
pVertex->pos = centers[0] + fanPositions[i]; | |
++pVertex; | |
} | |
for (int32 i = 0; i < quality - uniteH; ++i) | |
{ | |
pVertex->pos = centers[1] + Float2(fanPositions[quality - i - 1].x, -fanPositions[quality - i - 1].y); | |
++pVertex; | |
} | |
for (int32 i = 0; i < quality - uniteV; ++i) | |
{ | |
pVertex->pos = centers[2] + Float2(-fanPositions[i].x, -fanPositions[i].y); | |
++pVertex; | |
} | |
for (int32 i = 0; i < quality - uniteH; ++i) | |
{ | |
pVertex->pos = centers[3] + Float2(-fanPositions[quality - i - 1].x, fanPositions[quality - i - 1].y); | |
++pVertex; | |
} | |
} | |
{ | |
const float uOffst = uvRect.left; | |
const float vOffst = uvRect.top; | |
const float left = static_cast<float>(rect.x); | |
const float ws = (uvRect.right - uvRect.left) / static_cast<float>(rect.w); | |
const float top = static_cast<float>(rect.y); | |
const float hs = (uvRect.bottom - uvRect.top) / static_cast<float>(rect.h); | |
SpriteVertex* pVertex = sprite.vertices.data(); | |
for (size_t i = 0; i < vertexSize; ++i) | |
{ | |
const float u = uOffst + (pVertex->pos.x - left) * ws; | |
const float v = vOffst + (pVertex->pos.y - top) * hs; | |
(pVertex++)->tex.set(u, v); | |
} | |
} | |
{ | |
const Float4 colorF = diffuse.rgba(); | |
SpriteVertex* pVertex = sprite.vertices.data(); | |
for (size_t i = 0; i < vertexSize; ++i) | |
{ | |
(pVertex++)->color = ColorF(colorF.x, colorF.y, colorF.z, colorF.w); | |
} | |
} | |
{ | |
uint32* pIndex = sprite.indices.data(); | |
for (uint32 i = 0; i < (vertexSize - 2); ++i) | |
{ | |
pIndex[i * 3 + 1] = i + 1; | |
pIndex[i * 3 + 2] = (i + 2 < vertexSize) ? (i + 2) : 0; | |
} | |
} | |
sprite.draw(texture); | |
return rect; | |
} | |
RoundRect drawAt(double x, double y, const ColorF& diffuse = Palette::White) const | |
{ | |
RoundRect rr = rect; | |
rr.setCenter(x, y); | |
return TexturedRoundRect(texture, uvRect, rr).draw(diffuse); | |
} | |
RoundRect drawAt(const Vec2& pos, const ColorF& diffuse = Palette::White) const | |
{ | |
return drawAt(pos.x, pos.y, diffuse); | |
} | |
}; | |
inline TexturedRoundRect RoundTex(const RoundRect& rect, const Texture& texture) | |
{ | |
return TexturedRoundRect(texture, | |
0.0f, 0.0f, 1.0f, 1.0f, | |
rect); | |
} | |
inline TexturedRoundRect RoundTex(const RoundRect& rect, const TextureRegion& textureRegion) | |
{ | |
return TexturedRoundRect(textureRegion.texture, | |
textureRegion.uvRect, | |
rect); | |
} | |
} | |
void Main() | |
{ | |
const Texture texture(L"example/siv3d-kun.png"); | |
const RoundRect rrect(40, 40, 80, 80, 8); | |
while (System::Update()) | |
{ | |
rrect.draw(Palette::Skyblue); | |
RoundTex(rrect, texture(85, 5, 120, 120)).draw(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment