Skip to content

Commit 88839af

Browse files
authored
Merge pull request #315 from seb3s/add-alpha-channel-to-sprites
Add alpha channel to sprites
2 parents 5bc1c26 + ded8f29 commit 88839af

File tree

9 files changed

+68
-36
lines changed

9 files changed

+68
-36
lines changed

lib/scenic/graph/bounds.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ defmodule Scenic.Graph.Bounds do
226226
end
227227

228228
defp points(Primitive.Sprites, {_id, cmds}, _st) do
229-
Enum.reduce(cmds, [], fn {_, _, {x, y}, {w, h}}, acc ->
229+
Enum.reduce(cmds, [], fn {_, _, {x, y}, {w, h}, _alpha}, acc ->
230230
[[{x, y}, {x + w, y}, {x + w, y + h}, {x, y + h}, {x, y}] | acc]
231231
end)
232232
end

lib/scenic/primitive/sprites.ex

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,16 @@ defmodule Scenic.Primitive.Sprites do
2525
are executed in order when the primitive renders.
2626
2727
`[ {{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}} ]`
28+
or
29+
`[ {{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}}, alpha ]`
2830
2931
Each draw command is an x/y position and width/height of a rectangle in
3032
the source image, followed by the x/y position and width/height
3133
rectangle in the destination space.
3234
35+
An optional alpha channel can be set in last position to apply a transparency
36+
effect on the sprite.
37+
3338
In other words, This copies rectangular images from the source
3439
indicated by image_id and draws them in the coordinate space of
3540
the graph.
@@ -59,14 +64,16 @@ defmodule Scenic.Primitive.Sprites do
5964
You should add/modify primitives via the helper functions in
6065
[`Scenic.Primitives`](Scenic.Primitives.html#sprites/3)
6166
62-
This example draws the same source rectangle twice in different locations.
63-
The first is at full size, the second is expanded 10x.
67+
This example draws the same source rectangle three times in different locations.
68+
The first is at full size, the second is expanded 10x, the third is with a
69+
50% transparency effect.
6470
6571
```elixir
6672
graph
6773
|> sprites( { "images/my_sprites.png", [
6874
{{0,0}, {10, 20}, {10, 10}, {10, 20}},
6975
{{0,0}, {10, 20}, {100, 100}, {100, 200}},
76+
{{0,0}, {10, 20}, {100, 100}, {100, 200}, 0.5}
7077
]})
7178
```
7279
"""
@@ -81,7 +88,8 @@ defmodule Scenic.Primitive.Sprites do
8188
{sx :: number, sy :: number},
8289
{sw :: number, sh :: number},
8390
{dx :: number, dy :: number},
84-
{dw :: number, dh :: number}
91+
{dw :: number, dh :: number},
92+
alpha :: number
8593
}
8694
@type draw_cmds :: [draw_cmd()]
8795

@@ -217,22 +225,39 @@ defmodule Scenic.Primitive.Sprites do
217225
end
218226
end
219227

228+
@default_alpha 1
229+
220230
defp validate_commands(commands) do
221-
commands
222-
|> Enum.reduce({:ok, commands}, fn
223-
_, {:error, _} = error ->
224-
error
225-
226-
{{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}}, acc
227-
when is_number(src_x) and is_number(src_y) and
228-
is_number(src_w) and is_number(src_h) and
229-
is_number(dst_x) and is_number(dst_y) and
230-
is_number(dst_w) and is_number(dst_h) ->
231-
acc
232-
233-
cmd, _ ->
234-
{:error, :command, cmd}
235-
end)
231+
validate =
232+
Enum.reduce_while(commands, {:ok, []}, fn
233+
{{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}}, {:ok, cmds}
234+
when is_number(src_x) and is_number(src_y) and
235+
is_number(src_w) and is_number(src_h) and
236+
is_number(dst_x) and is_number(dst_y) and
237+
is_number(dst_w) and is_number(dst_h) ->
238+
{:cont,
239+
{:ok,
240+
[
241+
{{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}, @default_alpha}
242+
| cmds
243+
]}}
244+
245+
cmd = {{src_x, src_y}, {src_w, src_h}, {dst_x, dst_y}, {dst_w, dst_h}, alpha}, {:ok, cmds}
246+
when is_number(src_x) and is_number(src_y) and
247+
is_number(src_w) and is_number(src_h) and
248+
is_number(dst_x) and is_number(dst_y) and
249+
is_number(dst_w) and is_number(dst_h) and
250+
is_number(alpha) ->
251+
{:cont, {:ok, [cmd | cmds]}}
252+
253+
cmd, _ ->
254+
{:halt, {:error, :command, cmd}}
255+
end)
256+
257+
case validate do
258+
{:ok, cmds} -> {:ok, Enum.reverse(cmds)}
259+
error -> error
260+
end
236261
end
237262

238263
# --------------------------------------------------------

lib/scenic/primitive/style/paint/radial_gradient.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ defmodule Scenic.Primitive.Style.Paint.RadialGradient do
1616
1717
```elixir
1818
Graph.build()
19-
|> rect( {100, 50}, fill: {:linear, {50, 25, 10, 45, :blue, :yellow}} )
19+
|> rect( {100, 50}, fill: {:radial, {50, 25, 10, 45, :blue, :yellow}} )
2020
```
2121
"""
2222

lib/scenic/primitives.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,7 @@ defmodule Scenic.Primitives do
14141414

14151415
# --------------------------------------------------------
14161416
@doc """
1417-
Add a sprites list a graph.
1417+
Add a sprites list to a graph.
14181418
"""
14191419
@spec sprites(
14201420
source :: Graph.t() | Primitive.t(),

lib/scenic/script.ex

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,7 +1451,7 @@ defmodule Scenic.Script do
14511451

14521452
{cmds, count} =
14531453
Enum.reduce(cmds, {[], 0}, fn
1454-
{{sx, sy}, {sw, sh}, {dx, dy}, {dw, dh}}, {cmds, count} ->
1454+
{{sx, sy}, {sw, sh}, {dx, dy}, {dw, dh}, alpha}, {cmds, count} ->
14551455
{
14561456
[
14571457
<<
@@ -1462,7 +1462,8 @@ defmodule Scenic.Script do
14621462
dx::float-32-big,
14631463
dy::float-32-big,
14641464
dw::float-32-big,
1465-
dh::float-32-big
1465+
dh::float-32-big,
1466+
alpha::float-32-big
14661467
>>
14671468
| cmds
14681469
],
@@ -2204,10 +2205,11 @@ defmodule Scenic.Script do
22042205
dy::float-32-big,
22052206
dw::float-32-big,
22062207
dh::float-32-big,
2208+
alpha::float-32-big,
22072209
bin::binary
22082210
>> = bin
22092211

2210-
{[{{sx, sy}, {sw, sh}, {dx, dy}, {dw, dh}} | cmds], bin}
2212+
{[{{sx, sy}, {sw, sh}, {dx, dy}, {dw, dh}, alpha} | cmds], bin}
22112213
end)
22122214

22132215
cmds = Enum.reverse(cmds)

test/scenic/graph/bounds_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ defmodule Scenic.Graph.BoundsTest do
155155
end
156156

157157
test "finds the natural bounds of a single sprite" do
158-
graph = Graph.build() |> sprites({:parrot, [{{0, 0}, {10, 10}, {10, 20}, {30, 15}}]})
158+
graph = Graph.build() |> sprites({:parrot, [{{0, 0}, {10, 10}, {10, 20}, {30, 15}, 1}]})
159159
{10.0, 20.0, 40.0, 35.0} = Graph.bounds(graph)
160160
end
161161

@@ -165,8 +165,8 @@ defmodule Scenic.Graph.BoundsTest do
165165
|> sprites(
166166
{:parrot,
167167
[
168-
{{0, 0}, {10, 10}, {10, 20}, {30, 15}},
169-
{{0, 0}, {10, 10}, {40, -3}, {30, 15}}
168+
{{0, 0}, {10, 10}, {10, 20}, {30, 15}, 1},
169+
{{0, 0}, {10, 10}, {40, -3}, {30, 15}, 1}
170170
]}
171171
)
172172

test/scenic/graph/compile_test.exs renamed to test/scenic/graph/compiler_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ defmodule Scenic.Graph.CompilerTest do
193193
# ---------------------------------------------------------
194194
test "graph with sprites works" do
195195
cmds = [
196-
{{0, 1}, {10, 11}, {2, 3}, {12, 13}},
197-
{{2, 3}, {10, 11}, {4, 5}, {12, 13}}
196+
{{0, 1}, {10, 11}, {2, 3}, {12, 13}, 1},
197+
{{2, 3}, {10, 11}, {4, 5}, {12, 13}, 1}
198198
]
199199

200200
{:ok, list} =
@@ -250,7 +250,7 @@ defmodule Scenic.Graph.CompilerTest do
250250
end
251251

252252
# ---------------------------------------------------------
253-
# Should correctly compile fill and stroke. Note that
253+
# Should correctly compile fill and stroke. Note that
254254
# primitives with neither fill nor stroke are eliminated completely
255255
test "fill and stroke are compiled correctly" do
256256
{:ok, list} =

test/scenic/primitive/sprites_test.exs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ defmodule Scenic.Primitive.SpritesTest do
1212

1313
@cmds [
1414
{{0, 1}, {10, 11}, {2, 3}, {12, 13}},
15-
{{2, 3}, {10, 11}, {4, 5}, {12, 13}}
15+
{{2, 3}, {10, 11}, {4, 5}, {12, 13}, 0.8}
16+
]
17+
18+
@enhanced_cmds [
19+
{{0, 1}, {10, 11}, {2, 3}, {12, 13}, 1},
20+
{{2, 3}, {10, 11}, {4, 5}, {12, 13}, 0.8}
1621
]
1722

1823
# ============================================================================
@@ -21,16 +26,16 @@ defmodule Scenic.Primitive.SpritesTest do
2126
test "build works" do
2227
p = Sprites.build({:parrot, @cmds})
2328
assert p.module == Sprites
24-
assert Primitive.get(p) == {:parrot, @cmds}
29+
assert Primitive.get(p) == {:parrot, @enhanced_cmds}
2530
end
2631

2732
# ============================================================================
2833

2934
test "validate accepts valid data" do
30-
assert Sprites.validate({:parrot, @cmds}) == {:ok, {:parrot, @cmds}}
35+
assert Sprites.validate({:parrot, @cmds}) == {:ok, {:parrot, @enhanced_cmds}}
3136

3237
assert Sprites.validate({{:test_assets, "images/parrot.png"}, @cmds}) ==
33-
{:ok, {{:test_assets, "images/parrot.png"}, @cmds}}
38+
{:ok, {{:test_assets, "images/parrot.png"}, @enhanced_cmds}}
3439
end
3540

3641
test "validate rejects bad data" do
@@ -65,7 +70,7 @@ defmodule Scenic.Primitive.SpritesTest do
6570
p = Sprites.build({:parrot, @cmds})
6671

6772
assert Sprites.compile(p, %{stroke_fill: :blue}) == [
68-
{:draw_sprites, {"VvWQFjblIwTGsvGx866t8MIG2czWyIc8by6Xc88AOns", @cmds}}
73+
{:draw_sprites, {"VvWQFjblIwTGsvGx866t8MIG2czWyIc8by6Xc88AOns", @enhanced_cmds}}
6974
]
7075
end
7176
end

test/scenic/script_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ defmodule Scenic.ScriptTest do
238238
end
239239

240240
test "draw_sprites works" do
241-
cmds = [{{10, 11}, {30, 40}, {2, 3}, {60, 70}}]
241+
cmds = [{{10, 11}, {30, 40}, {2, 3}, {60, 70}, 1}]
242242
expected = [{:draw_sprites, {"VvWQFjblIwTGsvGx866t8MIG2czWyIc8by6Xc88AOns", cmds}}]
243243
assert Script.draw_sprites([], :parrot, cmds) == expected
244244
assert expected == Script.serialize(expected) |> Script.deserialize()

0 commit comments

Comments
 (0)