aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-01-31 10:36:03 +0100
committerLoïc Hoguin <[email protected]>2018-01-31 10:36:40 +0100
commit245944afa32d73628a9025efe33372290fa4bac3 (patch)
tree6afdc170fa41e4c2b25d573e8aaf67bf0184bc6e
parent889ac5dc3480e4ae7fb318e6cb114767ba4e160a (diff)
downloadesdl2-245944afa32d73628a9025efe33372290fa4bac3.tar.gz
esdl2-245944afa32d73628a9025efe33372290fa4bac3.tar.bz2
esdl2-245944afa32d73628a9025efe33372290fa4bac3.zip
Add all SDL_rect functions
-rw-r--r--README.asciidoc2
-rw-r--r--c_src/esdl2.h6
-rw-r--r--c_src/sdl_rect.c101
-rw-r--r--src/esdl2.erl24
-rw-r--r--src/sdl_rect.erl54
5 files changed, 186 insertions, 1 deletions
diff --git a/README.asciidoc b/README.asciidoc
index e3e7608..510407c 100644
--- a/README.asciidoc
+++ b/README.asciidoc
@@ -17,6 +17,7 @@ corresponding to the public headers.
* 'SDL_mouse.h'
* 'SDL_platform.h'
* 'SDL_power.h'
+* 'SDL_rect.h'
* 'SDL_scancode.h'
== Partially implemented
@@ -62,7 +63,6 @@ corresponding to the public headers.
** `SDL_RegisterEvents`
* 'SDL_hints.h': We only have a proof of concept callback system.
* 'SDL_pixels.h': Only the pixel format enum and conversion function is defined.
-* 'SDL_rect.h': Everything is missing except the map to point/rect conversion functions.
* 'SDL_render.h': The following elements are missing:
** `SDL_TextureAccess` enum
** `SDL_TextureModulate` enum
diff --git a/c_src/esdl2.h b/c_src/esdl2.h
index 2cee676..d4aa683 100644
--- a/c_src/esdl2.h
+++ b/c_src/esdl2.h
@@ -362,6 +362,12 @@
F(get_platform, 0) \
/* sdl_power */ \
F(get_power_info, 0) \
+ /* sdl_rect */ \
+ F(enclose_points, 2) \
+ F(has_intersection, 2) \
+ F(intersect_rect, 2) \
+ F(intersect_rect_and_line, 5) \
+ F(union_rect, 2) \
/* sdl_renderer */ \
F(create_renderer, 3) \
F(get_num_render_drivers, 0) \
diff --git a/c_src/sdl_rect.c b/c_src/sdl_rect.c
index 472cf01..ed42fdd 100644
--- a/c_src/sdl_rect.c
+++ b/c_src/sdl_rect.c
@@ -87,3 +87,104 @@ ERL_NIF_TERM rect_to_map(ErlNifEnv* env, const SDL_Rect* rect)
return map;
}
+
+// enclose_points
+
+NIF_FUNCTION(enclose_points)
+{
+ SDL_Point* points = NULL;
+ SDL_Rect clip, result;
+ SDL_bool b;
+ ERL_NIF_TERM list, head;
+ unsigned int count;
+ int i = 0;
+
+ BADARG_IF(!enif_get_list_length(env, argv[0], &count));
+ BADARG_IF(!map_to_rect(env, argv[1], &clip));
+
+ points = (SDL_Point*)enif_alloc(count * sizeof(SDL_Point));
+
+ list = argv[0];
+ while (enif_get_list_cell(env, list, &head, &list)) {
+ if (!map_to_point(env, head, &(points[i++]))) {
+ enif_free(points);
+ return enif_make_badarg(env);
+ }
+ }
+
+ b = SDL_EnclosePoints(points, count, &clip, &result);
+
+ enif_free(points);
+
+ if (!b)
+ return atom_false;
+
+ return rect_to_map(env, &result);
+}
+
+// has_intersection
+
+NIF_FUNCTION(has_intersection)
+{
+ SDL_Rect a, b;
+
+ BADARG_IF(!map_to_rect(env, argv[0], &a));
+ BADARG_IF(!map_to_rect(env, argv[1], &b));
+
+ if (SDL_HasIntersection(&a, &b))
+ return atom_true;
+
+ return atom_false;
+}
+
+// intersect_rect
+
+NIF_FUNCTION(intersect_rect)
+{
+ SDL_Rect a, b, result;
+
+ BADARG_IF(!map_to_rect(env, argv[0], &a));
+ BADARG_IF(!map_to_rect(env, argv[1], &b));
+
+ if (!SDL_IntersectRect(&a, &b, &result))
+ return atom_false;
+
+ return rect_to_map(env, &result);
+}
+
+// intersect_rect_and_line
+
+NIF_FUNCTION(intersect_rect_and_line)
+{
+ SDL_Rect rect;
+ int x1, y1, x2, y2;
+
+ BADARG_IF(!map_to_rect(env, argv[0], &rect));
+ BADARG_IF(!enif_get_int(env, argv[1], &x1));
+ BADARG_IF(!enif_get_int(env, argv[2], &y1));
+ BADARG_IF(!enif_get_int(env, argv[3], &x2));
+ BADARG_IF(!enif_get_int(env, argv[4], &y2));
+
+ if (!SDL_IntersectRectAndLine(&rect, &x1, &y1, &x2, &y2))
+ return atom_false;
+
+ return enif_make_tuple4(env,
+ enif_make_int(env, x1),
+ enif_make_int(env, y1),
+ enif_make_int(env, x2),
+ enif_make_int(env, y2));
+}
+
+// union_rect
+
+NIF_FUNCTION(union_rect)
+{
+ SDL_Rect a, b, result;
+
+ BADARG_IF(!map_to_rect(env, argv[0], &a));
+ BADARG_IF(!map_to_rect(env, argv[1], &b));
+
+ SDL_UnionRect(&a, &b, &result);
+
+ return rect_to_map(env, &result);
+}
diff --git a/src/esdl2.erl b/src/esdl2.erl
index ae429e7..747b74e 100644
--- a/src/esdl2.erl
+++ b/src/esdl2.erl
@@ -114,6 +114,13 @@
%% sdl_power
-export([get_power_info/0]).
+%% sdl_rect
+-export([enclose_points/2]).
+-export([has_intersection/2]).
+-export([intersect_rect/2]).
+-export([intersect_rect_and_line/5]).
+-export([union_rect/2]).
+
%% sdl_renderer
-export([create_renderer/3]).
-export([get_num_render_drivers/0]).
@@ -487,6 +494,23 @@ get_platform() ->
get_power_info() ->
erlang:nif_error({not_loaded, ?MODULE}).
+%% sdl_rect
+
+enclose_points(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+has_intersection(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+intersect_rect(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+intersect_rect_and_line(_, _, _, _, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+union_rect(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
%% sdl_renderer
create_renderer(_, _, _) ->
diff --git a/src/sdl_rect.erl b/src/sdl_rect.erl
index b747d64..b2589f5 100644
--- a/src/sdl_rect.erl
+++ b/src/sdl_rect.erl
@@ -12,10 +12,64 @@
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+%% The SDL_FORCE_INLINE functions have been reimplemented in Erlang.
-module(sdl_rect).
+-export([enclose_points/2]).
+-export([has_intersection/2]).
+-export([intersection/2]).
+-export([intersection/3]).
+-export([intersection/5]).
+-export([is_empty/1]).
+-export([is_equal/2]).
+-export([is_in/2]).
+-export([union/2]).
+
-type point() :: #{x=>integer(), y=>integer()}.
-export_type([point/0]).
-type rect() :: #{x=>integer(), y=>integer(), w=>integer(), h=>integer()}.
-export_type([rect/0]).
+
+-spec enclose_points([point()], rect()) -> rect() | false.
+enclose_points(Points, ClipRect) ->
+ esdl2:enclose_points(Points, ClipRect).
+
+-spec has_intersection(rect(), rect()) -> boolean().
+has_intersection(Rect1, Rect2) ->
+ esdl2:has_intersection(Rect1, Rect2).
+
+-spec intersection(rect(), rect()) -> rect() | false.
+intersection(Rect1, Rect2) ->
+ esdl2:intersect_rect(Rect1, Rect2).
+
+-spec intersection(rect(), P1, P2) -> {P1, P2} | false when P1 :: point(), P2 :: point().
+intersection(Rect, #{x := X1, y := Y1}, #{x := X2, y := Y2}) ->
+ case intersection(Rect, X1, Y1, X2, Y2) of
+ false ->
+ false;
+ {ResX1, ResY1, ResX2, ResY2} ->
+ {#{x => ResX1, y => ResY1}, #{x => ResX2, y => ResY2}}
+ end.
+
+-spec intersection(rect(), X1, Y1, X2, Y2) -> {X1, Y1, X2, Y2} | false
+ when X1 :: integer(), Y1 :: integer(), X2 :: integer(), Y2 :: integer().
+intersection(Rect, X1, Y1, X2, Y2) ->
+ esdl2:intersect_rect_and_line(Rect, X1, Y1, X2, Y2).
+
+-spec is_empty(rect()) -> boolean().
+is_empty(#{w := W, h := H}) ->
+ (W =< 0) orelse (H =< 0).
+
+-spec is_equal(rect(), rect()) -> boolean().
+is_equal(Rect1, Rect2) ->
+ Rect1 =:= Rect2.
+
+-spec is_in(point(), rect()) -> boolean().
+is_in(#{x := PX, y := PY}, #{x := RX, y := RY, w := RW, h := RH}) ->
+ (PX >= RX) andalso (PX < RX + RW)
+ andalso (PY >= RY) andalso (PY < RY + RH).
+
+-spec union(rect(), rect()) -> rect().
+union(Rect1, Rect2) ->
+ esdl2:union_rect(Rect1, Rect2).