From 2c30e7b863a64d48091179a0d4e4aeabdeb3d935 Mon Sep 17 00:00:00 2001 From: John Galvin <96908304+Johnnyg63@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:58:37 +0100 Subject: [PATCH 1/3] Issue293 Added Single Header project to xcode project file --- .../olcPGE3.xcodeproj/project.pbxproj | 152 +++++++++++++++++- .../xcschemes/olcPGE3_SH.xcscheme | 79 +++++++++ 2 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 dev/xcode_macos/olcPGE3.xcodeproj/xcshareddata/xcschemes/olcPGE3_SH.xcscheme diff --git a/dev/xcode_macos/olcPGE3.xcodeproj/project.pbxproj b/dev/xcode_macos/olcPGE3.xcodeproj/project.pbxproj index f8fd6154..f0bbb815 100644 --- a/dev/xcode_macos/olcPGE3.xcodeproj/project.pbxproj +++ b/dev/xcode_macos/olcPGE3.xcodeproj/project.pbxproj @@ -3,11 +3,18 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ 460496082E362F190047E223 /* test_mh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 460495FB2E300E0F0047E223 /* test_mh.cpp */; }; + 4610525930593E6D00C2BC3A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E85DF82E39135B00B74FA3 /* OpenGL.framework */; }; + 4610525A30593E6D00C2BC3A /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46B1E5942E40F8B0009734EC /* MetalKit.framework */; }; + 4610525B30593E6D00C2BC3A /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46B1E5922E40F8A6009734EC /* AppKit.framework */; }; + 4610525C30593E6D00C2BC3A /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E85DFC2E39137100B74FA3 /* Metal.framework */; }; + 4610525D30593E6D00C2BC3A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E85DFA2E39136800B74FA3 /* QuartzCore.framework */; }; + 4610525E30593E6D00C2BC3A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E85DF62E39135300B74FA3 /* Foundation.framework */; }; + 4610526630593EE400C2BC3A /* assets in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4610526530593EE400C2BC3A /* assets */; }; 46152BD72FE2DD1E00DCAC34 /* hw_touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46152BD62FE2DD1E00DCAC34 /* hw_touch.cpp */; }; 462680A42E69D03800799C36 /* image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 460495EC2E300E000047E223 /* image.cpp */; }; 462680A52E69D15C00799C36 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E85DF82E39135B00B74FA3 /* OpenGL.framework */; }; @@ -32,6 +39,16 @@ /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ + 4610525F30593E6D00C2BC3A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 7; + files = ( + 4610526630593EE400C2BC3A /* assets in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8998CE1E2E057F4E007DDD96 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -67,6 +84,9 @@ 460495F12E300E000047E223 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; 460495F22E300E000047E223 /* window.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = window.cpp; sourceTree = ""; }; 460495FB2E300E0F0047E223 /* test_mh.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_mh.cpp; sourceTree = ""; }; + 4610522030593E6300C2BC3A /* olcPixelGameEngine3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = olcPixelGameEngine3.h; path = /Users/mickymacm4/Documents/olcPixelGameEngine3_Issue293/olcPixelGameEngine3.h; sourceTree = ""; }; + 4610526330593E6D00C2BC3A /* olcPGE3_SH */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = olcPGE3_SH; sourceTree = BUILT_PRODUCTS_DIR; }; + 4610526530593EE400C2BC3A /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = assets; path = ../../examples/assets; sourceTree = ""; }; 46152BD52FE2DD1E00DCAC34 /* hw_touch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hw_touch.h; sourceTree = ""; }; 46152BD62FE2DD1E00DCAC34 /* hw_touch.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = hw_touch.cpp; sourceTree = ""; }; 462680D02E6C3C4500799C36 /* gpu_iface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_iface.cpp; sourceTree = ""; }; @@ -103,7 +123,64 @@ 8998CE372E057F92007DDD96 /* transform2d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transform2d.h; sourceTree = ""; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 4610526430593E6D00C2BC3A /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + olcPGE3_AntiAliasing.cpp, + olcPGE3_BatchesOfFills.cpp, + olcPGE3_BatchesOfLines.cpp, + olcPGE3_BlendingModes.cpp, + olcPGE3_Camera2D_Tiles.cpp, + olcPGE3_CirclesEllipses.cpp, + olcPGE3_Extensions.cpp, + olcPGE3_Fish.cpp, + olcPGE3_FrameGraph.cpp, + "olcPGE3_ImageQuads-FromMemory.cpp", + olcPGE3_ImageQuads.cpp, + olcPGE3_ImageRect.cpp, + olcPGE3_ImageRegion.cpp, + olcPGE3_ImageScaleRotate.cpp, + olcPGE3_ImageTiling.cpp, + olcPGE3_Keyboard.cpp, + olcPGE3_Lines.cpp, + olcPGE3_LocalTransforms.cpp, + olcPGE3_Mouse.cpp, + olcPGE3_Pixels.cpp, + olcPGE3_PixelShaders.cpp, + olcPGE3_Polygons.cpp, + olcPGE3_Rectangles.cpp, + olcPGE3_Shockwave.cpp, + olcPGE3_SimplePixelShaders.cpp, + olcPGE3_TextBasics.cpp, + olcPGE3_TextFontMap.cpp, + olcPGE3_Touch.cpp, + olcPGE3_WorldTransform.cpp, + ); + target = 4610524630593E6D00C2BC3A /* olcPGE3_SH */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 4610521930593E6300C2BC3A /* examples */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (4610526430593E6D00C2BC3A /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); name = examples; path = /Users/mickymacm4/Documents/olcPixelGameEngine3_Issue293/examples; sourceTree = ""; }; + 4610521F30593E6300C2BC3A /* extensions */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); name = extensions; path = /Users/mickymacm4/Documents/olcPixelGameEngine3_Issue293/extensions; sourceTree = ""; }; + 4610522730593E6300C2BC3A /* utilities */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); name = utilities; path = /Users/mickymacm4/Documents/olcPixelGameEngine3_Issue293/utilities; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ + 4610525830593E6D00C2BC3A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4610525930593E6D00C2BC3A /* OpenGL.framework in Frameworks */, + 4610525A30593E6D00C2BC3A /* MetalKit.framework in Frameworks */, + 4610525B30593E6D00C2BC3A /* AppKit.framework in Frameworks */, + 4610525C30593E6D00C2BC3A /* Metal.framework in Frameworks */, + 4610525D30593E6D00C2BC3A /* QuartzCore.framework in Frameworks */, + 4610525E30593E6D00C2BC3A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8998CE1D2E057F4E007DDD96 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -136,6 +213,11 @@ 8998CE172E057F4E007DDD96 = { isa = PBXGroup; children = ( + 4610526530593EE400C2BC3A /* assets */, + 4610521930593E6300C2BC3A /* examples */, + 4610521F30593E6300C2BC3A /* extensions */, + 4610522030593E6300C2BC3A /* olcPixelGameEngine3.h */, + 4610522730593E6300C2BC3A /* utilities */, 8998CE322E057F92007DDD96 /* src */, 8998CE2A2E057F85007DDD96 /* tests */, 46E85DF52E39135300B74FA3 /* Frameworks */, @@ -147,6 +229,7 @@ isa = PBXGroup; children = ( 8998CE202E057F4E007DDD96 /* olcPGE3 */, + 4610526330593E6D00C2BC3A /* olcPGE3_SH */, ); name = Products; sourceTree = ""; @@ -220,6 +303,28 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 4610524630593E6D00C2BC3A /* olcPGE3_SH */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4610526030593E6D00C2BC3A /* Build configuration list for PBXNativeTarget "olcPGE3_SH" */; + buildPhases = ( + 4610524730593E6D00C2BC3A /* Sources */, + 4610525830593E6D00C2BC3A /* Frameworks */, + 4610525F30593E6D00C2BC3A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 4610521930593E6300C2BC3A /* examples */, + 4610521F30593E6300C2BC3A /* extensions */, + 4610522730593E6300C2BC3A /* utilities */, + ); + name = olcPGE3_SH; + productName = olcPGE3; + productReference = 4610526330593E6D00C2BC3A /* olcPGE3_SH */; + productType = "com.apple.product-type.tool"; + }; 8998CE1F2E057F4E007DDD96 /* olcPGE3 */ = { isa = PBXNativeTarget; buildConfigurationList = 8998CE272E057F4E007DDD96 /* Build configuration list for PBXNativeTarget "olcPGE3" */; @@ -232,6 +337,11 @@ ); dependencies = ( ); + fileSystemSynchronizedGroups = ( + 4610521930593E6300C2BC3A /* examples */, + 4610521F30593E6300C2BC3A /* extensions */, + 4610522730593E6300C2BC3A /* utilities */, + ); name = olcPGE3; productName = olcPGE3; productReference = 8998CE202E057F4E007DDD96 /* olcPGE3 */; @@ -265,11 +375,19 @@ projectRoot = ""; targets = ( 8998CE1F2E057F4E007DDD96 /* olcPGE3 */, + 4610524630593E6D00C2BC3A /* olcPGE3_SH */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ + 4610524730593E6D00C2BC3A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8998CE1C2E057F4E007DDD96 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -296,6 +414,29 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + 4610526130593E6D00C2BC3A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + HEADER_SEARCH_PATHS = "$[PROJECT_DIR]/"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4610526230593E6D00C2BC3A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + HEADER_SEARCH_PATHS = "$[PROJECT_DIR]/"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 8998CE252E057F4E007DDD96 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -430,6 +571,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 4610526030593E6D00C2BC3A /* Build configuration list for PBXNativeTarget "olcPGE3_SH" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4610526130593E6D00C2BC3A /* Debug */, + 4610526230593E6D00C2BC3A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 8998CE1B2E057F4E007DDD96 /* Build configuration list for PBXProject "olcPGE3" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/dev/xcode_macos/olcPGE3.xcodeproj/xcshareddata/xcschemes/olcPGE3_SH.xcscheme b/dev/xcode_macos/olcPGE3.xcodeproj/xcshareddata/xcschemes/olcPGE3_SH.xcscheme new file mode 100644 index 00000000..3952f1de --- /dev/null +++ b/dev/xcode_macos/olcPGE3.xcodeproj/xcshareddata/xcschemes/olcPGE3_SH.xcscheme @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0edfc5d15b619af5af1c0060eeafa7fab183e11d Mon Sep 17 00:00:00 2001 From: John Galvin <96908304+Johnnyg63@users.noreply.github.com> Date: Tue, 15 Sep 2026 11:37:52 +0100 Subject: [PATCH 2/3] Enhance README with detailed XCode setup instructions Expanded instructions for cloning and setting up the XCode project, including detailed steps and images. --- dev/xcode_macos/README.md | 41 +++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/dev/xcode_macos/README.md b/dev/xcode_macos/README.md index 8e61d3bc..163f22c6 100644 --- a/dev/xcode_macos/README.md +++ b/dev/xcode_macos/README.md @@ -7,14 +7,47 @@
    -
  • Launch XCode and select **Clone and existing project**
  • -
  • Enter the repo git link and click **Clone**
  • -
  • Once the project is cloned, XCode will automatically detect the olcPGE3.xcodeproj folder and load the solution for you
  • -
  • Finally althought the olcPGE3.xcodeproj is displayed as a folder in GitHub, XCode will detected and display it as an XCode project
  • +
  • + 1:Naviage to https://github.com/OneLoneCoder/olcPixelGameEngine3
    + 2: Select the Main branch
    + 3: Click the green Code button dropdown
    + 4: Click the Copy button to copy the git url
    + image
    +
  • +
  • + Launch XCode and select Clone Git Repository...
    + image
    +
  • +
  • + 1 :Enter the repo git link and click Clone
    + image
    + 2: At the branch prompt select main
    + 3: At the folder prompt select defaults
    +
  • +
  • + Open the xcode-macos folder and double click olcPGE3.xcodeproj
    + image
    + Wait for the project to load
    +
  • +
  • + 1: Select Project Filter
    + 2: Select Project, +
    - olcPGE is a Multi-header file, builds all headers in the **src** directory +
    - olcPGE_SH is a Single-header file (released version), builds the selected example in the examples directory using olcPixelGameEngine3.h + image
    + 3: Press play and watch the magic happen
    +
  • +
  • +
    + **IMPORTANT**
    This Xcode project is setup using all the defaults of xcode, therefore the debug/release folders are held within the xcode **Derived Data** folder, hence why the project is setup to auto copy the **assets** folder to the debug/release output.
    + If you use a different setup, please edit the xcode project settings to suit +
    +

+

    Some simple rules:
  • The olcPGE3.xcodeproj folder and files are all auto generated
  • The olcPGE3.xcodeproj folder and files should never be editied outside of XCode itself
  • From 1911866ba5e48bdbaf54a793267000edb3c18b28 Mon Sep 17 00:00:00 2001 From: Javidx9 <25419386+OneLoneCoder@users.noreply.github.com> Date: Wed, 16 Sep 2026 21:30:30 +0100 Subject: [PATCH 3/3] [draw] Fix pixel get/set asymmetry [draw] Added UNSAFE pixel reads with no bounds check [transform2d] changed order of ops for point of rotation [examples] modified pixel example to demo transformed get/sets --- .../olcPGE3_BuildSH/olcPGE3_BuildSH.vcxproj | 8 +-- dev/src/draw.cpp | 40 +++++++++-- dev/src/draw.h | 26 ++++++- dev/src/transform2d.h | 2 +- examples/olcPGE3_Pixels.cpp | 4 ++ olcPixelGameEngine3.h | 68 +++++++++++++++++-- 6 files changed, 130 insertions(+), 18 deletions(-) diff --git a/dev/msvc/olcPGE3_BuildSH/olcPGE3_BuildSH.vcxproj b/dev/msvc/olcPGE3_BuildSH/olcPGE3_BuildSH.vcxproj index 2e2a6919..cf6056b7 100644 --- a/dev/msvc/olcPGE3_BuildSH/olcPGE3_BuildSH.vcxproj +++ b/dev/msvc/olcPGE3_BuildSH/olcPGE3_BuildSH.vcxproj @@ -22,8 +22,8 @@ true true - false - false + true + true true @@ -140,8 +140,8 @@ true true - true - true + false + false true diff --git a/dev/src/draw.cpp b/dev/src/draw.cpp index 56fb76cc..f3e19c42 100644 --- a/dev/src/draw.cpp +++ b/dev/src/draw.cpp @@ -242,16 +242,48 @@ void Draw::Pixel(const olc::vf2d& pos, const olc::Pixel col, const olc::Pixel ti // otherwise do nothing } -olc::Pixel olc::Draw::GetPixel(olc::Image& image, const olc::vf2d& pos) +olc::Pixel olc::Draw::GetPixel(olc::Image& image, const olc::vf2d& pos, const olc::Pixel failcol) +{ + olc::vf2d tpos = transformAffine.forwardRound(pos); + if (tpos.x >= 0 && tpos.y >= 0 && tpos.x < float(image.Size().x) && tpos.y < float(image.Size().y)) + { + PrepareImageForSW(image); + return image.Pixel(tpos); + } + else + return failcol; +} + +olc::Pixel olc::Draw::GetPixel(const olc::vf2d& pos, const olc::Pixel failcol) +{ + return GetPixel(GetTarget(), pos, failcol); +} + +olc::Pixel olc::Draw::GetRawPixel(olc::Image& image, const olc::vi2d& pos, const olc::Pixel failcol) +{ + if (pos.x >= 0 && pos.y >= 0 && pos.x < float(image.Size().x) && pos.y < float(image.Size().y)) + { + PrepareImageForSW(image); + return image.Pixel(pos); + } + else + return failcol; +} + +olc::Pixel olc::Draw::GetRawPixel(const olc::vi2d& pos, const olc::Pixel failcol) +{ + return GetRawPixel(GetTarget(), pos, failcol); +} + +olc::Pixel olc::Draw::GetUnsafeRawPixel(olc::Image& image, const olc::vi2d& pos) { PrepareImageForSW(image); return image.Pixel(pos); } -olc::Pixel olc::Draw::GetPixel(const olc::vf2d& pos) +olc::Pixel olc::Draw::GetUnsafeRawPixel(const olc::vi2d& pos) { - PrepareImageForSW(GetTarget()); - return GetTarget().Pixel(pos); + return GetUnsafeRawPixel(GetTarget(), pos); } void olc::Draw::Clear(const olc::Pixel& col) diff --git a/dev/src/draw.h b/dev/src/draw.h index cf7af215..dcdac670 100644 --- a/dev/src/draw.h +++ b/dev/src/draw.h @@ -236,11 +236,33 @@ namespace olc // Read a pixel from an image (guarantees fresh) olc::Pixel GetPixel( olc::Image& image, - const olc::vf2d& pos); + const olc::vf2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); // Read a pixel from target image (guarantees fresh) olc::Pixel GetPixel( - const olc::vf2d& pos); + const olc::vf2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from an image (guarantees fresh) + olc::Pixel GetRawPixel( + olc::Image& image, + const olc::vi2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from target image (guarantees fresh) + olc::Pixel GetRawPixel( + const olc::vi2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from a target image with no bounds checking (gurantees fresh) + olc::Pixel GetUnsafeRawPixel( + olc::Image& image, + const olc::vi2d& pos); + + // Read an untransformed pixel from target image with no bounds checking (gurantees fresh) + olc::Pixel GetUnsafeRawPixel( + const olc::vi2d& pos); // Clear entire draw target to specific colour void Clear(const olc::Pixel& col); diff --git a/dev/src/transform2d.h b/dev/src/transform2d.h index 68b92edb..f02fd43a 100644 --- a/dev/src/transform2d.h +++ b/dev/src/transform2d.h @@ -178,7 +178,7 @@ namespace olc template inline constexpr void rotate(const Q& v, const olc::v_2d& p = { 0,0 }) { - m_stackForward.push(m_stackForward.top() * (olc::m_3d::translation(-p) * olc::m_3d::rotation(v) * olc::m_3d::translation(p))); + m_stackForward.push(m_stackForward.top() * (olc::m_3d::translation(p) * olc::m_3d::rotation(v) * olc::m_3d::translation(-p))); m_stackInverse.push(m_stackForward.top().invert()); } diff --git a/examples/olcPGE3_Pixels.cpp b/examples/olcPGE3_Pixels.cpp index 25ae3d7e..34b6ade3 100644 --- a/examples/olcPGE3_Pixels.cpp +++ b/examples/olcPGE3_Pixels.cpp @@ -37,6 +37,9 @@ class Example_Pixels : public olc::PixelGameEngine // Clear screen to dark blue draw.Clear(olc::Colour::VERY_DARK_BLUE); + if (keyboard.GetKey(olc::Key::SPACE).bHeld) + draw.WorldRotate(TotalTimeElapsed() * 0.1f, { 128, 120 }); + // Draw random pixels in a box for (int y = 10; y < 108; y++) { @@ -89,6 +92,7 @@ class Example_Pixels : public olc::PixelGameEngine } } + // Successful frame return true; } diff --git a/olcPixelGameEngine3.h b/olcPixelGameEngine3.h index c2390020..5e757913 100644 --- a/olcPixelGameEngine3.h +++ b/olcPixelGameEngine3.h @@ -2155,7 +2155,7 @@ namespace olc template inline constexpr void rotate(const Q& v, const olc::v_2d& p = { 0,0 }) { - m_stackForward.push(m_stackForward.top() * (olc::m_3d::translation(-p) * olc::m_3d::rotation(v) * olc::m_3d::translation(p))); + m_stackForward.push(m_stackForward.top() * (olc::m_3d::translation(p) * olc::m_3d::rotation(v) * olc::m_3d::translation(-p))); m_stackInverse.push(m_stackForward.top().invert()); } @@ -2845,11 +2845,33 @@ namespace olc // Read a pixel from an image (guarantees fresh) olc::Pixel GetPixel( olc::Image& image, - const olc::vf2d& pos); + const olc::vf2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); // Read a pixel from target image (guarantees fresh) olc::Pixel GetPixel( - const olc::vf2d& pos); + const olc::vf2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from an image (guarantees fresh) + olc::Pixel GetRawPixel( + olc::Image& image, + const olc::vi2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from target image (guarantees fresh) + olc::Pixel GetRawPixel( + const olc::vi2d& pos, + const olc::Pixel failcol = olc::Colour::BLACK); + + // Read an untransformed pixel from a target image with no bounds checking (gurantees fresh) + olc::Pixel GetUnsafeRawPixel( + olc::Image& image, + const olc::vi2d& pos); + + // Read an untransformed pixel from target image with no bounds checking (gurantees fresh) + olc::Pixel GetUnsafeRawPixel( + const olc::vi2d& pos); // Clear entire draw target to specific colour void Clear(const olc::Pixel& col); @@ -18132,16 +18154,48 @@ void Draw::Pixel(const olc::vf2d& pos, const olc::Pixel col, const olc::Pixel ti // otherwise do nothing } -olc::Pixel olc::Draw::GetPixel(olc::Image& image, const olc::vf2d& pos) +olc::Pixel olc::Draw::GetPixel(olc::Image& image, const olc::vf2d& pos, const olc::Pixel failcol) +{ + olc::vf2d tpos = transformAffine.forwardRound(pos); + if (tpos.x >= 0 && tpos.y >= 0 && tpos.x < float(image.Size().x) && tpos.y < float(image.Size().y)) + { + PrepareImageForSW(image); + return image.Pixel(tpos); + } + else + return failcol; +} + +olc::Pixel olc::Draw::GetPixel(const olc::vf2d& pos, const olc::Pixel failcol) +{ + return GetPixel(GetTarget(), pos, failcol); +} + +olc::Pixel olc::Draw::GetRawPixel(olc::Image& image, const olc::vi2d& pos, const olc::Pixel failcol) +{ + if (pos.x >= 0 && pos.y >= 0 && pos.x < float(image.Size().x) && pos.y < float(image.Size().y)) + { + PrepareImageForSW(image); + return image.Pixel(pos); + } + else + return failcol; +} + +olc::Pixel olc::Draw::GetRawPixel(const olc::vi2d& pos, const olc::Pixel failcol) +{ + return GetRawPixel(GetTarget(), pos, failcol); +} + +olc::Pixel olc::Draw::GetUnsafeRawPixel(olc::Image& image, const olc::vi2d& pos) { PrepareImageForSW(image); return image.Pixel(pos); } -olc::Pixel olc::Draw::GetPixel(const olc::vf2d& pos) +olc::Pixel olc::Draw::GetUnsafeRawPixel(const olc::vi2d& pos) { - PrepareImageForSW(GetTarget()); - return GetTarget().Pixel(pos); + return GetUnsafeRawPixel(GetTarget(), pos); } void olc::Draw::Clear(const olc::Pixel& col)