gosu 2.0.0.pre6 → 2.0.0.pre7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c216718d8cc417f4136f1231d7a845bfab4a5308900243750d218d1ba433a6b
4
- data.tar.gz: 326fccc87ec22ee599c0536a744356423abf70e921f2e3bc247067b120a834a6
3
+ metadata.gz: de41d69b5cfd72bea1af496ef95e39cf80d89268d640548c73aeb421d9b05428
4
+ data.tar.gz: d2196d8e0a7f65e9c0d77fdfe5c56026570a807a15b4c46a7066c16bc296fcb0
5
5
  SHA512:
6
- metadata.gz: aaf8dce2376755bd906ff3598599941337544e489153ca691e68cd86bf773a0a7aeed6db2e27aedf591399d694bd3e67fa2e2e9aad62116371e8f3a51d06a00f
7
- data.tar.gz: 19f7f2dff02d74c44292218234fad7cab148f139f0e1cc04475428f1c8200812075a073cb0663d221aac769d91eb87ab6a2894c7052a94f7190a1727226495d6
6
+ metadata.gz: c809f58dd0e31ec02bd3c596e2dab1de6795d70eee53aa5226389815f8b37089289055222ed3f1a4eed3a1f2e4952e452a42042a14385e97737007adbf1dff78
7
+ data.tar.gz: 744c254d6ad35c6ceb9acbda0ac26d1d6f4531df389b38c13afea1775bf271be65941076fdc40d707c55a1c1a8a6ac3ae6ed95231c0a7de5bd11dc041bc0cce8
@@ -55,6 +55,8 @@ assert can have unique static variables associated with it.
55
55
  #define SDL_TriggerBreakpoint() __builtin_debugtrap()
56
56
  #elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
57
57
  #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
58
+ #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv)
59
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" )
58
60
  #elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
59
61
  #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
60
62
  #elif defined(__APPLE__) && defined(__arm__)
@@ -1474,6 +1474,17 @@ extern "C" {
1474
1474
  */
1475
1475
  #define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
1476
1476
 
1477
+ /**
1478
+ * \brief A variable controlling whether the Metal render driver select low power device over default one
1479
+ *
1480
+ * This variable can be set to the following values:
1481
+ * "0" - Use the prefered OS device
1482
+ * "1" - Select a low power one
1483
+ *
1484
+ * By default the prefered OS device is used.
1485
+ */
1486
+ #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
1487
+
1477
1488
  /**
1478
1489
  * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
1479
1490
  *
@@ -1890,7 +1890,7 @@ extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer);
1890
1890
  * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give
1891
1891
  * SDL a drawable to render to, which might happen if the window is
1892
1892
  * hidden/minimized/offscreen. This doesn't apply to command encoders for
1893
- * render targets, just the window's backbacker. Check your return values!
1893
+ * render targets, just the window's backbuffer. Check your return values!
1894
1894
  *
1895
1895
  * \param renderer The renderer to query
1896
1896
  * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the
@@ -1,7 +1,7 @@
1
1
  /* Generated by updaterev.sh, do not edit */
2
2
  #ifdef SDL_VENDOR_INFO
3
- #define SDL_REVISION "SDL-release-2.28.2-0-g031912c4b (" SDL_VENDOR_INFO ")"
3
+ #define SDL_REVISION "SDL-release-2.28.3-0-g8a5ba43d0 (" SDL_VENDOR_INFO ")"
4
4
  #else
5
- #define SDL_REVISION "SDL-release-2.28.2-0-g031912c4b"
5
+ #define SDL_REVISION "SDL-release-2.28.3-0-g8a5ba43d0"
6
6
  #endif
7
7
  #define SDL_REVISION_NUMBER 0
@@ -59,7 +59,7 @@ typedef struct SDL_version
59
59
  */
60
60
  #define SDL_MAJOR_VERSION 2
61
61
  #define SDL_MINOR_VERSION 28
62
- #define SDL_PATCHLEVEL 2
62
+ #define SDL_PATCHLEVEL 3
63
63
 
64
64
  /**
65
65
  * Macro to determine SDL version program was compiled against.
Binary file
Binary file
@@ -213,6 +213,7 @@ Gosu_IF_TILEABLE_TOP
213
213
  Gosu_Image_create
214
214
  Gosu_Image_create_from_blob
215
215
  Gosu_Image_create_from_markup
216
+ Gosu_Image_create_from_rect
216
217
  Gosu_Image_create_from_subimage
217
218
  Gosu_Image_create_from_text
218
219
  Gosu_Image_create_from_tiles
@@ -26,7 +26,7 @@ auto Gosu_translate_exceptions(Functor functor)
26
26
  }
27
27
  }
28
28
 
29
- // C-compatible wrapper structs for Gosu classes
29
+ // C-compatible wrapper structs for Gosu classes. (No inheritance because of missing virtual dtors.)
30
30
 
31
31
  struct Gosu_Channel
32
32
  {
@@ -48,7 +48,7 @@ struct Gosu_Sample
48
48
  Gosu::Sample sample;
49
49
  };
50
50
 
51
- // Use inheritance where composition is not feasible
51
+ // Use inheritance where composition is not feasible (because we want to compare pointers).
52
52
 
53
53
  struct Gosu_Song : Gosu::Song
54
54
  {
data/ffi/Gosu_Image.cpp CHANGED
@@ -2,9 +2,18 @@
2
2
  #include <cstring> // for std::memcpy
3
3
 
4
4
  GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags)
5
+ {
6
+ return Gosu_translate_exceptions([=] { //
7
+ return new Gosu_Image { Gosu::Image(filename, image_flags) };
8
+ });
9
+ }
10
+
11
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
12
+ int x, int y, int width, int height,
13
+ unsigned image_flags)
5
14
  {
6
15
  return Gosu_translate_exceptions([=] {
7
- return new Gosu_Image{Gosu::Image{filename, image_flags}};
16
+ return new Gosu_Image { Gosu::Image(filename, { x, y, width, height }, image_flags) };
8
17
  });
9
18
  }
10
19
 
@@ -32,32 +41,35 @@ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_text(const char* text, const cha
32
41
  });
33
42
  }
34
43
 
35
- GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, int byte_count, int columns,
36
- int rows, unsigned image_flags)
44
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
45
+ int columns, int rows, //
46
+ int x, int y, int width, int height,
47
+ unsigned image_flags)
37
48
  {
38
49
  return Gosu_translate_exceptions([=] {
39
- std::size_t size = columns * rows * 4;
40
- Gosu::Bitmap bitmap{columns, rows};
50
+ const int pixels = columns * rows * 4;
51
+ Gosu::Bitmap bitmap;
41
52
 
42
- if (byte_count == size) {
53
+ if (byte_count == pixels) {
43
54
  // 32 bit per pixel, assume R8G8B8A8
44
- std::memcpy(bitmap.data(), blob, size);
55
+ bitmap = Gosu::Bitmap(columns, rows, Gosu::Buffer(blob, byte_count, nullptr));
45
56
  }
46
- else if (byte_count == size * sizeof(float)) {
47
- // 128 bit per channel, assume float/float/float/float - for Texplay compatibility.
57
+ else if (byte_count == pixels * 4UL * sizeof(float)) {
58
+ bitmap.resize(columns, rows);
59
+ // 128 bit per channel, assume float/float/float/float RGBA - for Texplay compatibility.
48
60
  const float* in = static_cast<const float*>(blob);
49
61
  Gosu::Color::Channel* out = reinterpret_cast<Gosu::Color::Channel*>(bitmap.data());
50
- for (std::size_t i = 0; i < size; ++i) {
62
+ for (std::size_t i = 0; i < pixels; ++i) {
51
63
  out[i] = static_cast<Gosu::Color::Channel>(in[i] * 255);
52
64
  }
53
65
  }
54
66
  else {
55
- throw std::invalid_argument{"Invalid byte_count " + std::to_string(byte_count) +
56
- "for image of size " + std::to_string(columns) + "x" +
57
- std::to_string(rows)};
67
+ throw std::invalid_argument("Invalid byte_count " + std::to_string(byte_count)
68
+ + " for image of size " + std::to_string(columns) + "x"
69
+ + std::to_string(rows));
58
70
  }
59
71
 
60
- return new Gosu_Image{Gosu::Image{bitmap, image_flags}};
72
+ return new Gosu_Image { Gosu::Image(bitmap, { x, y, width, height }, image_flags) };
61
73
  });
62
74
  }
63
75
 
data/ffi/Gosu_Image.h CHANGED
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include "Gosu_FFI.h"
4
+ #include <stddef.h> // for size_t
4
5
  #include <stdint.h>
5
6
 
6
7
  typedef struct Gosu_Image Gosu_Image;
@@ -13,8 +14,13 @@ typedef struct Gosu_GLTexInfo
13
14
 
14
15
  // Constructor
15
16
  GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags);
16
- GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, int byte_count, int width,
17
- int height, unsigned image_flags);
17
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
18
+ int x, int y, int width, int height,
19
+ unsigned image_flags);
20
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
21
+ int columns, int rows, //
22
+ int x, int y, int width, int height,
23
+ unsigned image_flags);
18
24
  GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_markup(const char* markup, const char* font,
19
25
  double font_height, int width,
20
26
  double spacing, unsigned align,
@@ -24,7 +24,7 @@ namespace Gosu
24
24
  /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
25
25
  explicit Image(const std::string& filename, unsigned image_flags = IF_SMOOTH);
26
26
 
27
- //! Loads a portion of the the image at the given filename..
27
+ /// Loads a portion of the the image at the given filename..
28
28
  ///
29
29
  /// A color key of #ff00ff is automatically applied to BMP image files.
30
30
  /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
data/lib/SDL2.dll CHANGED
Binary file
data/lib/gosu/ffi.rb CHANGED
@@ -134,11 +134,12 @@ module GosuFFI
134
134
  attach_function :Gosu_Font_set_image, [:pointer, :string, :uint32, :pointer], :void
135
135
 
136
136
  attach_function :Gosu_Image_create, [:string, :uint32], :pointer
137
+ attach_function :Gosu_Image_create_from_rect, [:string, :int, :int, :int, :int, :uint32], :pointer
137
138
  attach_function :Gosu_Image_destroy, [:pointer], :void
138
139
 
139
140
  attach_function :Gosu_Image_create_from_markup, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
140
141
  attach_function :Gosu_Image_create_from_text, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
141
- attach_function :Gosu_Image_create_from_blob, [:pointer, :ulong, :int, :int, :uint32], :pointer
142
+ attach_function :Gosu_Image_create_from_blob, [:pointer, :size_t, :int, :int, :int, :int, :int, :int, :uint32], :pointer
142
143
  attach_function :Gosu_Image_create_from_subimage, [:pointer, :int, :int, :int, :int], :pointer
143
144
  attach_function :Gosu_Image_create_from_tiles, [:string, :int, :int, :_callback_with_image, :pointer, :uint32], :void
144
145
  attach_function :Gosu_Image_create_tiles_from_image, [:pointer, :int, :int, :_callback_with_image, :pointer, :uint32], :void
data/lib/gosu/image.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  module Gosu
2
2
  class Image
3
- BlobHelper = Struct.new(:columns, :rows, :to_blob)
4
-
5
3
  def self.from_blob(width, height, rgba = "\0\0\0\0" * (width * height), retro: false, tileable: false)
6
- self.new(BlobHelper.new(width, height, rgba), retro: retro, tileable: tileable)
4
+ @struct ||= Struct.new(:columns, :rows, :to_blob)
5
+ self.new(@struct.new(width, height, rgba), retro: retro, tileable: tileable)
7
6
  end
8
7
 
9
8
  def self.from_text(markup, line_height, font: Gosu.default_font_name, width: -1, spacing: 0, align: :left,
@@ -48,25 +47,38 @@ module Gosu
48
47
  return images
49
48
  end
50
49
 
51
- def initialize(object, retro: false, tileable: false)
50
+ def initialize(object, retro: false, tileable: false, rect: nil)
51
+ if rect and rect.size != 4
52
+ raise ArgumentError, "Expected 4-element array as rect"
53
+ end
54
+
55
+ flags = GosuFFI.image_flags(retro: retro, tileable: tileable)
56
+
52
57
  if object.is_a? String
53
- __image = GosuFFI.Gosu_Image_create(object, GosuFFI.image_flags(retro: retro, tileable: tileable))
58
+ if rect
59
+ __image = GosuFFI.Gosu_Image_create_from_rect(object, *rect, flags)
60
+ else
61
+ __image = GosuFFI.Gosu_Image_create(object, flags)
62
+ end
54
63
  GosuFFI.check_last_error
55
64
  elsif object.is_a?(FFI::Pointer)
56
65
  __image = object
57
- elsif object.respond_to?(:to_blob) &&
58
- object.respond_to?(:columns) &&
66
+ elsif object.respond_to?(:to_blob) and
67
+ object.respond_to?(:columns) and
59
68
  object.respond_to?(:rows)
60
- blob_bytes = object.to_blob { self.format = "RGBA"; self.depth = 8 }.bytes
61
- FFI::MemoryPointer.new(:uchar, blob_bytes.size) do |blob|
62
- blob.write_array_of_type(:uchar, :put_uchar, blob_bytes)
63
- __image = GosuFFI.Gosu_Image_create_from_blob(blob, blob_bytes.size, object.columns, object.rows, GosuFFI.image_flags(retro: retro, tileable: tileable))
64
- GosuFFI.check_last_error
65
- end
69
+
70
+ blob = object.to_blob { self.format = "RGBA"; self.depth = 8 }
66
71
 
67
- raise "Failed to load image from blob" if __image.null?
72
+ # This creates a copy of the Ruby string data, which shouldn't be necessary with CRuby.
73
+ ptr = FFI::MemoryPointer.from_string(blob)
74
+ rect ||= [0, 0, object.columns, object.rows]
75
+ # Do not consider the terminating null byte part of the ptr length.
76
+ __image = GosuFFI.Gosu_Image_create_from_blob(ptr, ptr.size - 1, object.columns, object.rows, *rect, flags)
77
+ ptr.free
78
+
79
+ GosuFFI.check_last_error
68
80
  else
69
- raise ArgumentError
81
+ raise ArgumentError, "Expected String or RMagick::Image (or a type compatible with it)"
70
82
  end
71
83
 
72
84
  @managed_pointer = FFI::AutoPointer.new(__image, GosuFFI.method(:Gosu_Image_destroy))
@@ -112,17 +124,17 @@ module Gosu
112
124
  end
113
125
 
114
126
  def subimage(left, top, width, height)
115
- __pointer = GosuFFI.Gosu_Image_create_from_subimage(__pointer, left, top, width, height)
127
+ __subimage = GosuFFI.Gosu_Image_create_from_subimage(__pointer, left, top, width, height)
116
128
  GosuFFI.check_last_error
117
- Gosu::Image.new(__pointer)
129
+ Gosu::Image.new(__subimage)
118
130
  end
119
131
 
120
132
  def insert(image, x, y)
121
133
  image_ = nil
122
134
  if image.is_a?(Gosu::Image)
123
135
  image_ = image.__pointer
124
- elsif image.respond_to?(:to_blob) &&
125
- image.respond_to?(:rows) &&
136
+ elsif image.respond_to?(:to_blob) and
137
+ image.respond_to?(:rows) and
126
138
  image.respond_to?(:columns)
127
139
  image_ = Gosu::Image.new(image).__pointer
128
140
  else
data/lib64/SDL2.dll CHANGED
Binary file
data/src/BinPacker.cpp CHANGED
@@ -136,7 +136,7 @@ void Gosu::BinPacker::merge_neighbors(int index)
136
136
  // ┃ ┣━━┻━┫
137
137
  // ┗━┻━━━━┛
138
138
  // In this case, the texture gets stuck in this fragmented state. We assume that this is not an
139
- // issue in practice, just like memory
139
+ // issue in practice, just like RAM fragmentation has never been problematic for us.
140
140
 
141
141
  // Merge any of the other rectangles in the list into the one with the given index if they share
142
142
  // any of their four sides.
@@ -0,0 +1,38 @@
1
+ #include "ClipRectStack.hpp"
2
+ #include <stdexcept>
3
+
4
+ void Gosu::ClipRectStack::clear()
5
+ {
6
+ m_stack.clear();
7
+ m_effective_rect = std::nullopt;
8
+ }
9
+
10
+ void Gosu::ClipRectStack::push(const Rect& rect)
11
+ {
12
+ m_stack.push_back(rect);
13
+ if (m_effective_rect) {
14
+ m_effective_rect->clip_to(rect);
15
+ }
16
+ else {
17
+ m_effective_rect = rect;
18
+ }
19
+ }
20
+
21
+ void Gosu::ClipRectStack::pop()
22
+ {
23
+ if (m_stack.empty()) {
24
+ throw std::logic_error("ClipRectStack is empty");
25
+ }
26
+ m_stack.pop_back();
27
+
28
+ // The clip rect is the intersection of all active clip rects (if any).
29
+ m_effective_rect = std::nullopt;
30
+ for (const auto& rect : m_stack) {
31
+ if (m_effective_rect) {
32
+ m_effective_rect->clip_to(rect);
33
+ }
34
+ else {
35
+ m_effective_rect = rect;
36
+ }
37
+ }
38
+ }
@@ -1,90 +1,24 @@
1
1
  #pragma once
2
2
 
3
+ #include <Gosu/Utility.hpp>
3
4
  #include "GraphicsImpl.hpp"
4
- #include <cassert>
5
+ #include <limits>
6
+ #include <optional>
7
+ #include <stdexcept>
5
8
  #include <vector>
6
9
 
7
- class Gosu::ClipRectStack
10
+ namespace Gosu
8
11
  {
9
- std::vector<ClipRect> stack;
10
- bool has_effective_rect; // is effective_rect valid?
11
- ClipRect effective_rect;
12
-
13
- void update_effective_rect()
12
+ class ClipRectStack
14
13
  {
15
- // Nothing to do, no clipping in place.
16
- if (stack.empty()) {
17
- has_effective_rect = false;
18
- return;
19
- }
20
-
21
- ClipRect result = { 0.0, 0.0, 1e10, 1e10 };
22
- for (std::size_t i = 0, end = stack.size(); i < end; ++i) {
23
- const ClipRect& rect = stack[i];
24
- int result_right = std::min(result.x + result.width, rect.x + rect.width);
25
- int result_bottom = std::min(result.y + result.height, rect.y + rect.height);
26
- result.x = std::max(result.x, rect.x);
27
- result.y = std::max(result.y, rect.y);
28
-
29
- if (result.x >= result_right || result.y >= result_bottom) {
30
- // We have clipped the world away!
31
- has_effective_rect = false;
32
- return;
33
- }
34
-
35
- result.width = result_right - result.x;
36
- result.height = result_bottom - result.y;
37
- }
38
-
39
- // On the iPhone, we may have to multiply everything by 2 for Retina displays.
40
- // TODO: Doesn't this affect Retina Macs as well?
41
- // TODO: This should be handled by a global transform.
42
- int fac = clip_rect_base_factor();
43
- result.x *= fac;
44
- result.y *= fac;
45
- result.width *= fac;
46
- result.height *= fac;
47
-
48
- // Normal clipping.
49
- effective_rect = result;
50
- has_effective_rect = true;
51
- }
52
-
53
- public:
54
- ClipRectStack()
55
- : has_effective_rect(false)
56
- {
57
- }
58
-
59
- void clear()
60
- {
61
- stack.clear();
62
- has_effective_rect = false;
63
- }
64
-
65
- void begin_clipping(double x, double y, double width, double height)
66
- {
67
- ClipRect rect = { x, y, width, height };
68
- stack.push_back(rect);
69
- update_effective_rect();
70
- }
71
-
72
- void end_clipping()
73
- {
74
- assert (!stack.empty());
75
- stack.pop_back();
76
- update_effective_rect();
77
- }
78
-
79
- const ClipRect* maybe_effective_rect() const
80
- {
81
- return has_effective_rect ? &effective_rect : 0;
82
- }
83
-
84
- bool clipped_world_away() const
85
- {
86
- // When we have no effective rect but the stack is not empty, we have clipped
87
- // the whole world away and don't need to render things.
88
- return !has_effective_rect && !stack.empty();
89
- }
90
- };
14
+ std::vector<Rect> m_stack;
15
+ std::optional<Rect> m_effective_rect;
16
+
17
+ public:
18
+ void clear();
19
+ void push(const Rect& rect);
20
+ void pop();
21
+
22
+ const std::optional<Rect>& effective_rect() const { return m_effective_rect; }
23
+ };
24
+ }
data/src/DrawOp.hpp CHANGED
@@ -168,10 +168,5 @@ namespace Gosu
168
168
 
169
169
  vas.back().vertices.insert(vas.back().vertices.end(), result, result + 4);
170
170
  }
171
-
172
- bool operator<(const DrawOp& other) const
173
- {
174
- return z < other.z;
175
- }
176
171
  };
177
172
  }
data/src/DrawOpQueue.hpp CHANGED
@@ -9,6 +9,7 @@
9
9
  #include <cmath>
10
10
  #include <functional>
11
11
  #include <map>
12
+ #include <utility>
12
13
  #include <vector>
13
14
 
14
15
  class Gosu::DrawOpQueue
@@ -22,7 +23,7 @@ class Gosu::DrawOpQueue
22
23
  std::vector<std::function<void ()>> gl_blocks;
23
24
 
24
25
  public:
25
- DrawOpQueue(QueueMode mode)
26
+ explicit DrawOpQueue(QueueMode mode)
26
27
  : queue_mode(mode)
27
28
  {
28
29
  }
@@ -34,39 +35,31 @@ public:
34
35
 
35
36
  void schedule_draw_op(DrawOp op)
36
37
  {
37
- if (clip_rect_stack.clipped_world_away()) return;
38
-
39
- #ifdef GOSU_IS_OPENGLES
38
+ #ifdef GOSU_IS_OPENGLES
40
39
  // No triangles, no lines supported
41
- assert (op.vertices_or_block_index == 4);
42
- #endif
40
+ assert(op.vertices_or_block_index == 4);
41
+ #endif
43
42
 
44
43
  op.render_state.transform = &transform_stack.current();
45
- if (const ClipRect* cr = clip_rect_stack.maybe_effective_rect()) {
46
- op.render_state.clip_rect = *cr;
47
- }
44
+ op.render_state.clip_rect = clip_rect_stack.effective_rect();
48
45
  ops.push_back(op);
49
46
  }
50
47
 
51
48
  void gl(std::function<void ()> gl_block, ZPos z)
52
49
  {
53
- // TODO: Document this case: Clipped-away GL blocks are *not* being run.
54
- if (clip_rect_stack.clipped_world_away()) return;
55
-
56
50
  int complement_of_block_index = ~(int)gl_blocks.size();
57
- gl_blocks.push_back(gl_block);
51
+ gl_blocks.push_back(std::move(gl_block));
58
52
 
59
53
  DrawOp op;
60
54
  op.vertices_or_block_index = complement_of_block_index;
61
55
  op.render_state.transform = &transform_stack.current();
62
- if (const ClipRect* cr = clip_rect_stack.maybe_effective_rect()) {
63
- op.render_state.clip_rect = *cr;
64
- }
56
+ op.render_state.clip_rect = clip_rect_stack.effective_rect();
65
57
  op.z = z;
66
58
  ops.push_back(op);
67
59
  }
68
60
 
69
- void begin_clipping(double x, double y, double width, double height, double screen_height)
61
+ void begin_clipping(double x, double y, double width, double height,
62
+ std::optional<int> viewport_height)
70
63
  {
71
64
  if (mode() == QM_RECORD_MACRO) {
72
65
  throw std::logic_error("Clipping is not allowed while creating a macro");
@@ -80,21 +73,21 @@ public:
80
73
  transform_stack.current().apply(left, top);
81
74
  transform_stack.current().apply(right, bottom);
82
75
 
83
- double phys_x = std::min(left, right);
84
- double phys_y = std::min(top, bottom);
85
- double phys_width = std::abs(left - right);
86
- double phys_height = std::abs(top - bottom);
87
-
76
+ Rect clip_rect {
77
+ .x = static_cast<int>(std::min(left, right)),
78
+ .y = static_cast<int>(std::min(top, bottom)),
79
+ .width = static_cast<int>(std::abs(left - right)),
80
+ .height = static_cast<int>(std::abs(top - bottom)),
81
+ };
88
82
  // Adjust for OpenGL having the wrong idea of where y=0 is.
89
- phys_y = screen_height - phys_y - phys_height;
83
+ if (viewport_height && mode() == QM_RENDER_TO_SCREEN) {
84
+ clip_rect.y = *viewport_height - clip_rect.y - clip_rect.height;
85
+ }
90
86
 
91
- clip_rect_stack.begin_clipping(phys_x, phys_y, phys_width, phys_height);
87
+ clip_rect_stack.push(clip_rect);
92
88
  }
93
89
 
94
- void end_clipping()
95
- {
96
- clip_rect_stack.end_clipping();
97
- }
90
+ void end_clipping() { clip_rect_stack.pop(); }
98
91
 
99
92
  void set_base_transform(const Transform& base_transform)
100
93
  {
@@ -118,7 +111,8 @@ public:
118
111
  }
119
112
 
120
113
  // Apply Z-Ordering.
121
- std::stable_sort(ops.begin(), ops.end());
114
+ std::stable_sort(ops.begin(), ops.end(),
115
+ [](const DrawOp& lhs, const DrawOp& rhs) { return lhs.z < rhs.z; });
122
116
 
123
117
  RenderStateManager manager;
124
118
 
@@ -156,7 +150,7 @@ public:
156
150
  throw std::logic_error("Custom OpenGL code cannot be recorded as a macro");
157
151
  }
158
152
 
159
- std::stable_sort(ops.begin(), ops.end());
153
+ std::stable_sort(ops.begin(), ops.end(), [](const DrawOp& lhs, const DrawOp& rhs) { return lhs.z < rhs.z; });
160
154
  for (const auto& op : ops) {
161
155
  op.compile_to(vas);
162
156
  }
data/src/GosuGLView.cpp CHANGED
@@ -28,12 +28,6 @@ namespace Gosu
28
28
  {
29
29
  // Don't bother unsetting anything.
30
30
  }
31
-
32
- int clip_rect_base_factor()
33
- {
34
- static int result = [UIScreen mainScreen].scale;
35
- return result;
36
- }
37
31
  }
38
32
 
39
33
  @implementation GosuGLView
@@ -97,7 +91,7 @@ namespace Gosu
97
91
  [EAGLContext setCurrentContext:_context];
98
92
  [self destroyFramebuffer];
99
93
  [self createFramebuffer];
100
- self.contentScaleFactor = Gosu::clip_rect_base_factor();
94
+ self.contentScaleFactor = [UIScreen mainScreen].scale;
101
95
  }
102
96
 
103
97
  - (BOOL)createFramebuffer
data/src/Graphics.cpp CHANGED
@@ -247,17 +247,20 @@ void Gosu::gl(Gosu::ZPos z, const std::function<void()>& f)
247
247
  #endif
248
248
  }
249
249
 
250
- void Gosu::clip_to(double x, double y, double width, double height,
251
- const std::function<void()>& f)
250
+ void Gosu::clip_to(double x, double y, double width, double height, const std::function<void()>& f)
252
251
  {
253
- double screen_height = current_viewport().m_impl->phys_height;
254
- current_queue().begin_clipping(x, y, width, height, screen_height);
252
+ std::optional<int> viewport_height;
253
+ if (current_viewport_pointer) {
254
+ viewport_height = current_viewport_pointer->m_impl->phys_height;
255
+ }
256
+
257
+ current_queue().begin_clipping(x, y, width, height, viewport_height);
255
258
  f();
256
259
  current_queue().end_clipping();
257
260
  }
258
261
 
259
262
  Gosu::Image Gosu::render(int width, int height, const std::function<void()>& f,
260
- unsigned image_flags)
263
+ unsigned image_flags)
261
264
  {
262
265
  const OpenGLContext current_context;
263
266
 
data/src/GraphicsImpl.hpp CHANGED
@@ -13,23 +13,6 @@ namespace Gosu
13
13
  struct RenderState;
14
14
  class RenderStateManager;
15
15
 
16
- const unsigned NO_CLIPPING = 0xffffffff;
17
-
18
- // In various places in Gosu, width==NO_CLIPPING by convention means
19
- // that no clipping should happen.
20
- struct ClipRect
21
- {
22
- double x, y, width, height;
23
-
24
- bool operator==(const ClipRect& other) const
25
- {
26
- // No clipping
27
- return (width == NO_CLIPPING && other.width == NO_CLIPPING) ||
28
- // Clipping, but same
29
- (x == other.x && y == other.y && width == other.width && height == other.height);
30
- }
31
- };
32
-
33
16
  enum QueueMode
34
17
  {
35
18
  QM_RENDER_TO_SCREEN,
@@ -71,12 +54,6 @@ namespace Gosu
71
54
 
72
55
  void schedule_draw_op(const DrawOp& op);
73
56
 
74
- #ifdef GOSU_IS_IPHONE
75
- int clip_rect_base_factor();
76
- #else
77
- inline int clip_rect_base_factor() { return 1; }
78
- #endif
79
-
80
57
  void register_frame();
81
58
 
82
59
  inline std::string escape_markup(const std::string& text) {
data/src/RenderState.hpp CHANGED
@@ -1,9 +1,11 @@
1
1
  #pragma once
2
2
 
3
3
  #include <Gosu/Transform.hpp>
4
+ #include "ClipRectStack.hpp"
4
5
  #include "GraphicsImpl.hpp"
5
6
  #include "OpenGLContext.hpp"
6
7
  #include "Texture.hpp"
8
+ #include <optional>
7
9
 
8
10
  // Properties that potentially need to be changed between each draw operation.
9
11
  // This does not include the color or vertex data of the actual quads.
@@ -11,13 +13,12 @@ struct Gosu::RenderState
11
13
  {
12
14
  std::shared_ptr<Texture> texture;
13
15
  const Transform* transform;
14
- ClipRect clip_rect;
16
+ std::optional<Rect> clip_rect;
15
17
  BlendMode mode;
16
18
 
17
19
  RenderState()
18
20
  : transform(0), mode(BM_DEFAULT)
19
21
  {
20
- clip_rect.width = NO_CLIPPING;
21
22
  }
22
23
 
23
24
  bool operator==(const RenderState& rhs) const
@@ -54,12 +55,12 @@ struct Gosu::RenderState
54
55
 
55
56
  void apply_clip_rect() const
56
57
  {
57
- if (clip_rect.width == NO_CLIPPING) {
58
- glDisable(GL_SCISSOR_TEST);
58
+ if (clip_rect.has_value()) {
59
+ glEnable(GL_SCISSOR_TEST);
60
+ glScissor(clip_rect->x, clip_rect->y, clip_rect->width, clip_rect->height);
59
61
  }
60
62
  else {
61
- glEnable(GL_SCISSOR_TEST);
62
- glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
63
+ glDisable(GL_SCISSOR_TEST);
63
64
  }
64
65
  }
65
66
 
@@ -76,12 +77,8 @@ struct Gosu::RenderState
76
77
 
77
78
  // Manages the OpenGL rendering state. It caches the current state, only forwarding the
78
79
  // changes to OpenGL if the new state is really different.
79
- class Gosu::RenderStateManager : private Gosu::RenderState
80
+ class Gosu::RenderStateManager : private Gosu::RenderState, private Gosu::Noncopyable
80
81
  {
81
- // Not copyable
82
- RenderStateManager(const RenderStateManager&);
83
- RenderStateManager& operator=(const RenderStateManager&);
84
-
85
82
  void apply_transform() const
86
83
  {
87
84
  glMatrixMode(GL_MODELVIEW);
@@ -110,9 +107,7 @@ public:
110
107
 
111
108
  ~RenderStateManager()
112
109
  {
113
- ClipRect no_clipping;
114
- no_clipping.width = NO_CLIPPING;
115
- set_clip_rect(no_clipping);
110
+ set_clip_rect(std::nullopt);
116
111
  set_texture(std::shared_ptr<Texture>());
117
112
  // Return to previous MV matrix
118
113
  glMatrixMode(GL_MODELVIEW);
@@ -127,9 +122,11 @@ public:
127
122
  set_alpha_mode(rs.mode);
128
123
  }
129
124
 
130
- void set_texture(std::shared_ptr<Texture> new_texture)
125
+ void set_texture(const std::shared_ptr<Texture>& new_texture)
131
126
  {
132
- if (new_texture == texture) return;
127
+ if (new_texture == texture) {
128
+ return;
129
+ }
133
130
 
134
131
  if (new_texture) {
135
132
  if (!texture) {
@@ -146,39 +143,29 @@ public:
146
143
 
147
144
  void set_transform(const Transform* new_transform)
148
145
  {
149
- if (new_transform == transform) return;
146
+ if (new_transform == transform) {
147
+ return;
148
+ }
150
149
 
151
150
  transform = new_transform;
152
151
  apply_transform();
153
152
  }
154
153
 
155
- void set_clip_rect(const ClipRect& new_clip_rect)
154
+ void set_clip_rect(const std::optional<Rect>& new_clip_rect)
156
155
  {
157
- if (new_clip_rect.width == NO_CLIPPING) {
158
- // Disable clipping
159
- if (clip_rect.width != NO_CLIPPING) {
160
- glDisable(GL_SCISSOR_TEST);
161
- clip_rect.width = NO_CLIPPING;
162
- }
163
- }
164
- else {
165
- // Enable clipping if off
166
- if (clip_rect.width == NO_CLIPPING) {
167
- glEnable(GL_SCISSOR_TEST);
168
- clip_rect = new_clip_rect;
169
- glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
170
- }
171
- // Adjust clipping if necessary
172
- else if (!(clip_rect == new_clip_rect)) {
173
- clip_rect = new_clip_rect;
174
- glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
175
- }
156
+ if (clip_rect == new_clip_rect) {
157
+ return;
176
158
  }
159
+
160
+ clip_rect = new_clip_rect;
161
+ apply_clip_rect();
177
162
  }
178
163
 
179
164
  void set_alpha_mode(BlendMode new_mode)
180
165
  {
181
- if (new_mode == mode) return;
166
+ if (new_mode == mode) {
167
+ return;
168
+ }
182
169
 
183
170
  mode = new_mode;
184
171
  apply_alpha_mode();
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gosu
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre6
4
+ version: 2.0.0.pre7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Raschke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-02 00:00:00.000000000 Z
11
+ date: 2023-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -258,6 +258,7 @@ files:
258
258
  - src/BitmapIO.cpp
259
259
  - src/Buffer.cpp
260
260
  - src/Channel.cpp
261
+ - src/ClipRectStack.cpp
261
262
  - src/ClipRectStack.hpp
262
263
  - src/Color.cpp
263
264
  - src/Directories.cpp
@@ -336,7 +337,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
336
337
  - !ruby/object:Gem::Version
337
338
  version: 1.3.1
338
339
  requirements: []
339
- rubygems_version: 3.4.3
340
+ rubygems_version: 3.4.10
340
341
  signing_key:
341
342
  specification_version: 4
342
343
  summary: 2D game development library.