Skip to content

Commit db5f827

Browse files
authored
Merge pull request #406 from OneLoneCoder/image-patches
Added experimental "patches". Unstable right now, we'll see
2 parents 3da0fb4 + 654c794 commit db5f827

2 files changed

Lines changed: 264 additions & 2 deletions

File tree

examples/TEST_Patches.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
Example file for Patch Experiments
3+
4+
License (OLC-3)
5+
~~~~~~~~~~~~~~~
6+
7+
Copyright 2018 - 2025 OneLoneCoder.com
8+
9+
Redistribution and use in source and binary forms, with or without
10+
modification, are permitted provided that the following conditions
11+
are met:
12+
13+
1. Redistributions or derivations of source code must retain the above
14+
copyright notice, this list of conditions and the following disclaimer.
15+
16+
2. Redistributions or derivative works in binary form must reproduce
17+
the above copyright notice. This list of conditions and the following
18+
disclaimer must be reproduced in the documentation and/or other
19+
materials provided with the distribution.
20+
21+
3. Neither the name of the copyright holder nor the names of its
22+
contributors may be used to endorse or promote products derived
23+
from this software without specific prior written permission.
24+
25+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36+
37+
Links
38+
~~~~~
39+
YouTube: https://www.youtube.com/javidx9
40+
Discord: https://discord.gg/WhwHUMV
41+
Twitter: https://www.twitter.com/javidx9
42+
Twitch: https://www.twitch.tv/javidx9
43+
GitHub: https://www.github.com/onelonecoder
44+
Homepage: https://www.onelonecoder.com
45+
46+
Author
47+
~~~~~~
48+
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022, 2023, 2024, 2025
49+
50+
*/
51+
52+
53+
#define OLC_PGE_APPLICATION
54+
#include <olcPixelGameEngine.h>
55+
56+
57+
58+
class TEST_Patches : public olc::PixelGameEngine
59+
{
60+
public:
61+
TEST_Patches()
62+
{
63+
sAppName = "Testing Patches";
64+
}
65+
66+
std::unique_ptr<olc::Sprite> pSprite;
67+
std::unique_ptr<olc::Decal> pDecal;
68+
69+
public:
70+
bool OnUserCreate() override
71+
{
72+
pSprite = std::make_unique<olc::Sprite>("./assets/DirectionalSolids.png");
73+
pDecal = std::make_unique<olc::Decal>(pSprite.get());
74+
return true;
75+
}
76+
77+
78+
bool OnUserUpdate(float fElapsedTime) override
79+
{
80+
81+
Clear(olc::TANGERINE);
82+
DrawSprite({ 10,10 }, pSprite.get());
83+
84+
/*DrawSprite(
85+
olc::vf2d(GetMousePos()),
86+
pSprite->Patch({ 16, 0 }, { 16, 16 }),
87+
{ -30.0f, -30.0f });
88+
89+
DrawSprite(
90+
olc::vf2d(GetMousePos()),
91+
pSprite->Patch({ 0.25f, 0.5f }, { 0.5f, 0.0f }, { 0.75f, 0.5f }, { 0.5f, 1.0f }),
92+
{ 100.0f, 100.0f });
93+
94+
DrawSprite(
95+
olc::vf2d(GetMousePos()),
96+
*pSprite,
97+
{ 50.0f, -50.0f });*/
98+
99+
100+
101+
DrawDecal(
102+
olc::vf2d(GetMousePos()),
103+
pDecal->Patch({ 16, 0 }, { 16, 16 }),
104+
{ -30.0f, -30.0f });
105+
106+
DrawDecal(
107+
olc::vf2d(GetMousePos()),
108+
pDecal->Patch({ 0.25f, 0.5f }, { 0.5f, 0.0f }, { 0.75f, 0.5f }, { 0.5f, 1.0f }),
109+
{ 100.0f, 100.0f });
110+
111+
DrawDecal(
112+
olc::vf2d(GetMousePos()),
113+
*pDecal,
114+
{ 320.0f, -180.0f });
115+
116+
DrawLine({ 0,0 }, GetScreenSize(), olc::TANGERINE);
117+
118+
return true;
119+
}
120+
};
121+
122+
int main()
123+
{
124+
TEST_Patches demo;
125+
if (demo.Construct(1280, 720, 1, 1, false, false))
126+
demo.Start();
127+
return 0;
128+
}

olcPixelGameEngine.h

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,10 @@
357357
Updated Geometry2D to support non-segment line intersections
358358
+olcUTIL_Hardware3D.h file v1.01
359359
NOTICE OF DEPRECATION! olc::DecalInstance is to be removed and replaced by olc::GPUTask
360-
2.30:
360+
2.30: Experimental "Patches" - Pass image resources to drawing functions using intermediate placeholders
361+
+SpritePatch
362+
+DecalPatch
363+
+Added the Colour "Orange" cos some internet rando made me laugh about it :D
361364
362365
363366
!! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !!
@@ -932,6 +935,8 @@ namespace olc
932935
{
933936
class PixelGameEngine;
934937
class Sprite;
938+
struct SpritePatch;
939+
struct DecalPatch;
935940

936941
// Pixel Game Engine Advanced Configuration
937942
constexpr uint8_t nMouseButtons = 5;
@@ -989,7 +994,7 @@ namespace olc
989994
CYAN(0, 255, 255), DARK_CYAN(0, 128, 128), VERY_DARK_CYAN(0, 64, 64),
990995
BLUE(0, 0, 255), DARK_BLUE(0, 0, 128), VERY_DARK_BLUE(0, 0, 64),
991996
MAGENTA(255, 0, 255), DARK_MAGENTA(128, 0, 128), VERY_DARK_MAGENTA(64, 0, 64),
992-
WHITE(255, 255, 255), BLACK(0, 0, 0), BLANK(0, 0, 0, 0);
997+
WHITE(255, 255, 255), BLACK(0, 0, 0), BLANK(0, 0, 0, 0), TANGERINE(255, 165, 0);
993998
#endif
994999
// Thanks to scripticuk and others for updating the key maps
9951000
// NOTE: The GLUT platform will need updating, open to contributions ;)
@@ -1104,9 +1109,20 @@ namespace olc
11041109
std::vector<olc::Pixel> pColData;
11051110
Mode modeSample = Mode::NORMAL;
11061111

1112+
operator olc::SpritePatch();
1113+
olc::SpritePatch Patch(const olc::vi2d& pos, const olc::vi2d& size);
1114+
olc::SpritePatch Patch(const olc::vf2d& pBL, const olc::vf2d& pTL, const olc::vf2d& pTR, const olc::vf2d& pBR);
1115+
11071116
static std::unique_ptr<olc::ImageLoader> loader;
11081117
};
11091118

1119+
struct SpritePatch
1120+
{
1121+
olc::Sprite* sprite;
1122+
std::array<olc::vf2d, 4> coords;
1123+
};
1124+
1125+
11101126
// O------------------------------------------------------------------------------O
11111127
// | olc::Decal - A GPU resident storage of an olc::Sprite |
11121128
// O------------------------------------------------------------------------------O
@@ -1119,12 +1135,23 @@ namespace olc
11191135
void Update();
11201136
void UpdateSprite();
11211137

1138+
operator olc::DecalPatch();
1139+
olc::DecalPatch Patch(const olc::vi2d& pos, const olc::vi2d& size);
1140+
olc::DecalPatch Patch(const olc::vf2d& pBL, const olc::vf2d& pTL, const olc::vf2d& pTR, const olc::vf2d& pBR);
1141+
1142+
11221143
public: // But dont touch
11231144
int32_t id = -1;
11241145
olc::Sprite* sprite = nullptr;
11251146
olc::vf2d vUVScale = { 1.0f, 1.0f };
11261147
};
11271148

1149+
struct DecalPatch
1150+
{
1151+
olc::Decal* decal;
1152+
std::array<olc::vf2d, 4> coords;
1153+
};
1154+
11281155
enum class DecalMode
11291156
{
11301157
NORMAL,
@@ -1488,6 +1515,11 @@ namespace olc
14881515
// Clip a line segment to visible area
14891516
bool ClipLineToScreen(olc::vi2d& in_p1, olc::vi2d& in_p2);
14901517

1518+
1519+
// Patches
1520+
void DrawSprite(const olc::vf2d& pos, const SpritePatch& patch, const olc::vf2d& scale = { 1.0f, 1.0f });
1521+
void DrawDecal(const olc::vf2d& pos, const DecalPatch& patch, const olc::vf2d& scale = { 1.0f, 1.0f });
1522+
14911523
// Dont allow PGE to mark layers as dirty, so pixel graphics don't update
14921524
void EnablePixelTransfer(const bool bEnable = true);
14931525

@@ -2089,6 +2121,34 @@ namespace olc
20892121
return { width, height };
20902122
}
20912123

2124+
2125+
olc::Sprite::operator olc::SpritePatch()
2126+
{
2127+
return Patch({ 0,0 }, Size());
2128+
}
2129+
2130+
SpritePatch olc::Sprite::Patch(const olc::vi2d& pos, const olc::vi2d& size)
2131+
{
2132+
SpritePatch patch;
2133+
patch.sprite = this;
2134+
patch.coords[0] = olc::vf2d(pos.x, pos.y + size.y) / olc::vf2d(Size());
2135+
patch.coords[1] = olc::vf2d(pos) / olc::vf2d(Size());
2136+
patch.coords[2] = olc::vf2d(pos.x + size.x, pos.y) / olc::vf2d(Size());
2137+
patch.coords[3] = olc::vf2d(pos + size) / olc::vf2d(Size());
2138+
return patch;
2139+
}
2140+
2141+
SpritePatch olc::Sprite::Patch(const olc::vf2d& pBL, const olc::vf2d& pTL, const olc::vf2d& pTR, const olc::vf2d& pBR)
2142+
{
2143+
SpritePatch patch;
2144+
patch.sprite = this;
2145+
patch.coords[0] = pBL;
2146+
patch.coords[1] = pTL;
2147+
patch.coords[2] = pTR;
2148+
patch.coords[3] = pBR;
2149+
return patch;
2150+
}
2151+
20922152
// O------------------------------------------------------------------------------O
20932153
// | olc::Decal IMPLEMENTATION |
20942154
// O------------------------------------------------------------------------------O
@@ -2163,6 +2223,33 @@ namespace olc
21632223
return pSprite.get();
21642224
}
21652225

2226+
olc::Decal::operator olc::DecalPatch()
2227+
{
2228+
return Patch({ 0,0 }, this->sprite->Size());
2229+
}
2230+
2231+
DecalPatch olc::Decal::Patch(const olc::vi2d& pos, const olc::vi2d& size)
2232+
{
2233+
DecalPatch patch;
2234+
patch.decal = this;
2235+
patch.coords[0] = olc::vf2d(pos.x, pos.y + size.y) / olc::vf2d(this->sprite->Size());
2236+
patch.coords[1] = olc::vf2d(pos) / olc::vf2d(this->sprite->Size());
2237+
patch.coords[2] = olc::vf2d(pos.x + size.x, pos.y) / olc::vf2d(this->sprite->Size());
2238+
patch.coords[3] = olc::vf2d(pos + size) / olc::vf2d(this->sprite->Size());
2239+
return patch;
2240+
}
2241+
2242+
DecalPatch olc::Decal::Patch(const olc::vf2d& pBL, const olc::vf2d& pTL, const olc::vf2d& pTR, const olc::vf2d& pBR)
2243+
{
2244+
DecalPatch patch;
2245+
patch.decal = this;
2246+
patch.coords[0] = pBL;
2247+
patch.coords[1] = pTL;
2248+
patch.coords[2] = pTR;
2249+
patch.coords[3] = pBR;
2250+
return patch;
2251+
}
2252+
21662253
// O------------------------------------------------------------------------------O
21672254
// | olc::ResourcePack IMPLEMENTATION |
21682255
// O------------------------------------------------------------------------------O
@@ -3303,6 +3390,53 @@ namespace olc
33033390
}
33043391
}
33053392

3393+
3394+
void PixelGameEngine::DrawSprite(const olc::vf2d& pos, const SpritePatch& patch, const olc::vf2d& scale)
3395+
{
3396+
std::vector<olc::vf2d> transformed(4);
3397+
transformed = {
3398+
(patch.coords[0] - patch.coords[1]) * patch.sprite->Size() * scale + pos,
3399+
pos,
3400+
(patch.coords[2] - patch.coords[1]) * patch.sprite->Size() * scale + pos,
3401+
(patch.coords[3] - patch.coords[1]) * patch.sprite->Size() * scale + pos
3402+
} ;
3403+
3404+
std::vector<olc::vf2d> verts =
3405+
{
3406+
olc::vf2d{pos.x, pos.y + scale.y},
3407+
pos,
3408+
olc::vf2d{pos.x + scale.x, pos.y},
3409+
olc::vf2d{pos + scale}
3410+
};
3411+
3412+
std::vector<olc::vf2d> uv(patch.coords.begin(), patch.coords.end());
3413+
3414+
FillTexturedPolygon(verts, uv, { olc::WHITE, olc::WHITE , olc::WHITE , olc::WHITE }, patch.sprite, olc::DecalStructure::FAN);
3415+
}
3416+
3417+
void PixelGameEngine::DrawDecal(const olc::vf2d& pos, const DecalPatch& patch, const olc::vf2d& scale)
3418+
{
3419+
std::vector<olc::vf2d> transformed(4);
3420+
transformed = {
3421+
(patch.coords[0] - patch.coords[1]) * patch.decal->sprite->Size() * scale + pos,
3422+
pos,
3423+
(patch.coords[2] - patch.coords[1]) * patch.decal->sprite->Size() * scale + pos,
3424+
(patch.coords[3] - patch.coords[1]) * patch.decal->sprite->Size() * scale + pos
3425+
};
3426+
3427+
std::vector<olc::vf2d> verts =
3428+
{
3429+
olc::vf2d{pos.x, pos.y + scale.y},
3430+
pos,
3431+
olc::vf2d{pos.x + scale.x, pos.y},
3432+
olc::vf2d{pos + scale}
3433+
};
3434+
3435+
std::vector<olc::vf2d> uv(patch.coords.begin(), patch.coords.end());
3436+
3437+
DrawPolygonDecal(patch.decal, verts, uv, { olc::WHITE, olc::WHITE , olc::WHITE , olc::WHITE });
3438+
}
3439+
33063440
void PixelGameEngine::SetDecalMode(const olc::DecalMode& mode)
33073441
{
33083442
nDecalMode = mode;

0 commit comments

Comments
 (0)