gosu 2.0.0.pre6 → 2.0.0.pre7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.