From 01a4819bb9b15af6ff00aa7278d09d14dc7a6e49 Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 20 Oct 2021 16:37:03 +0200 Subject: [PATCH 01/36] first attempt at DelayedPosition --- src/Javis.jl | 8 ++++++++ src/object_values.jl | 25 +++++++++++++++++++++++++ src/structs/Delayed.jl | 5 +++++ src/structs/Transitions.jl | 6 +++--- 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/structs/Delayed.jl diff --git a/src/Javis.jl b/src/Javis.jl index e54db99e1..1add70443 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -52,6 +52,7 @@ Transformation(p, a) = Transformation(p, a, 1.0) Transformation(p, a, s::Float64) = Transformation(p, a, (s, s)) Transformation(p, a, s::Tuple{Float64,Float64}) = Transformation(p, a, Scale(s...)) +include("structs/Delayed.jl") include("structs/ObjectSetting.jl") include("structs/Object.jl") include("structs/Transitions.jl") @@ -204,6 +205,11 @@ end # finally objects flatten!(objects::Array{AbstractObject}, object::Object) = push!(objects, object) + +const STARTED_RENDERING = [ + false +] + """ render( video::Video; @@ -253,6 +259,8 @@ function render( postprocess_frames_flow = identity, postprocess_frame = default_postprocess, ) + + STARTED_RENDERING[1] = true layers = video.layers objects = video.objects frames = preprocess_frames!(video) diff --git a/src/object_values.jl b/src/object_values.jl index f09d7ce5f..f2787cc9e 100644 --- a/src/object_values.jl +++ b/src/object_values.jl @@ -17,6 +17,16 @@ val(x) = get_value(x) get_position(p::Point) = p get_position(t::Transformation) = t.point +""" + get_delayed_position(obj::Object) + +In principle this is similar to [`get_position`](@ref) however, unlike that +one it gets evaluated the first time is called after the rendering has started. +""" +function get_delayed_position(obj::Object) + DelayedPosition(obj, nothing, false) +end + """ get_position(obj::Object) @@ -32,6 +42,14 @@ function get_position(obj::Object) return get_position(obj.result[1]) end +function get_position(p::DelayedPosition) + if STARTED_RENDERING[1] && !p.called + p.called = true + p.position = get_position(p.obj) + end + return p.position +end + """ pos(x) @@ -39,6 +57,13 @@ end """ pos(x) = get_position(x) +""" + delayed_pos(x) + +`delayed_pos` is just a short-hand for [`get_delayed_position`](@ref) +""" +delayed_pos(x) = get_delayed_position(x) + # As it is just the number tuple -> return it get_scale(x::Tuple{<:Number,<:Number}) = Scale(x...) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl new file mode 100644 index 000000000..d4e7b05ef --- /dev/null +++ b/src/structs/Delayed.jl @@ -0,0 +1,5 @@ +mutable struct DelayedPosition + obj + position + called +end \ No newline at end of file diff --git a/src/structs/Transitions.jl b/src/structs/Transitions.jl index 1b7d57f5e..312cf6138 100644 --- a/src/structs/Transitions.jl +++ b/src/structs/Transitions.jl @@ -5,8 +5,8 @@ =# struct Translation <: AbstractTransition - from::Union{Object,Point} - to::Union{Object,Point} + from::Union{Object,Point,DelayedPosition} + to::Union{Object,Point,DelayedPosition} end """ @@ -29,7 +29,7 @@ act!(obj, Action(1:50, anim_translate(10, 10))) """ anim_translate(x::Real, y::Real) = anim_translate(Point(x, y)) anim_translate(tp::Point) = Translation(O, tp) -anim_translate(fp::Union{Object,Point}, tp::Union{Object,Point}) = Translation(fp, tp) +anim_translate(fp::Union{Object,Point,DelayedPosition}, tp::Union{Object,Point,DelayedPosition}) = Translation(fp, tp) struct Rotation{T<:Real} <: AbstractTransition from::T From 64c46acdd43cc374ec05a96339fa4881cacc613e Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 20 Oct 2021 17:15:46 +0200 Subject: [PATCH 02/36] reset STARTED_RENDERING at the end of render --- src/Javis.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Javis.jl b/src/Javis.jl index 1add70443..b82e4bdbe 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -367,6 +367,7 @@ function render( # clear all CURRENT_* constants to not accidentally use a previous video when creating a new one empty_CURRENT_constants() + STARTED_RENDERING[1] = false # even if liveview = false, show the rendered gif in the cell output if isdefined(Main, :IJulia) && Main.IJulia.inited From 7d2ab4e96a7c27718f439bc4fc7b5a74bedcc25d Mon Sep 17 00:00:00 2001 From: gpucce Date: Tue, 26 Oct 2021 15:22:51 +0200 Subject: [PATCH 03/36] add types to DelayedPosition and add DelayedPosition to Rotation --- src/structs/Delayed.jl | 6 +++--- src/structs/Transitions.jl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index d4e7b05ef..7509fec37 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -1,5 +1,5 @@ mutable struct DelayedPosition - obj - position - called + obj::AbstractObject + position::Union{Nothing, Point} + called::Bool end \ No newline at end of file diff --git a/src/structs/Transitions.jl b/src/structs/Transitions.jl index 312cf6138..681c41f58 100644 --- a/src/structs/Transitions.jl +++ b/src/structs/Transitions.jl @@ -34,7 +34,7 @@ anim_translate(fp::Union{Object,Point,DelayedPosition}, tp::Union{Object,Point,D struct Rotation{T<:Real} <: AbstractTransition from::T to::T - center::Union{Nothing,Point,AbstractObject} + center::Union{Nothing,Point,AbstractObject, DelayedPosition} end """ From c53da962f4b94e0f2cbe8cf8425bace41c7a758e Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 13:33:51 +0200 Subject: [PATCH 04/36] add first test for delayed --- test/delayed.jl | 20 ++++++++++++++++++++ test/images/.keep | 0 test/refs/delayed_translation_1.png | Bin 0 -> 1024 bytes test/refs/delayed_translation_15.png | Bin 0 -> 1016 bytes test/refs/delayed_translation_24.png | Bin 0 -> 1048 bytes test/refs/delayed_translation_30.png | Bin 0 -> 1056 bytes test/refs/delayed_translation_7.png | Bin 0 -> 1015 bytes test/runtests.jl | 6 ++++++ test/stream_local.gif | Bin 95147 -> 95518 bytes 9 files changed, 26 insertions(+) create mode 100644 test/delayed.jl delete mode 100644 test/images/.keep create mode 100644 test/refs/delayed_translation_1.png create mode 100644 test/refs/delayed_translation_15.png create mode 100644 test/refs/delayed_translation_24.png create mode 100644 test/refs/delayed_translation_30.png create mode 100644 test/refs/delayed_translation_7.png diff --git a/test/delayed.jl b/test/delayed.jl new file mode 100644 index 000000000..2bdf56f5d --- /dev/null +++ b/test/delayed.jl @@ -0,0 +1,20 @@ + +@testset "delayedposition Trnslation" begin + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin; background("white"); sethue("black") end) + ball1 = Object(1:31, JCircle(O, 10, color="black", action=:fill), Point(-45, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!(ball1, Action(17:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) + v = render(testvideo, tempdirectory="images", pathname="") + + for frame in [1, 7, 15, 24, 30] + png_name = lpad(string(frame), 10, "0") + @test_reference "refs/delayed_translation_$(frame).png" load("images/$png_name.png",) + end + + for i in readdir("images", join=true) + if endswith(i, ".png") + rm(i) + end + end +end \ No newline at end of file diff --git a/test/images/.keep b/test/images/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/refs/delayed_translation_1.png b/test/refs/delayed_translation_1.png new file mode 100644 index 0000000000000000000000000000000000000000..4a8d27349a22089967f1b98371b790a97d243a52 GIT binary patch literal 1024 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4xj)-jM&AMK#C>Z(btiIVPik{pF~z5Um@8e z$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jb(lDyqr82-2SpV`mA zz+CI;;uunK>+KC&KM_WWhKEO4wD&Y@{J30UTLnL7P$Ay|=@|)EsxzD#sy)`WW<2KI z(xhQFi$hxY-rX~P*KGW^em32GfA-Cpb7ObTDG1(v>>tBvmo*Nf5G@1}6gQr`|8C9t zwQJw+v6ipC`*TeU-+#IG-}CGDSN$l;e$)Eg@XySz$>qQOSD(DOdGGw>e4F-%=hxi5 z9?tij|5#jQS@UtLJNwKmZplO1Wae4M+cKJUVf7`FFbU$eBeLL$%^yO>su0DQ#`nPV(f!aR_@82)} zD-Lp`>z|+Hd%i#4_4UP7q50w6ou)f2>@5FU?cBccXG!Us+UJ`lMEvi5TKi3+F=7;= chrmI7+m9A6UMkeh1ZGPHPgg&ebxsLQ0D(``C;$Ke literal 0 HcmV?d00001 diff --git a/test/refs/delayed_translation_15.png b/test/refs/delayed_translation_15.png new file mode 100644 index 0000000000000000000000000000000000000000..36b1ed929bc6e774e00a1a545b77cd10182f92a3 GIT binary patch literal 1016 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4xj)-jM&AMK#C>Z(btiIVPik{pF~z5Um@8e z$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jb(lDyqr82-2SpV`mA zz+CF-;uunK>+N;hEYU!QwuhYyLhm%(_z~Q)Wfy;Q)XqMYcMcsZeg_CVw%c;;P{w1v zEnXLHXs8$q)~vQX^f{#5@9RgS?*;FVy*#pi*OqS$|2rcZMR~_ptO|L8|2dO!7D^l)m zboJ#k7UF+Sep`O?JsN*dym_mX#qgGYd73>ZEjN!Qy7J4 cA@G6w)ozOyvAfw<0J9^5r>mdKI;Vst0Qp6i;{X5v literal 0 HcmV?d00001 diff --git a/test/refs/delayed_translation_24.png b/test/refs/delayed_translation_24.png new file mode 100644 index 0000000000000000000000000000000000000000..070664c34c8221e79cc105a4fa06e3f8e38e64b3 GIT binary patch literal 1048 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4xj)-jM&AMK#C>Z(btiIVPik{pF~z5Um@8e z$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jb(lDyqr82-2SpV`mA zz&zE{#WAGf*4rBgv!;YgG(5BqeZhL9W4GVJD3u*6RPQy+E_=-z@wn|F|_l_t^ofTfZM4soc8HAgR}KAMg9QTcY^h^G7Ck&Hh^Q z{l}Fjck-3@i7ej{$?q4fd;EU?jbyGh^Ud7t`#_BJ*^3VgR{MNB^XtdcXD`+>R{Iog z-e&GzXSHYb)tPSZ_iJw0cT1+$HmP58US$5yxnG}rYOr0lBXWLyaaB=z%T*ckY|CAR z6_5VBtoprw@5TSwU9-2ovAJbgSYvS{OK8p0TL-_^^Tn?_{>Ryv``RX}8~1BJXO;hd zFxk=j%*QiTm*2mBetPNN^T%`zgs*)_`zcW;aFA;hQW64t+5U*wy!h0hc?6hU89ZJ6 KT-G@yGywpQ@X+c2 literal 0 HcmV?d00001 diff --git a/test/refs/delayed_translation_30.png b/test/refs/delayed_translation_30.png new file mode 100644 index 0000000000000000000000000000000000000000..c5ad4adaaa831d1701074bb969674824e7c64562 GIT binary patch literal 1056 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4xj)-jM&AMK#C>Z(btiIVPik{pF~z5Um@8e z$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jb(lDyqr82-2SpV`mA zz&zK}#WAGf*4w)qPlu+;9QgP=>w@)6(^g*2YYEAEynd!8Q=L{fz5UCmb@m@~uP>jT zm(#=qXN9&)6aG7>JX)}Ni-z7)f!2NHAD!oY{&e8G_1w?W@7_N=ymR{IyJzn&j@wpS zUE45|i+gCps@(PbAL@5~KRmbn@r8}T?cuk!&-|Y6R&QVbb^hV}eLFt<(~^FEbXU={ zkM-BB@6U@$e!3+>e1FZqC$qbkhu^T&zLtM{{=S0!#jg)Poqn#X^v|_*2i>=uck9pn za`oZ!yJ3&7OP|i4EAo2x+lyD9Zujf@divXoXP=_gk5+vMS{#0NNreA4_x``ZTRb=3 zyC)|bRrh*HgnUkapWgn`pf%^WxzE?%UwUc!C3knZx3l(?et+;NTD^ADJ)8a2pS~Uh z8uu%ucfa4CABX-fzy3{sf5|2F>^Hl=eEht9eoWlKtf)1G50-CU|G#=~@w;D*re)`T znaU*h{JvlF|G32Cy_4hj?ml;D=Eh?Z^>z~P_iVhi?c~O5xwr1G*{h*53TYn#FC_P< X+BARobwL@JZ5cdW{an^LB{Ts5eQZMo literal 0 HcmV?d00001 diff --git a/test/refs/delayed_translation_7.png b/test/refs/delayed_translation_7.png new file mode 100644 index 0000000000000000000000000000000000000000..805bb848dccb6a4bc8a748591a3215ab4dbe54e1 GIT binary patch literal 1015 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4xj)-jM&AMK#C>Z(btiIVPik{pF~z5Um@8e z$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jb(lDyqr82-2SpV`mA zz+B?#;uunK>+KC&zmPzQhKC1PwC^-*{J30U+YWw?ppAS7WM?E?sm*X|sP$Oen(>%# z%b_2aJr?=+yt{p7rsurvvp$;^e|~bW`1zSz>t`-2%l^W;CTN4xC`1o|<_+uay~)qZ z$$7VbuM}@U)Nj*A(f)mQe}8`YaP(b9)63o+o9krW#73Xhn=kiICf8u6VEMI!tLvw^ zA73oE%#7i6%KKvvO47F+IwICz`t`@BV^99I-(D=aZ0ir(*I$-hee?NeMr)_8-0Pe= zme=*MXZr8;hRwL~==&P$`_J5@VBUwkfGrm8#|8;X{C0F~Nt^NG}<792+ zf$lS`|2J1Q?tOHB+`2Qhrd-+I{=WJ1==7U=*Uo+WmC<-XVa?T?P(LYe!8HP-5G@2Q ZIH2>$>B2pmYTpuvL(3;tV3&)F_jpC~0tMCp^N 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 G1OPkMbe;hK From 5e5d08bf87a4a29dd0c608848cd057950e637a3e Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 13:34:29 +0200 Subject: [PATCH 05/36] format --- src/Javis.jl | 4 +-- src/structs/Delayed.jl | 4 +-- src/structs/Transitions.jl | 7 +++-- test/delayed.jl | 21 ++++++++------- test/runtests.jl | 54 +++++++++++++++++++------------------- 5 files changed, 47 insertions(+), 43 deletions(-) diff --git a/src/Javis.jl b/src/Javis.jl index b82e4bdbe..40f5fb4a1 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -206,9 +206,7 @@ end flatten!(objects::Array{AbstractObject}, object::Object) = push!(objects, object) -const STARTED_RENDERING = [ - false -] +const STARTED_RENDERING = [false] """ render( diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 7509fec37..8419a9b64 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -1,5 +1,5 @@ mutable struct DelayedPosition obj::AbstractObject - position::Union{Nothing, Point} + position::Union{Nothing,Point} called::Bool -end \ No newline at end of file +end diff --git a/src/structs/Transitions.jl b/src/structs/Transitions.jl index 681c41f58..11ea7afb7 100644 --- a/src/structs/Transitions.jl +++ b/src/structs/Transitions.jl @@ -29,12 +29,15 @@ act!(obj, Action(1:50, anim_translate(10, 10))) """ anim_translate(x::Real, y::Real) = anim_translate(Point(x, y)) anim_translate(tp::Point) = Translation(O, tp) -anim_translate(fp::Union{Object,Point,DelayedPosition}, tp::Union{Object,Point,DelayedPosition}) = Translation(fp, tp) +anim_translate( + fp::Union{Object,Point,DelayedPosition}, + tp::Union{Object,Point,DelayedPosition}, +) = Translation(fp, tp) struct Rotation{T<:Real} <: AbstractTransition from::T to::T - center::Union{Nothing,Point,AbstractObject, DelayedPosition} + center::Union{Nothing,Point,AbstractObject,DelayedPosition} end """ diff --git a/test/delayed.jl b/test/delayed.jl index 2bdf56f5d..643dc32d3 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -1,20 +1,23 @@ @testset "delayedposition Trnslation" begin testvideo = Video(300, 300) - Background(1:31, (args...) -> begin; background("white"); sethue("black") end) - ball1 = Object(1:31, JCircle(O, 10, color="black", action=:fill), Point(-45, 0)) - act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) - act!(ball1, Action(17:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) - v = render(testvideo, tempdirectory="images", pathname="") + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!(ball1, Action(17:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) + v = render(testvideo, tempdirectory = "images", pathname = "") for frame in [1, 7, 15, 24, 30] png_name = lpad(string(frame), 10, "0") - @test_reference "refs/delayed_translation_$(frame).png" load("images/$png_name.png",) + @test_reference "refs/delayed_translation_$(frame).png" load("images/$png_name.png") end - for i in readdir("images", join=true) - if endswith(i, ".png") + for i in readdir("images", join = true) + if endswith(i, ".png") rm(i) end end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 2288b2e8b..b4d87fb8a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,31 +36,31 @@ end @testset "all" begin -@testset "Unit" begin - include("unit.jl") + @testset "Unit" begin + include("unit.jl") + end + @testset "SVG LaTeX tests" begin + include("svg.jl") + end + @testset "Animations" begin + include("animations.jl") + end + @testset "Morphing" begin + include("morphing.jl") + end + @testset "Javis Viewer" begin + include("viewer.jl") + end + @testset "Shorthands" begin + include("shorthands.jl") + end + @testset "Layers" begin + include("layers.jl") + end + @testset "Postprocessing" begin + include("postprocessing.jl") + end + @testset "delayed" begin + include("delayed.jl") + end end -@testset "SVG LaTeX tests" begin - include("svg.jl") -end -@testset "Animations" begin - include("animations.jl") -end -@testset "Morphing" begin - include("morphing.jl") -end -@testset "Javis Viewer" begin - include("viewer.jl") -end -@testset "Shorthands" begin - include("shorthands.jl") -end -@testset "Layers" begin - include("layers.jl") -end -@testset "Postprocessing" begin - include("postprocessing.jl") -end -@testset "delayed" begin - include("delayed.jl") -end -end \ No newline at end of file From dc47929662dfd72bea871377b6a55f1bea80a363 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 13:36:04 +0200 Subject: [PATCH 06/36] fix testset name --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index b4d87fb8a..b1e67051e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -60,7 +60,7 @@ end @testset "Postprocessing" begin include("postprocessing.jl") end - @testset "delayed" begin + @testset "Delayed" begin include("delayed.jl") end end From 44807f69ad77c660805eb6f7900634ad3b624be3 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 13:51:19 +0200 Subject: [PATCH 07/36] add .keep back --- images/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/.keep diff --git a/images/.keep b/images/.keep new file mode 100644 index 000000000..e69de29bb From 473add29bb23259bd5888472daa156bc3448205d Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 15:49:12 +0200 Subject: [PATCH 08/36] fix test in util not cleaning images folder --- test/images/.keep | 0 test/runtests.jl | 45 ++++++++--------- test/unit.jl | 122 ++++++++++++++++++++++++---------------------- 3 files changed, 84 insertions(+), 83 deletions(-) create mode 100644 test/images/.keep diff --git a/test/images/.keep b/test/images/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/runtests.jl b/test/runtests.jl index b1e67051e..7d5085c33 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,31 +36,28 @@ end @testset "all" begin + # @testset "SVG LaTeX tests" begin + # include("svg.jl") + # end + # @testset "Animations" begin + # include("animations.jl") + # end + # @testset "Morphing" begin + # include("morphing.jl") + # end + # @testset "Javis Viewer" begin + # include("viewer.jl") + # end + # @testset "Shorthands" begin + # include("shorthands.jl") + # end + # @testset "Layers" begin + # include("layers.jl") + # end + # @testset "Postprocessing" begin + # include("postprocessing.jl") + # end @testset "Unit" begin include("unit.jl") end - @testset "SVG LaTeX tests" begin - include("svg.jl") - end - @testset "Animations" begin - include("animations.jl") - end - @testset "Morphing" begin - include("morphing.jl") - end - @testset "Javis Viewer" begin - include("viewer.jl") - end - @testset "Shorthands" begin - include("shorthands.jl") - end - @testset "Layers" begin - include("layers.jl") - end - @testset "Postprocessing" begin - include("postprocessing.jl") - end - @testset "Delayed" begin - include("delayed.jl") - end end diff --git a/test/unit.jl b/test/unit.jl index 227624bb0..7dfbd8308 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -295,66 +295,70 @@ act!(a, Action(RFrames(1:3), appear(:fade))) # 1:3 render(video; tempdirectory = "images", pathname = "") @test Javis.get_frames(a.actions[1]) == 1:3 - end - - @testset "anim_" begin - s = anim_scale(1, 2) - @test s.from == Javis.Scale(1, 1) - @test s.to == Javis.Scale(2, 2) - - s = anim_scale(Javis.Scale(1, 1), 2) - @test s.from == Javis.Scale(1, 1) - @test s.to == Javis.Scale(2, 2) - - s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) - @test s.from == Javis.Scale(1, 1) - @test s.to == Javis.Scale(2, 2) - - s = anim_scale((1, 1), Javis.Scale(2, 1)) - @test s.from == Javis.Scale(1, 1) - @test s.to == Javis.Scale(2, 1) - - s = anim_scale(Javis.Scale(2, 1)) - @test s.from == :current_scale - @test s.to == Javis.Scale(2, 1) - end - - @testset "Test warning if background not defined" begin - video = Video(100, 100) - Background(1:10, (args...) -> 1) - Object(1:11, (args...) -> 2) - @test_logs (:warn,) render(video; pathname = "") - end - @testset "Test warning if action outside frame range" begin - video = Video(100, 100) - Background(1:20, (args...) -> 1) - act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) - @test_logs (:warn,) render(video; pathname = "") + for i in readdir("images", join=true) + endswith(i, ".png") && rm(i) + end end - @testset "Linear scale" begin - scale_val = scale_linear(-10, 10, 10, -10) - @test scale_val(-20) == 10 # clamped - @test scale_val(-5) == 5 - @test scale_val(20) == -10 - - scale_val = scale_linear(-10, 10, 10, -10; clamp = false) - @test scale_val(-20) == 20 # clamped - - scale_val = - scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) - @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped - @test scale_val(Point(-5, -7)) == Point(5, 7) - @test scale_val(Point(20, -10)) == Point(-10, 10) - - scale_val = scale_linear( - Point(-10, -10), - Point(10, 10), - Point(10, 10), - Point(-10, -10); - clamp = false, - ) - @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped - end +# @testset "anim_" begin +# s = anim_scale(1, 2) +# @test s.from == Javis.Scale(1, 1) +# @test s.to == Javis.Scale(2, 2) + +# s = anim_scale(Javis.Scale(1, 1), 2) +# @test s.from == Javis.Scale(1, 1) +# @test s.to == Javis.Scale(2, 2) + +# s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) +# @test s.from == Javis.Scale(1, 1) +# @test s.to == Javis.Scale(2, 2) + +# s = anim_scale((1, 1), Javis.Scale(2, 1)) +# @test s.from == Javis.Scale(1, 1) +# @test s.to == Javis.Scale(2, 1) + +# s = anim_scale(Javis.Scale(2, 1)) +# @test s.from == :current_scale +# @test s.to == Javis.Scale(2, 1) +# end + +# @testset "Test warning if background not defined" begin +# video = Video(100, 100) +# Background(1:10, (args...) -> 1) +# Object(1:11, (args...) -> 2) +# @test_logs (:warn,) render(video; pathname = "") +# end + +# @testset "Test warning if action outside frame range" begin +# video = Video(100, 100) +# Background(1:20, (args...) -> 1) +# act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) +# @test_logs (:warn,) render(video; pathname = "") +# end + +# @testset "Linear scale" begin +# scale_val = scale_linear(-10, 10, 10, -10) +# @test scale_val(-20) == 10 # clamped +# @test scale_val(-5) == 5 +# @test scale_val(20) == -10 + +# scale_val = scale_linear(-10, 10, 10, -10; clamp = false) +# @test scale_val(-20) == 20 # clamped + +# scale_val = +# scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) +# @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped +# @test scale_val(Point(-5, -7)) == Point(5, 7) +# @test scale_val(Point(20, -10)) == Point(-10, 10) + +# scale_val = scale_linear( +# Point(-10, -10), +# Point(10, 10), +# Point(10, 10), +# Point(-10, -10); +# clamp = false, +# ) +# @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped +# end end From 073a57579e947d0c2fc0ec910a0390c9db3e22d5 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 16:29:18 +0200 Subject: [PATCH 09/36] adjust testing so .keep does not get removed --- test/animations.jl | 1 - test/postprocessing.jl | 10 ++++----- test/runtests.jl | 49 +++++++++++++++++++++--------------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/test/animations.jl b/test/animations.jl index f520d342d..1c85448ba 100644 --- a/test/animations.jl +++ b/test/animations.jl @@ -899,5 +899,4 @@ end end rm("images/with_layer/", recursive = true) rm("images/without_layer/", recursive = true) - end diff --git a/test/postprocessing.jl b/test/postprocessing.jl index bf5fe6de8..7f02677dc 100644 --- a/test/postprocessing.jl +++ b/test/postprocessing.jl @@ -131,10 +131,9 @@ end @test_reference "images/$png_no_pad.png" load("images/$png_pad.png") end - for i in 1:n_frames - rm("images/$(lpad(i, 10, "0")).png") + for i in readdir("images", join=true) + endswith(i, ".png") && rm(i) end - rm("images/", recursive = true) function postprocess_crop(frame_image, idx, frames) return if idx > 25 @@ -159,10 +158,9 @@ end @test_reference "images/$png_no_crop.png" load("images/$png_crop.png") end - for i in 1:n_frames - rm("images/$(lpad(i, 10, "0")).png") + for i in readdir("images", join=true) + endswith(i, ".png") && rm(i) end - rm("images/", recursive = true) end @testset "postprocess_frame and postprocess_frames_flow" begin diff --git a/test/runtests.jl b/test/runtests.jl index 7d5085c33..8afdf23c5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -35,29 +35,28 @@ function circle_with_color(position, radius, action, color) end -@testset "all" begin - # @testset "SVG LaTeX tests" begin - # include("svg.jl") - # end - # @testset "Animations" begin - # include("animations.jl") - # end - # @testset "Morphing" begin - # include("morphing.jl") - # end - # @testset "Javis Viewer" begin - # include("viewer.jl") - # end - # @testset "Shorthands" begin - # include("shorthands.jl") - # end - # @testset "Layers" begin - # include("layers.jl") - # end - # @testset "Postprocessing" begin - # include("postprocessing.jl") - # end - @testset "Unit" begin - include("unit.jl") - end + +@testset "Unit" begin + include("unit.jl") +end +@testset "SVG LaTeX tests" begin + include("svg.jl") +end +@testset "Animations" begin + include("animations.jl") +end +@testset "Morphing" begin + include("morphing.jl") +end +@testset "Javis Viewer" begin + include("viewer.jl") +end +@testset "Shorthands" begin + include("shorthands.jl") +end +@testset "Layers" begin + include("layers.jl") +end +@testset "Postprocessing" begin + include("postprocessing.jl") end From 0003112eec408629e5ea5f1d8742afbe187a0b56 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 28 Oct 2021 16:29:58 +0200 Subject: [PATCH 10/36] format --- test/postprocessing.jl | 4 +- test/unit.jl | 122 ++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/test/postprocessing.jl b/test/postprocessing.jl index 7f02677dc..8e399f74e 100644 --- a/test/postprocessing.jl +++ b/test/postprocessing.jl @@ -131,7 +131,7 @@ end @test_reference "images/$png_no_pad.png" load("images/$png_pad.png") end - for i in readdir("images", join=true) + for i in readdir("images", join = true) endswith(i, ".png") && rm(i) end @@ -158,7 +158,7 @@ end @test_reference "images/$png_no_crop.png" load("images/$png_crop.png") end - for i in readdir("images", join=true) + for i in readdir("images", join = true) endswith(i, ".png") && rm(i) end end diff --git a/test/unit.jl b/test/unit.jl index 7dfbd8308..54ce4433a 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -296,69 +296,69 @@ render(video; tempdirectory = "images", pathname = "") @test Javis.get_frames(a.actions[1]) == 1:3 - for i in readdir("images", join=true) + for i in readdir("images", join = true) endswith(i, ".png") && rm(i) end end -# @testset "anim_" begin -# s = anim_scale(1, 2) -# @test s.from == Javis.Scale(1, 1) -# @test s.to == Javis.Scale(2, 2) - -# s = anim_scale(Javis.Scale(1, 1), 2) -# @test s.from == Javis.Scale(1, 1) -# @test s.to == Javis.Scale(2, 2) - -# s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) -# @test s.from == Javis.Scale(1, 1) -# @test s.to == Javis.Scale(2, 2) - -# s = anim_scale((1, 1), Javis.Scale(2, 1)) -# @test s.from == Javis.Scale(1, 1) -# @test s.to == Javis.Scale(2, 1) - -# s = anim_scale(Javis.Scale(2, 1)) -# @test s.from == :current_scale -# @test s.to == Javis.Scale(2, 1) -# end - -# @testset "Test warning if background not defined" begin -# video = Video(100, 100) -# Background(1:10, (args...) -> 1) -# Object(1:11, (args...) -> 2) -# @test_logs (:warn,) render(video; pathname = "") -# end - -# @testset "Test warning if action outside frame range" begin -# video = Video(100, 100) -# Background(1:20, (args...) -> 1) -# act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) -# @test_logs (:warn,) render(video; pathname = "") -# end - -# @testset "Linear scale" begin -# scale_val = scale_linear(-10, 10, 10, -10) -# @test scale_val(-20) == 10 # clamped -# @test scale_val(-5) == 5 -# @test scale_val(20) == -10 - -# scale_val = scale_linear(-10, 10, 10, -10; clamp = false) -# @test scale_val(-20) == 20 # clamped - -# scale_val = -# scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) -# @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped -# @test scale_val(Point(-5, -7)) == Point(5, 7) -# @test scale_val(Point(20, -10)) == Point(-10, 10) - -# scale_val = scale_linear( -# Point(-10, -10), -# Point(10, 10), -# Point(10, 10), -# Point(-10, -10); -# clamp = false, -# ) -# @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped -# end + # @testset "anim_" begin + # s = anim_scale(1, 2) + # @test s.from == Javis.Scale(1, 1) + # @test s.to == Javis.Scale(2, 2) + + # s = anim_scale(Javis.Scale(1, 1), 2) + # @test s.from == Javis.Scale(1, 1) + # @test s.to == Javis.Scale(2, 2) + + # s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) + # @test s.from == Javis.Scale(1, 1) + # @test s.to == Javis.Scale(2, 2) + + # s = anim_scale((1, 1), Javis.Scale(2, 1)) + # @test s.from == Javis.Scale(1, 1) + # @test s.to == Javis.Scale(2, 1) + + # s = anim_scale(Javis.Scale(2, 1)) + # @test s.from == :current_scale + # @test s.to == Javis.Scale(2, 1) + # end + + # @testset "Test warning if background not defined" begin + # video = Video(100, 100) + # Background(1:10, (args...) -> 1) + # Object(1:11, (args...) -> 2) + # @test_logs (:warn,) render(video; pathname = "") + # end + + # @testset "Test warning if action outside frame range" begin + # video = Video(100, 100) + # Background(1:20, (args...) -> 1) + # act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) + # @test_logs (:warn,) render(video; pathname = "") + # end + + # @testset "Linear scale" begin + # scale_val = scale_linear(-10, 10, 10, -10) + # @test scale_val(-20) == 10 # clamped + # @test scale_val(-5) == 5 + # @test scale_val(20) == -10 + + # scale_val = scale_linear(-10, 10, 10, -10; clamp = false) + # @test scale_val(-20) == 20 # clamped + + # scale_val = + # scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) + # @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped + # @test scale_val(Point(-5, -7)) == Point(5, 7) + # @test scale_val(Point(20, -10)) == Point(-10, 10) + + # scale_val = scale_linear( + # Point(-10, -10), + # Point(10, 10), + # Point(10, 10), + # Point(-10, -10); + # clamp = false, + # ) + # @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped + # end end From 64f6f291f997927078f6710a54b08207d86f3af6 Mon Sep 17 00:00:00 2001 From: gpucce Date: Sun, 31 Oct 2021 20:25:00 +0100 Subject: [PATCH 11/36] add test for rotation and initial support for layers --- src/object_values.jl | 2 +- test/delayed.jl | 30 ++++++++++++++++++++++++++++-- test/refs/delayed_rotation_1.png | Bin 0 -> 1708 bytes test/refs/delayed_rotation_15.png | Bin 0 -> 1852 bytes test/refs/delayed_rotation_24.png | Bin 0 -> 1700 bytes test/refs/delayed_rotation_30.png | Bin 0 -> 1830 bytes test/refs/delayed_rotation_7.png | Bin 0 -> 1851 bytes test/runtests.jl | 3 +++ 8 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 test/refs/delayed_rotation_1.png create mode 100644 test/refs/delayed_rotation_15.png create mode 100644 test/refs/delayed_rotation_24.png create mode 100644 test/refs/delayed_rotation_30.png create mode 100644 test/refs/delayed_rotation_7.png diff --git a/src/object_values.jl b/src/object_values.jl index f2787cc9e..1ee7acefb 100644 --- a/src/object_values.jl +++ b/src/object_values.jl @@ -23,7 +23,7 @@ get_position(t::Transformation) = t.point In principle this is similar to [`get_position`](@ref) however, unlike that one it gets evaluated the first time is called after the rendering has started. """ -function get_delayed_position(obj::Object) +function get_delayed_position(obj::AbstractObject) DelayedPosition(obj, nothing, false) end diff --git a/test/delayed.jl b/test/delayed.jl index 643dc32d3..cdb311362 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -1,5 +1,5 @@ -@testset "delayedposition Trnslation" begin +@testset "delayedposition Translation" begin testvideo = Video(300, 300) Background(1:31, (args...) -> begin background("white") @@ -8,7 +8,7 @@ ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) act!(ball1, Action(17:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) - v = render(testvideo, tempdirectory = "images", pathname = "") + render(testvideo, tempdirectory = "images", pathname = "") for frame in [1, 7, 15, 24, 30] png_name = lpad(string(frame), 10, "0") @@ -21,3 +21,29 @@ end end end + +@testset "delayedposition rotation" begin + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + + ball1 = Object(1:31, JCircle(O, 10, color="black", action=:fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color="red", action=:fill), Point(0, -25)) + + act!(ball1, Action(1:17, anim_translate(Point(-45, 0), O))) + act!(ball2, Action(17:31, anim_rotate_around(-π, O))) + render(testvideo, tempdirectory = "images", pathname = "") + + for frame in [1, 7, 15, 24, 30] + png_name = lpad(string(frame), 10, "0") + @test_reference "refs/delayed_rotation_$(frame).png" load("images/$png_name.png") + end + + for i in readdir("images", join = true) + if endswith(i, ".png") + rm(i) + end + end +end \ No newline at end of file diff --git a/test/refs/delayed_rotation_1.png b/test/refs/delayed_rotation_1.png new file mode 100644 index 0000000000000000000000000000000000000000..bddd3bf72f0bcc6a9c9da3421e5564e2ae8c99d2 GIT binary patch literal 1708 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4kn<;H+e}VAjOjI=U}oXkrgMB-RN-K#XR}iwOj+G3$-1^oG(}& z%XysnnSbsDpWg9lckJVuiG4Yrw0_9{r*A2>ukA) zN4dc=6=!Zr_8Uko>=obg^WNU%`uVe^uYLNWnSXx~NTkhqS#V!p#Odef-@I7>6cFX( zx3o;OOLv{jxmfTPo8#>ytEVT0?P?$O`}zO;A(-0<^q7Rf?2oTR1UEL@^hGhXww%g7hk^!!stPNHky{QLLs z(W9iDF?D}`eSPGupFdx|eEI$T{h#Ld|CN=MeS33r z^Ua*Hii(ac%NE%G{QLWRiczGFn9ZAS-@d(g@#4vo6sx&>Y|Klhvi>~@mRXZvH=m!a z`DIDhmQ4%lOX}+OMd(D_%rUF}`RQqeja!uOg~RXOzgM5knO*h&-{05Q*O!--O$ZbC zvZ1@X`}XbVYhNB8?|)iUSyR)qrD;KXY+T$Yjnhv*{rDk~$?C|zd)KZy%9{_ZX?M9!Y&eO>YE%gfu_^CyN0f7$S`z+$dnKQNk( zKR-Vo>^|Wy{e1lV{(gSXK3lGy>7xeHpXyj|G}mvwP35PTm(~A0`SJzibdT2@za}3{ zFqnNdZg17shlkr|&zAl-`S0JqKWprydM8{H*)r>6#h+(qXP-WO8tBc^($eyB_BU_e z%F4*}9DjTcC literal 0 HcmV?d00001 diff --git a/test/refs/delayed_rotation_15.png b/test/refs/delayed_rotation_15.png new file mode 100644 index 0000000000000000000000000000000000000000..fe1a14709936e1d2162eae5ddb2171e869c88987 GIT binary patch literal 1852 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4kn<;H+e}VAjOjI=U}oXkrgMO*XF90AYBy=@ z*%LKuvG0mAyBBDlHC?f}P0TfS=jo;5Iu>3W^E0^SJ=c6c?f!rH`{&iKua9>R@}CeQ zsuIfT8R{4mI?5y|9D2`f&7Na*^bphYa~roDkvGdv`(3td`OJA~MMAw^7k13CIXO`| zX5X3kx%TIOex74-keT1W`g9|6hE3D4N8j&TR!!My`R~|LZyB2t3!P=GkL@bW-~r0K z2z>Tzhv4!4&3UrN`xY8*Sv9sqkWs6_FobjQl?fos&KDpGbaWxZdt7pt{ zIV@&Uv)r%nrO@iHZ@25{7#KIV>1O1+h1)Kq!i10@6n@2 z?D91qUM`=nr?3D2%Vq!ayQSB!t&Nti|MPMA{JN^o&(3B%X<~cx>FH_xyF4+T`E>fc-S0Q6*YB%(y>|Pei(FExfWqg_ocZ(NF#jL<{r`TwzH{f!OyhJh zF|l`hzsH&QIX0KPyR%b$eoawoYHR(cuh--4zuiclU;ppt-12*!ZWR literal 0 HcmV?d00001 diff --git a/test/refs/delayed_rotation_24.png b/test/refs/delayed_rotation_24.png new file mode 100644 index 0000000000000000000000000000000000000000..fea20846d8c7bd825b8be0e2b09cf792e172a843 GIT binary patch literal 1700 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 Cohje| literal 0 HcmV?d00001 diff --git a/test/refs/delayed_rotation_7.png b/test/refs/delayed_rotation_7.png new file mode 100644 index 0000000000000000000000000000000000000000..6fe4892547cfa19f3a4d4a55272b634717253ffb GIT binary patch literal 1851 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4kn<;H+e}VAjOjI=U}oXkrgM%}aiVl&s( zO&cXAP7~UqDWh@mrTP^ojkOCnMAr63>UuRP7^nELu%BDRpDs~(Z~OOs>(;DYtGH6# zV-?q=RZUA)DXi2QWs(#QZs)dU&#^iAN^5@2p{3q`@_v_YcLSV$ma( zcD|2S!~g6rer{3T_xSkE*Lr;NY477qteV`8etoT@vtiGf`#UNo*8aArm~hlpP5q(< zhm>OP@};Tm{?=@u<~Vk~4=)z` z_%D7aX7a~x-jheJ*IvI~9~qnazs}?iP|?cZoHMVqet!qcpPQGOd~S}Tvwp^p+TXg; zpU;|SykPy??d!K_p}5JPZFx`sRGKBc4g;IME_ROndA2iW7J#JKnET|@nV&toaDiK@ zuKL@CWOi}A4SMDGPCo8m43b~AEFvc5zTLH_Cj^%*zX(*sS^d4}gMzpBodvC|Ky4r| zb$9#teE9YH&tm8HinpdFN`gJ`vpaW*ia#B{!c;e%`vECl&srpu=1iN7N%jfg!>%QMDzhD3V z?|J+Ge?C1uefjd`+uL$y&z&pF!`5%}>BN&KDpJ*s=ErZ{y0tO+cwFVvsqgpypZEXg z)9LYbzg{la-~Z>+S@ZjQe!tt@FK7Gf05kuBk76alF?*}Nu3SFPs_u_P{oBpw?W$ia zY@ar5+Oy}+FG_IV%E`{o_P6`_eGRhu%a89}Bwh>?cUW->>0jPk^4z z&|%G;*V)NwmX(ym)Vp-S+2Z4}JU+Sor&$;`1*rFOS?m zbEc%pv?jBw2?iFmzf4}6o13=-O+(<$(k9#cY)5< z-}~iKBQyJs#NgoI)2B~o#IWXW`}y-{zum8l)YMk#&&Q+ z&fEEPZuz~3`KpmoQB~h=rUL_S7w5K|o1ebj&bJ4K0Vwp#@7Erme{*N?^NWk!-|v2J zXL7G8Z`Shpb-y~*=T*Gl`#mf?eE*L}-QLsn?gEX3#O>Y9>E{pg+uK-Lb{>nnaJJ-j s?)JaW`910tN6Rvj$}%dK|NogfcZ+@c`)1V=VC}}>>FVdQ&MBb@0KB_|lK=n! literal 0 HcmV?d00001 diff --git a/test/runtests.jl b/test/runtests.jl index 8afdf23c5..47392fa78 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -60,3 +60,6 @@ end @testset "Postprocessing" begin include("postprocessing.jl") end +@testset "Delayed" begin + include("delayed.jl") +end From f2ce80d5e867dc0cc095e4a91eaa5273b7acc34e Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 20:58:54 +0100 Subject: [PATCH 12/36] add +,- for betwenn delayedposition and poin --- src/structs/Delayed.jl | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 8419a9b64..7b8dc9bda 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -1,5 +1,21 @@ mutable struct DelayedPosition obj::AbstractObject - position::Union{Nothing,Point} + position::Point called::Bool end + +import Base: +, - + +function +(dp::DelayedPosition, p::Point) + DelayedPosition(dp.obj, dp.position + p, dp.called) +end + ++(p::Point, dp::DelayedPosition) = +(dp, p) + +function -(dp::DelayedPosition, p::Point) + return DelayedPosition(dp.obj, dp.position - p, dp.called) +end + +function -(p::Point, dp::DelayedPosition) + return DelayedPosition(dp.obj, p - dp.position, dp.called) +end From 3944a90dfccf705e1b2da96ef916464c3ddac631 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 20:59:08 +0100 Subject: [PATCH 13/36] format tests --- test/delayed.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/delayed.jl b/test/delayed.jl index cdb311362..714ed2755 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -24,17 +24,17 @@ end @testset "delayedposition rotation" begin testvideo = Video(300, 300) - Background(1:31, (args...) -> begin + Background(1:31, (args...) -> begin background("white") sethue("black") end) - - ball1 = Object(1:31, JCircle(O, 10, color="black", action=:fill), Point(-45, 0)) - ball2 = Object(1:31, JCircle(O, 10, color="red", action=:fill), Point(0, -25)) - - act!(ball1, Action(1:17, anim_translate(Point(-45, 0), O))) - act!(ball2, Action(17:31, anim_rotate_around(-π, O))) - render(testvideo, tempdirectory = "images", pathname = "") + + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color = "red", action = :fill), Point(0, -25)) + + act!(ball1, Action(1:17, anim_translate(Point(-45, 0), O))) + act!(ball2, Action(17:31, anim_rotate_around(-π, O))) + render(testvideo, tempdirectory = "images", pathname = "") for frame in [1, 7, 15, 24, 30] png_name = lpad(string(frame), 10, "0") @@ -46,4 +46,4 @@ end rm(i) end end -end \ No newline at end of file +end From 8e1c204cadfc6797f3cedc5aa6be3ae9ad56be19 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 20:59:34 +0100 Subject: [PATCH 14/36] minor operation change --- src/object_values.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/object_values.jl b/src/object_values.jl index 1ee7acefb..eccf4e62f 100644 --- a/src/object_values.jl +++ b/src/object_values.jl @@ -24,7 +24,7 @@ In principle this is similar to [`get_position`](@ref) however, unlike that one it gets evaluated the first time is called after the rendering has started. """ function get_delayed_position(obj::AbstractObject) - DelayedPosition(obj, nothing, false) + DelayedPosition(obj, O, false) end """ @@ -45,7 +45,7 @@ end function get_position(p::DelayedPosition) if STARTED_RENDERING[1] && !p.called p.called = true - p.position = get_position(p.obj) + p.position += get_position(p.obj) end return p.position end From a9d3837917959aa727821f5f8998193ea1874986 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 22:25:35 +0100 Subject: [PATCH 15/36] add test for + --- test/delayed.jl | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/test/delayed.jl b/test/delayed.jl index 714ed2755..c68db56e4 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -1,3 +1,40 @@ +@testset "delayed operations" begin + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!(ball2, Action(16:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) + mkdir("images/delayed/") + render(testvideo, tempdirectory = "images/delayed/", pathname = "") + + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!(ball2, Action(16:31, anim_translate(Point(0, 0), Point(0, -45)))) + mkdir("images/not_delayed/") + render(testvideo, tempdirectory = "images/not_delayed", pathname = "") + + for frame in [1, 5, 14, 24, 30] + png_name = lpad(frame, 10, "0") + @test_reference "images/delayed/$(png_name).png" load( + "images/not_delayed/$(png_name).png", + ) + end + + rm("images/not_delayed", recursive = true) + rm("images/delayed", recursive = true) +end + + @testset "delayedposition Translation" begin testvideo = Video(300, 300) @@ -16,9 +53,7 @@ end for i in readdir("images", join = true) - if endswith(i, ".png") - rm(i) - end + endswith(i, ".png") && rm(i) end end From dd3e312b51f905cffa99fdc26f7eddf44e5bcbed Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 22:31:38 +0100 Subject: [PATCH 16/36] add test for delayedposition +/- point both left and right --- test/delayed.jl | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/test/delayed.jl b/test/delayed.jl index c68db56e4..0d9f23a79 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -1,4 +1,6 @@ @testset "delayed operations" begin + + testvideo = Video(300, 300) Background(1:31, (args...) -> begin background("white") @@ -7,10 +9,37 @@ ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) - act!(ball2, Action(16:31, anim_translate(Javis.delayed_pos(ball1), Point(0, -45)))) + act!(ball2, Action(16:31, anim_translate(Point(25, 0), Point(0, -45)))) + mkdir("images/not_delayed/") + render(testvideo, tempdirectory = "images/not_delayed", pathname = "") + + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!( + ball2, + Action( + 16:31, + anim_translate(Javis.delayed_pos(ball1) + Point(25, 0), Point(0, -45)), + ), + ) mkdir("images/delayed/") render(testvideo, tempdirectory = "images/delayed/", pathname = "") + for frame in [1, 5, 14, 24, 30] + png_name = lpad(frame, 10, "0") + @test_reference "images/delayed/$(png_name).png" load( + "images/not_delayed/$(png_name).png", + ) + end + + rm("images/delayed", recursive = true) + testvideo = Video(300, 300) Background(1:31, (args...) -> begin background("white") @@ -19,9 +48,16 @@ ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) - act!(ball2, Action(16:31, anim_translate(Point(0, 0), Point(0, -45)))) - mkdir("images/not_delayed/") - render(testvideo, tempdirectory = "images/not_delayed", pathname = "") + act!( + ball2, + Action( + 16:31, + anim_translate(Javis.delayed_pos(ball1) - Point(-25, 0), Point(0, -45)), + ), + ) + mkdir("images/delayed/") + render(testvideo, tempdirectory = "images/delayed/", pathname = "") + for frame in [1, 5, 14, 24, 30] png_name = lpad(frame, 10, "0") @@ -30,8 +66,8 @@ ) end - rm("images/not_delayed", recursive = true) rm("images/delayed", recursive = true) + rm("images/not_delayed", recursive = true) end From c9ff4940af95b357b0e73a2cb3e14e95d2f00ae0 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 4 Nov 2021 23:05:03 +0100 Subject: [PATCH 17/36] change from STARTED_RENDERING to CURRENTLY_RENDERING and add test for it --- src/Javis.jl | 6 +++--- src/object_values.jl | 2 +- test/delayed.jl | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Javis.jl b/src/Javis.jl index 40f5fb4a1..cfff7ae66 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -206,7 +206,7 @@ end flatten!(objects::Array{AbstractObject}, object::Object) = push!(objects, object) -const STARTED_RENDERING = [false] +const CURRENTLY_RENDERING = [false] """ render( @@ -258,7 +258,7 @@ function render( postprocess_frame = default_postprocess, ) - STARTED_RENDERING[1] = true + CURRENTLY_RENDERING[1] = true layers = video.layers objects = video.objects frames = preprocess_frames!(video) @@ -344,6 +344,7 @@ function render( filecounter += 1 end + CURRENTLY_RENDERING[1] = false isempty(pathname) && return if ext == ".gif" # generate a colorpalette first so ffmpeg does not have to guess it @@ -365,7 +366,6 @@ function render( # clear all CURRENT_* constants to not accidentally use a previous video when creating a new one empty_CURRENT_constants() - STARTED_RENDERING[1] = false # even if liveview = false, show the rendered gif in the cell output if isdefined(Main, :IJulia) && Main.IJulia.inited diff --git a/src/object_values.jl b/src/object_values.jl index eccf4e62f..155f80c0a 100644 --- a/src/object_values.jl +++ b/src/object_values.jl @@ -43,7 +43,7 @@ function get_position(obj::Object) end function get_position(p::DelayedPosition) - if STARTED_RENDERING[1] && !p.called + if CURRENTLY_RENDERING[1] && !p.called p.called = true p.position += get_position(p.obj) end diff --git a/test/delayed.jl b/test/delayed.jl index 0d9f23a79..7a6d01709 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -68,6 +68,8 @@ rm("images/delayed", recursive = true) rm("images/not_delayed", recursive = true) + + @test Javis.CURRENTLY_RENDERING[1] == false end From bb316f367a335afb25798c27c6025f975bafe7de Mon Sep 17 00:00:00 2001 From: gpucce Date: Sat, 6 Nov 2021 23:32:41 +0100 Subject: [PATCH 18/36] add minimal doc for DelayedPosition --- src/structs/Delayed.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 7b8dc9bda..625cc82ff 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -1,3 +1,10 @@ +""" + DelayedPosition(obj, position, called) + +This struct is used in place of a `Point` as a hook that will let you access the +position of an object at the starting frame of an `Action`. One should not need to call +this directly, rather check [`delayed_pos`](@ref) +""" mutable struct DelayedPosition obj::AbstractObject position::Point From 84991286e874244a3a7c4777d54f1e4241d1bc8c Mon Sep 17 00:00:00 2001 From: gpucce Date: Sun, 7 Nov 2021 10:06:17 +0100 Subject: [PATCH 19/36] adjust tests --- test/delayed.jl | 27 +++++++++++++++++++++++++++ test/runtests.jl | 47 ++++++++++++++++++++++++----------------------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/test/delayed.jl b/test/delayed.jl index 7a6d01709..033fb3a17 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -58,6 +58,33 @@ mkdir("images/delayed/") render(testvideo, tempdirectory = "images/delayed/", pathname = "") + for frame in [1, 5, 14, 24, 30] + png_name = lpad(frame, 10, "0") + @test_reference "images/delayed/$(png_name).png" load( + "images/not_delayed/$(png_name).png", + ) + end + + rm("images/delayed", recursive = true) + + testvideo = Video(300, 300) + Background(1:31, (args...) -> begin + background("white") + sethue("black") + end) + ball1 = Object(1:31, JCircle(O, 10, color = "black", action = :fill), Point(-45, 0)) + ball2 = Object(1:31, JCircle(O, 10, color = "blue", action = :fill), Point(0, 0)) + act!(ball1, Action(1:31, anim_translate(Point(-45, 0), Point(45, 0)))) + act!( + ball2, + Action( + 16:31, + anim_translate(Javis.delayed_pos(ball1) - Point(-25, 0), Point(0, -45)), + ), + ) + mkdir("images/delayed/") + render(testvideo, tempdirectory = "images/delayed/", pathname = "") + for frame in [1, 5, 14, 24, 30] png_name = lpad(frame, 10, "0") diff --git a/test/runtests.jl b/test/runtests.jl index c65659b79..d56666f4f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -38,28 +38,29 @@ end @testset "Unit" begin include("unit.jl") end - @testset "SVG LaTeX tests" begin - include("svg.jl") - end - @testset "Animations" begin - include("animations.jl") - end - @testset "Morphing" begin - include("morphing.jl") - end - @testset "Javis Viewer" begin - include("viewer.jl") - end - @testset "Shorthands" begin - include("shorthands.jl") - end - @testset "Layers" begin - include("layers.jl") - end - @testset "Postprocessing" begin - include("postprocessing.jl") + # @testset "SVG LaTeX tests" begin + # include("svg.jl") + # end + # @testset "Animations" begin + # include("animations.jl") + # end + # @testset "Morphing" begin + # include("morphing.jl") + # end + # @testset "Javis Viewer" begin + # include("viewer.jl") + # end + # @testset "Shorthands" begin + # include("shorthands.jl") + # end + # @testset "Layers" begin + # include("layers.jl") + # end + # @testset "Postprocessing" begin + # include("postprocessing.jl") + # end + @testset "Delayed" begin + include("delayed.jl") end end -@testset "Delayed" begin - include("delayed.jl") -end + From 4fe938f064c7d44dd8041e29090837c680a0abe4 Mon Sep 17 00:00:00 2001 From: gpucce Date: Sun, 7 Nov 2021 10:07:05 +0100 Subject: [PATCH 20/36] doc change --- src/structs/Delayed.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 625cc82ff..352bcc371 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -3,7 +3,7 @@ This struct is used in place of a `Point` as a hook that will let you access the position of an object at the starting frame of an `Action`. One should not need to call -this directly, rather check [`delayed_pos`](@ref) +this directly, rather check [`delayed_pos`](@ref). """ mutable struct DelayedPosition obj::AbstractObject From 5dcf4a2df08378736580bb10682365bb1f9afc4a Mon Sep 17 00:00:00 2001 From: gpucce Date: Mon, 8 Nov 2021 09:47:59 +0100 Subject: [PATCH 21/36] reset tests --- test/runtests.jl | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index d56666f4f..6788b5d76 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -38,27 +38,27 @@ end @testset "Unit" begin include("unit.jl") end - # @testset "SVG LaTeX tests" begin - # include("svg.jl") - # end - # @testset "Animations" begin - # include("animations.jl") - # end - # @testset "Morphing" begin - # include("morphing.jl") - # end - # @testset "Javis Viewer" begin - # include("viewer.jl") - # end - # @testset "Shorthands" begin - # include("shorthands.jl") - # end - # @testset "Layers" begin - # include("layers.jl") - # end - # @testset "Postprocessing" begin - # include("postprocessing.jl") - # end + @testset "SVG LaTeX tests" begin + include("svg.jl") + end + @testset "Animations" begin + include("animations.jl") + end + @testset "Morphing" begin + include("morphing.jl") + end + @testset "Javis Viewer" begin + include("viewer.jl") + end + @testset "Shorthands" begin + include("shorthands.jl") + end + @testset "Layers" begin + include("layers.jl") + end + @testset "Postprocessing" begin + include("postprocessing.jl") + end @testset "Delayed" begin include("delayed.jl") end From 4d71361ccb01f564b725ac556b9001a8bedd8fd1 Mon Sep 17 00:00:00 2001 From: gpucce Date: Tue, 22 Feb 2022 23:39:14 +0100 Subject: [PATCH 22/36] add support for delayed_position in all shorthands except @JShape --- src/shorthands/JBox.jl | 30 +++++++++++++++++++++--------- src/shorthands/JCircle.jl | 13 ++++++++++--- src/shorthands/JEllipse.jl | 9 ++++++--- src/shorthands/JLine.jl | 6 ++++-- src/shorthands/JPoly.jl | 5 +++-- src/shorthands/JRect.jl | 5 +++-- src/shorthands/JStar.jl | 3 ++- src/structs/Delayed.jl | 2 ++ 8 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/shorthands/JBox.jl b/src/shorthands/JBox.jl index 27c002b4f..e58308a00 100644 --- a/src/shorthands/JBox.jl +++ b/src/shorthands/JBox.jl @@ -1,26 +1,37 @@ function _JBox( - cornerpoint1::Point, - cornerpoint2::Point, + cornerpoint1::PointOrDelayed, + cornerpoint2::PointOrDelayed, color, action::Symbol, vertices::Bool, ) sethue(color) - verts = box(cornerpoint1, cornerpoint2, action, vertices = vertices) + cp1 = get_position(cornerpoint1) + cp2 = get_position(cornerpoint2) + verts = box(cp1, cp2, action, vertices = vertices) return verts[2] end function _JBox(points::Array, color, action::Symbol, vertices::Bool) sethue(color) + points = [get_position(p) for p in points] verts = box(points, action, vertices = vertices) return verts[2] end -function _JBox(pt::Point, width::Real, height::Real, color, action::Symbol, vertices::Bool) +function _JBox( + pt::PointOrDelayed, + width::Real, + height::Real, + color, + action::Symbol, + vertices::Bool, +) sethue(color) + pt = get_position(pt) box(pt, width, height, action, vertices = vertices) return Point(pt.x - width / 2, pt.y + height / 2) end function _JBox( - pt::Point, + pt::PointOrDelayed, width::Real, height::Real, cornerradius::Float64, @@ -28,6 +39,7 @@ function _JBox( action::Symbol, ) sethue(color) + pt = get_position(pt) box(pt, width, height, cornerradius, action) return Point(pt.x - width / 2, pt.y + height / 2) end @@ -39,8 +51,8 @@ Create a box (rectangle) between two points and do an action. Returns the top left corner point of the box. """ JBox( - cornerpoint1::Point, - cornerpoint2::Point; + cornerpoint1::PointOrDelayed, + cornerpoint2::PointOrDelayed; color = "black", action = :stroke, vertices = false, @@ -70,7 +82,7 @@ JBox(points::Array; color = "black", action = :stroke, vertices = false) = Create a box/rectangle centered at point pt with width and height. Use vertices=true to return an array of the four corner points rather than draw the box. """ JBox( - pt::Point, + pt::PointOrDelayed, width::Real, height::Real; color = "black", @@ -101,7 +113,7 @@ JBox(x::Int64, y::Int64, width::Real, height::Real; color = "black", action = :s Draw a box/rectangle centered at point pt with width and height and round each corner by cornerradius. """ JBox( - pt::Point, + pt::PointOrDelayed, width::Real, height::Real, cornerradius::Float64; diff --git a/src/shorthands/JCircle.jl b/src/shorthands/JCircle.jl index 638b8c686..0dbc6b0c6 100644 --- a/src/shorthands/JCircle.jl +++ b/src/shorthands/JCircle.jl @@ -1,8 +1,9 @@ function _JCircle(center, radius, color, linewidth, action) sethue(color) setline(linewidth) - circle(center, radius, action) - return center + thecenter = get_position(center) + circle(thecenter, radius, action) + return thecenter end """ @@ -22,7 +23,13 @@ Draw a circle at `center` with the given `radius` Returns the center of the circle """ -JCircle(center::Point, radius::Real; color = "black", linewidth = 1, action = :stroke) = +JCircle( + center::PointOrDelayed, + radius::Real; + color = "black", + linewidth = 1, + action = :stroke, +) = ( args...; center = center, diff --git a/src/shorthands/JEllipse.jl b/src/shorthands/JEllipse.jl index 894eb348a..52d35f438 100644 --- a/src/shorthands/JEllipse.jl +++ b/src/shorthands/JEllipse.jl @@ -1,13 +1,14 @@ -function _JEllipse(cpt::Point, w::Real, h::Real, color, linewidth, action::Symbol) +function _JEllipse(cpt::PointOrDelayed, w::Real, h::Real, color, linewidth, action::Symbol) sethue(color) setline(linewidth) + cpt = get_position(cpt) ellipse(cpt, w, h, action) return cpt end function _JEllipse( - focus1::Point, - focus2::Point, + focus1::PointOrDelayed, + focus2::PointOrDelayed, k::Union{Real,Point}, color, linewidth, @@ -17,6 +18,8 @@ function _JEllipse( ) sethue(color) setline(linewidth) + focus1 = get_position(focus1) + focus2 = get_position(focus2) ellipse(focus1, focus2, k, action, stepvalue = stepvalue, reversepath = reversepath) return focus1, focus2 end diff --git a/src/shorthands/JLine.jl b/src/shorthands/JLine.jl index cc2ff84e4..fef00eda1 100644 --- a/src/shorthands/JLine.jl +++ b/src/shorthands/JLine.jl @@ -1,6 +1,8 @@ function _JLine(p1, p2, linewidth, color) sethue(color) setline(linewidth) + p1 = get_position(p1) + p2 = get_position(p2) line(p1, p2, :stroke) return p2 end @@ -17,8 +19,8 @@ end Draw a line between the points pt1 and pt2. Returns the final point of the line """ -JLine(pt1::Point, pt2::Point; linewidth = 1, color = "black") = +JLine(pt1::PointOrDelayed, pt2::PointOrDelayed; linewidth = 1, color = "black") = (args...; color = color, linewidth = linewidth, pt1 = pt1, pt2 = pt2) -> _JLine(pt1, pt2, linewidth, color) -JLine(pt::Point; kwargs...) = JLine(O, pt; kwargs...) +JLine(pt::PointOrDelayed; kwargs...) = JLine(O, pt; kwargs...) diff --git a/src/shorthands/JPoly.jl b/src/shorthands/JPoly.jl index dd2df48ef..b26efc76e 100644 --- a/src/shorthands/JPoly.jl +++ b/src/shorthands/JPoly.jl @@ -1,6 +1,7 @@ function _JPoly(pointlist, color, linewidth, action, close, reversepath) sethue(color) setline(linewidth) + pointlist = [get_position(p) for p in pointlist] poly(pointlist, action; close = close, reversepath = reversepath) end @@ -17,13 +18,13 @@ Draw a polygon around points in the pointlist. - `reversepath` can be set to `true` to reverse the path and create a polygon hole """ JPoly( - pointlist::Vector{Point}; + pointlist::Vector{T}; color = "black", linewidth = 1, action = :stroke, close = true, reversepath = false, -) = +) where {T<:PointOrDelayed} = ( args...; pointlist = pointlist, diff --git a/src/shorthands/JRect.jl b/src/shorthands/JRect.jl index bd76be7cb..3706e608d 100644 --- a/src/shorthands/JRect.jl +++ b/src/shorthands/JRect.jl @@ -1,5 +1,5 @@ function _JRect( - cornerpoint::Point, + cornerpoint::PointOrDelayed, w::Real, h::Real, color, @@ -8,6 +8,7 @@ function _JRect( ) sethue(color) setline(linewidth) + cornerpoint = get_position(cornerpoint) rect(cornerpoint, w, h, action) return cornerpoint end @@ -26,7 +27,7 @@ You can specify the `linewidth` and the `color` of the rectangle. - `action` Defines whether the rectangle should be outlined (`:stroke`) or filled (`:fill`) """ JRect( - cornerpoint::Point, + cornerpoint::PointOrDelayed, w::Real, h::Real; color = "black", diff --git a/src/shorthands/JStar.jl b/src/shorthands/JStar.jl index 306e5cbcb..69fa0585e 100644 --- a/src/shorthands/JStar.jl +++ b/src/shorthands/JStar.jl @@ -11,6 +11,7 @@ function _JStar( ) sethue(color) setline(linewidth) + center = get_position(center) star(center, radius, npoints, ratio, orientation, action, reversepath = reversepath) return center end @@ -33,7 +34,7 @@ Return the center of the star. - `reversepath` if true it reverses the path and therefore creates a hole (default: true) """ JStar( - center::Point, + center::PointOrDelayed, radius; color = "black", linewidth = 1, diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 352bcc371..48fc4a7d8 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -26,3 +26,5 @@ end function -(p::Point, dp::DelayedPosition) return DelayedPosition(dp.obj, p - dp.position, dp.called) end + +PointOrDelayed = Union{Point,DelayedPosition} From 20e6f40efeec79d53079212035fc939072dd25fc Mon Sep 17 00:00:00 2001 From: gpucce Date: Tue, 22 Feb 2022 23:42:55 +0100 Subject: [PATCH 23/36] improve howto --- docs/src/howto.md | 65 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/docs/src/howto.md b/docs/src/howto.md index 202a16931..d37c60428 100644 --- a/docs/src/howto.md +++ b/docs/src/howto.md @@ -19,7 +19,7 @@ Background(1:100, ground) render(video; pathname="how_to.gif") ``` -## Why are all my `Javis` functions undefined? +## Why are all my `Javis` functions undefined? If you have worked with the Julia drawing package [`Luxor.jl`](https://github.com/JuliaGraphics/Luxor.jl), you will be happy to see that it provides all the drawing functions that `Javis` uses. `Javis` is basically an abstraction layer built on on top of `Luxor.jl` which provides functions to animate the static images you can create with `Luxor` more easily. @@ -51,6 +51,7 @@ There are currently three different ways to define frames inside Javis. The simplest one is to define the `UnitRange` like `1:100` as above such that the action is called for every frame from `1` to `100`. **Examples:** + ```julia Object(1:100, (args...)->circle(O, 50, :fill)) Object(1:50, (args...)->circle(O, 70, :stroke)) @@ -59,6 +60,7 @@ Object(1:50, (args...)->circle(O, 70, :stroke)) It is relatively often the case that the following action should work with the same frames as the previous action this can be done with. **Examples:** + ```julia Object(1:100, (args...)->circle(O, 50, :fill)) Object(:same, (args...)->circle(O, 20, :stroke), Point(100, 100)) @@ -70,12 +72,14 @@ so either use the symbol `:same` or just don't mention frames. The last option is to define frames relative to the previous frame. More precisely the end of the last frame. **Examples:** + ```julia Object(1:50, (args...)->circle(O, 50, :fill)) Object(RFrames(1:50), (args...)->circle(O, 20, :stroke), Point(100, 100)) ``` This is the same as: + ```julia Object(1:50, (args...)->circle(O, 50, :fill)) Object(51:100, (args...)->circle(O, 20, :stroke), Point(100, 100)) @@ -95,6 +99,7 @@ this is using a change in opacity to show the circle. There are two other options `:scale` and `:fade_line_width`. `:scale` also works for every kind of [`Object`](@ref) whereas `:fade_line_width` only works if you only draw the stroke instead of using fill. **Example:** + ```julia circ = Object(1:100, (args...)->circle(O, 50, :stroke)) act!(circ, Action(1:50, appear(:fade_line_width))) @@ -117,6 +122,7 @@ end ``` Now we define two actions: + 1. Drawing a circle and saving the position `my_circle` 2. Drawing a rectangle above the circle @@ -130,17 +136,18 @@ In this animation the position of the circle is saved inside `my_circle` and can ## How can I show a text being drawn? -A `text` or [`latex`](@ref) rendering can appear as *any* other object with `appear(:fade)` and `appear(:scale)`, However, it also has a special [`appear`](@ref) functionality called +A `text` or [`latex`](@ref) rendering can appear as _any_ other object with `appear(:fade)` and `appear(:scale)`, However, it also has a special [`appear`](@ref) functionality called `:draw_text`. -You can use +You can use + ```julia my_text = Object(1:100, (args...) -> text("Hello World!"; halign = :center)) act!(my_text, Action(1:15, sineio(), appear(:draw_text))) act!(my_text, Action(76:100, sineio(), disappear(:draw_text))) ``` -to let the text `"Hello World!"` appear from left to right in an animated way. +to let the text `"Hello World!"` appear from left to right in an animated way. ## How can I have an object follow a path? @@ -154,12 +161,14 @@ my_star = Object(1:100, (args...) -> star(O, 20, 5, 0.5, 0, :fill)) act!(my_star, Action(1:100, follow_path(star(O, 200)))) ``` -in this case a star is following the path of a bigger star. +in this case a star is following the path of a bigger star. + > **NOTE:** the star inside [`follow_path`](@ref) should have the `action=:none` which is the default for most Luxor functions. > **NOTE:** Unfortunately the above currently only works for some Luxor functions like `ngon` and `star` but not for `circle` and `rect` as they return `true` instead of the points. In that case you need to define a function like: + ```julia function ground(args...) background("white") @@ -180,7 +189,6 @@ act!(my_star, Action(1:100, follow_path(luxor2poly(()->rect(O, 100, 100, :path)) render(video; pathname="follow_path.gif") ``` - Another possibility is to specify a vector of points like this: ```julia @@ -212,9 +220,50 @@ The live viewer can be called with adding `; liveview=true` to the [`render`](@r For longer videos, it can happen that rendering takes some time. A long time. -One way to reduce rendering time is that you can render a scaled version of the animation to check if everything is animated as expected. +One way to reduce rendering time is that you can render a scaled version of the animation to check if everything is animated as expected. By using `render(video; pathname="how_to.gif", rescale_factor=0.5)`, the rendering process can be sped up generally a factor of 2. -This scales the frames of an animation down to half where a `Video(1000, 1000)` will be shown as a `Video(500, 500)` rendered video. +This scales the frames of an animation down to half where a `Video(1000, 1000)` will be shown as a `Video(500, 500)` rendered video. > **Note:** You might want to experiment with rendering to `mp4` instead of `gif` as well. + +## Why does `pos` always throws error? + +Both `get_position` and `pos` are a bit unintuitive in the sense that one may think that this should work: + +```julia +vid = Video(500, 500) +Background(1:50, (args...)->background("black")) +o1 = Object(JCircle(O, 10, action=:fill)) +render(vid) +``` + +However this will throw an error: + +```julia +MethodError: no method matching get_position(::Nothing) +``` + +This happens because the `pos` is supposed to be used by the drawing function at render time. This means that instead of the above this would work: + +```julia +vid = Video(500, 500) +Background(1:50, (args...)->background("black")) +o1 = Object(JCircle(O, 10, action=:fill)) +o2 = Object(@JShape begin + circle(pos(o1), 5, :fill) + end) +render(vid) +``` + +However there is an alternative to `pos` to make the first example work, `get_delayed_position` and you can use this just like above: + +```julia +vid = Video(500, 500) +Background(1:50, (args...)->background("black")) +o1 = Object(JCircle(O, 10, action=:fill, color="red")) +# it works with or w/o this line and the effect changes coherently!!! +act!(o1, Action(anim_translate(Point(100, 0)))) +o2 = Object(25:50, JCircle(Javis.get_delayed_position(o1), 5, action=:fill, color="blue")) +embed(vid) +``` From 4e9c6779355ca0214b2d2bb648b01a6f92ba3135 Mon Sep 17 00:00:00 2001 From: gpucce Date: Tue, 22 Feb 2022 23:54:00 +0100 Subject: [PATCH 24/36] fix test --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index f36899e0a..eb2ae7afb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -58,8 +58,8 @@ end end @testset "Delayed" begin include("delayed.jl") + end @testset "Javis Viewer" begin include("viewer.jl") end end - From 16b65d0a9f90fdfe67bc3ef7224d8ee32000088f Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 24 Feb 2022 13:42:38 +0100 Subject: [PATCH 25/36] add delayed_pos for layers --- src/Javis.jl | 6 +++++- src/structs/Delayed.jl | 28 ++++++++++++++++++++++++---- src/structs/Layer.jl | 4 ++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/Javis.jl b/src/Javis.jl index bff2e8235..c275bb8d5 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -135,6 +135,10 @@ function centered_point(pos::Point, width::Int, height::Int) Point(pos.x - width / 2, pos.y - height / 2) end +function centered_point(pos::DelayedPosition, width::Int, height::Int) + Point(get_position(pos).x - width / 2, get_position(pos).y - height / 2) +end + """ preprocess_frames!(video::Video) @@ -566,7 +570,7 @@ function get_javis_frame(video, objects, frame; layers = Layer[]) # check if any layers have been defined if !isempty(layers) - starting_positions = Point[] + starting_positions = PointOrDelayed[] # render each layer's objects and store the layer's Drawing as an image matrix for layer in layers push!(starting_positions, layer.position) diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 48fc4a7d8..8d962572f 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -11,20 +11,40 @@ mutable struct DelayedPosition called::Bool end +PointOrDelayed = Union{Point,DelayedPosition} + import Base: +, - +-(dp::DelayedPosition) = DelayedPosition(dp.obj, -get_position(dp), dp.called) + function +(dp::DelayedPosition, p::Point) - DelayedPosition(dp.obj, dp.position + p, dp.called) + DelayedPosition(dp.obj, get_position(dp) + p, dp.called) end +(p::Point, dp::DelayedPosition) = +(dp, p) function -(dp::DelayedPosition, p::Point) - return DelayedPosition(dp.obj, dp.position - p, dp.called) + return DelayedPosition(dp.obj, get_position(dp) - p, dp.called) end function -(p::Point, dp::DelayedPosition) - return DelayedPosition(dp.obj, p - dp.position, dp.called) + return DelayedPosition(dp.obj, p - get_position(dp), dp.called) end -PointOrDelayed = Union{Point,DelayedPosition} +function translate(pos::DelayedPosition) + return translate(get_position(pos)) +end + + +import Luxor: distance + +distance(dp1::DelayedPosition, dp2::DelayedPosition) = + distance(get_position(dp1), get_position(dp2)) + +function distance(dp::DelayedPosition, p::Point) + return distance(get_position(dp), p) +end + +distance(p::Point, dp::DelayedPosition) = distance(dp, p) + +Base.:/(dp::DelayedPosition, k::Number) = get_position(dp) / k diff --git a/src/structs/Layer.jl b/src/structs/Layer.jl index 116a41d61..3c05ce513 100644 --- a/src/structs/Layer.jl +++ b/src/structs/Layer.jl @@ -18,7 +18,7 @@ mutable struct Layer <: AbstractObject frames::Frames width::Int height::Int - position::Point + position::PointOrDelayed layer_objects::Vector{AbstractObject} actions::Vector{AbstractAction} current_setting::LayerSetting @@ -40,7 +40,7 @@ function Layer( frames, width, height, - position::Point; + position::PointOrDelayed; layer_objects::Vector{AbstractObject} = AbstractObject[], actions::Vector{AbstractAction} = AbstractAction[], setting::LayerSetting = LayerSetting(), From 507fbaeafa13ad23fb9306c5495f334e6c74b3c5 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 24 Feb 2022 16:02:37 +0100 Subject: [PATCH 26/36] fix JEllipse and add more tests --- src/shorthands/JEllipse.jl | 9 +++- test/delayed.jl | 55 ++++++++++++++++++++ test/refs/delayed_shorthands_0000000001.png | Bin 0 -> 2662 bytes test/refs/delayed_shorthands_0000000002.png | Bin 0 -> 2710 bytes test/refs/delayed_shorthands_0000000041.png | Bin 0 -> 2692 bytes test/refs/delayed_shorthands_0000000042.png | Bin 0 -> 2682 bytes test/refs/delayed_shorthands_0000000101.png | Bin 0 -> 9241 bytes test/refs/delayed_shorthands_0000000102.png | Bin 0 -> 9405 bytes test/refs/delayed_shorthands_0000000151.png | Bin 0 -> 6823 bytes test/refs/delayed_shorthands_0000000152.png | Bin 0 -> 6866 bytes test/refs/delayed_shorthands_0000000200.png | Bin 0 -> 9666 bytes test/runtests.jl | 6 +-- 12 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 test/refs/delayed_shorthands_0000000001.png create mode 100644 test/refs/delayed_shorthands_0000000002.png create mode 100644 test/refs/delayed_shorthands_0000000041.png create mode 100644 test/refs/delayed_shorthands_0000000042.png create mode 100644 test/refs/delayed_shorthands_0000000101.png create mode 100644 test/refs/delayed_shorthands_0000000102.png create mode 100644 test/refs/delayed_shorthands_0000000151.png create mode 100644 test/refs/delayed_shorthands_0000000152.png create mode 100644 test/refs/delayed_shorthands_0000000200.png diff --git a/src/shorthands/JEllipse.jl b/src/shorthands/JEllipse.jl index c8169d42f..4a5cb0011 100644 --- a/src/shorthands/JEllipse.jl +++ b/src/shorthands/JEllipse.jl @@ -36,7 +36,14 @@ Returns the center of the ellipse. - `linewidth` = 2 - `action::Symbol` :stroke by default can be `:fill` or other actions explained in the Luxor documentation. """ -JEllipse(cpt::Point, w::Real, h::Real; color = "black", linewidth = 2, action = :stroke) = +JEllipse( + cpt::PointOrDelayed, + w::Real, + h::Real; + color = "black", + linewidth = 2, + action = :stroke, +) = ( args...; cpt = cpt, diff --git a/test/delayed.jl b/test/delayed.jl index 033fb3a17..6cb358415 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -147,3 +147,58 @@ end end end end + + +@testset "delayed_shorthands" begin + vid = Video(500, 500) + Background(1:200, (args...) -> background("black")) + o1 = Object(JCircle(O, 30, color = "red", action = :fill), Point(50, 0)) + act!(o1, Action(anim_rotate_around(2π, Point(0, 0)))) + o2 = Object(50:200, JStar(Javis.delayed_pos(o1), 50, color = "blue", action = :fill)) + l1 = @JLayer 100:200 200 200 Javis.delayed_pos(o2) begin + lo1 = Object(JStar(O, 50, color = "gray", action = :fill)) + end + + act!(o2, Action(anim_rotate_around(2π, Point(100, 0)))) + act!(l1, Action(1:100, anim_rotate_around(2π, Point(-100, 0)))) + + o4 = Object( + 100:200, + JEllipse(Javis.delayed_pos(o2), 10, 20, color = "green", action = :fill), + ) + o5 = Object( + 100:200, + JLine(Javis.delayed_pos(o2), Javis.delayed_pos(o1), color = "white"), + ) + o6 = Object( + 100:200, + JPoly( + Javis.PointOrDelayed[O, Javis.delayed_pos(o1), Javis.delayed_pos(o2)], + color = "navyblue", + action = :stroke, + linewidth = 10, + ), + ) + o3 = Object( + 100:200, + JBox(Javis.delayed_pos(o2), 10, 10, color = "orange", action = :fill), + ) + act!( + o3, + Action( + anim_translate(Javis.delayed_pos(o2), Javis.delayed_pos(o1) + Point(10, 10)), + ), + ) + render(vid, pathname = "", tempdirectory = "images/") + + for frame in [1, 2, 41, 42, 101, 102, 151, 152, 200] + png_name = lpad(string(frame), 10, "0") + @test_reference "refs/delayed_shorthands_$(png_name).png" load( + "images/$png_name.png", + ) + end + + for i in readdir("images", join = true) + endswith(i, ".png") && rm(i) + end +end diff --git a/test/refs/delayed_shorthands_0000000001.png b/test/refs/delayed_shorthands_0000000001.png new file mode 100644 index 0000000000000000000000000000000000000000..49241579dc95f94cdac6efc49b2db5470ec373e6 GIT binary patch literal 2662 zcmeH}{ZCU@9L7&eYgb-mOSdtHl_i*JvW=phYXvF+!GhBACccE0mod{#5UOwii-j9D zGZm$oW@@E~ibA2ZML@v|Ev!h|1APCnoBoNrE^ z^W@|lO%w2f{6F;v00bo`C1e0VnDdSIh~7#_Z0K-5_PLL^EgJq7^k-^mGa+bapvrtI6X z%S6VB)YnjQL$?2o%XJs(7;zU)Jt&VKE<%oMh;P}$-ZL@5xbN;7O3Zus9eGP2g67qK zNz5N9GcSxT?~FhWjD6gvscVTgo=yu~wtfX(wa}`6{z`UUOw4Pf!Vm-46kyj9EP3!Q z=OE(PHW!W{+IBU{LqCGPw@AC@Tj%=?JA$o)_A{g(~%LI&73|g%FwBr zRO~tBf~H2(?|SZJHJos7PqgA`m>v)lDz#UwlM>O~L+QMub8Y#@S z2DAm=D(i6vEMHHUvZ!4J*m?6{p(_AWNNYUe8Ci<);DJIziKMG!yUgQY?cv#UwlkJ7QS89Gg}qgcm=z8JW&DLpLE zP(ZAAH)7fJ@GzCmHcqxE;BfpZ(p)fg3LD0^%ydvWmtr+{qsz4_xm~x+at>~;EYx=w zpbm)V2>Xh_dqJTW)(Gt+zR@%$w3l~ygpM@vUp)=*53)X*GaOf5EN`;853y zbhY4`7pwM05n75he@AB)aC{qj z4q*#)RF2UVov+naP0pQz{e)I(X_j)YSEG)~&!H`D=6RQoXYL~|pLr=bd)L?7PiUjg zzT{YaZx`$rldgNV`e2Oj1jb2hL~ycXxb15K<@FX%<(fM~``h_Of+45GD_OfJ+1wZz zyeO#bq&+ctn>a!6C<{tnGsMEIiN?x#1m5bdc6H)opRjI7BHQ$Ou{ zTkhGcET>7%^3YN!^Ol2)CHb&ZZs*f0ddXhT+&ZQmqUYweQ)(H`wbg@$d+V?o?7nk1 zP4eL@Yb$E2Zys!8nYtOyBb&CD=su6iS*0EiI?p2T=1xdUWXR-Wwl|U+X_B%ETdwVG zRK)y%+uwVs=8@;4S=i~ELrpq4X)y;+ksEHEx@w(==h@1o#aKv6%`Mk7_PbQXtf#o> z*l*5$zHwt^PqC^W-6tw~Wo6oXYeOOlQ%{cKSMUVcg}NywI)tUn++;YFTv1pD(@KXD zLu>_DC{!_{_oZ3PO{>Wm+!1?^{6Znk_3ZRz{LQSyBlSR@bkX>mvX*L{nM6^*v(xj) z#bT9w^u&fneTkh5Wpm$OX(9g*`xiuWShD*7-a@$&KyV-=0;Y_H+5h@I%0aps>U=cdaBxBSP fEP3#b=3v3^2(gRRqBxQ0{Ro2OL_vZ!KCkwF2xwfZ literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000002.png b/test/refs/delayed_shorthands_0000000002.png new file mode 100644 index 0000000000000000000000000000000000000000..5b78704eb2d09faf7f62a7c0c149fa18bb6fc99a GIT binary patch literal 2710 zcmeH}`%jZs7{^a*0SgMjswiNqi9(DHoC z&P<3|>gw$Z09YEkD|#;ggn#DFVxogYx9ocED5R{Y_$UCbR=NF~;pEVSqkCg^0Ik9I zjYF*6ziV$i03tsC#3up39Y{O^fN%={XgUCl8UVZmQe;mU0Ithpqoa}w32(dkBf-w8 zT`vZ$Z(ANzWS8%g)UAukOkU<4^@strP8X{p{=v#}q`kVjy)fC;;0HG}{)$f(M^= z4#L{C8hL*b`Z=tzK_0w-sLgB|IY3Nqo9bwEy>s96zzK4kc3N@OA zIdQjCDfsA9v;ez}7IlABCw6<~3E$&)M9E&}VPR2Goc^MjIZ5)!BnF(659FCx1xLag z(|Caj4Aoj5O2p$6QhWw)r~2{OC0vtnP4}WY@%T~hOlG+1)Ic>>g-JyGcfijQ#$o5F z-YlD{K$^5Vc3EN&;Whdcvq}PLH=$Pi7G7>%RdQiz*rj4^hksiiNqU)&ImzgQ-0K50=Shk9+SnuHYV}An z{v)FQ&;Jn7a4QZgmoa(CgDjn!L|n#A4aA~9j3G)}<^B+Y%LlWF!4{$9Y1b{0?^> z+jZ*Dcw2>Ih)W?)-W&Pno;vZO_DgBcvfmr#w{?#GGF|uarmiw(6)@U$X3G4OPG}Wn z$p2suJ&Nzj$W?mfGoG!yolA5dH{t^BlFHN}o~BkS4*Nm9K>zYsdIp-*(wZc8ymkYG-UOb*E} zmnnbiZ*XZiKr{>l8ed}HaKDaZc2bY4$aIfL?kqR*;RZpXUX#0o+C`E!uuL)-2S=z8 zG@aK#&U`W_eBh*zUliqWs=x%HVJ^XLFLY=e76gY7&Dr7I`U}M^Hg{?-iL;ib^g*qn zobYRI_DWIqbI-6Aa@+Y_U7#96<>+eeD!YPZ`b_9Y|BJ*qG}(U-hC&E`78P^v-p2XBna=T{pdjkMN&xD=raan~+T0B{Nt^>TH5)V9U@GiI zR1w$fnN_1{S*QVjjen_^M|ewhtoe9y}9qFb21K5CkX8-^I literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000041.png b/test/refs/delayed_shorthands_0000000041.png new file mode 100644 index 0000000000000000000000000000000000000000..53536349157987208134f32e2881b0132a205bb9 GIT binary patch literal 2692 zcmeH}ZBP?O7{?bI#NYs}XQfqMtXLd6qKs&X$cs=af)Ef9V#ymqO)E1P#TYqyl!gN1 z*g|a;L?TqH0+JU55eOb|*cqfM6g`Ln31BPW9VXK8Kn@5!_}*{*$cLTX-!r?<|Ji5$ zJF{n^xuJHpYi$7lc42!%VgRsuvoKaHVy!4zL;?W21CaGS05lWI8UsM)1ppxi!1p2mj#8y=zaId$%fdo}VozJW!USVe zHiue=yPl->51hDAY`y2|kq>uy)Q03p6UD{sM9&qgu%PSv3v*(U@$b5;y|zVoWZZh0 z+Z|SUK90-s{A9!L=iA;tGI`?9ON|kuZTas6&CXj|%yWGG4y)=;R;w=r$OxeFUV^0_ zEcxJne+#YijWHr&LB%@qBjgW6CPJzMqURx}4p#iFyxvFDZ912}sk<^iI7bywCOC91 z4E5p2AwHtfnkz=}N3zH=;|{6fM^&?b1l_2gH}unW4=Q z)qOH*pDe|Z#3*m-4PC0+)$k28PThx-{I5XiC*}_NHyPLPYuJS}LEocmxWr1rlbVHP z(qi|gVDTVO(QfJn%qtoRp9?o6)Y}v#DFn?GM!tjjXM{Vq2dOsM zZoyb*`IUnz?f7QD3X`f`pQkubB0lGOQ*v@o^R>+K=1P|p+@lIlm-s;av-G3>S|Oyw zSqZbjg8rR4b!LlYC+9Ld?rkq!*olwoqwtlAC&l8NGD5}djGJGryw7T%!r{Y`SAFn) z)QfYDoo~)@ZcQUTrUo&O2&vRTT`mVA-k?yvyxa@J5DAjn{u-4@q_&XLK&|f&C1fAX zlMcIcYAVZ5exTPwq-LlsQkpC};B#uDk6wV~lnmW>8N>!wE8AG1lNaqrjxXd*7IkBO zpK@~8`QyXR4`nh0+1|i|oSxY^cl}6p4;^MQ=;eMsEXP!Z+sx_qG|{3&hHq)X@`X@S zd3Iw;z~e^I+i=x(@jIGnPR3+d70VVM1@<19J%X)C*E~i)H2ewaCrOc z-KaN%_ND^D!}(sBzGd-hXtVH(c;76&&8BS_hPD_FMiB!Bk$gFW6X=~%ym1Dlqoo@l zr@>=A`^fh$*A>~6dt(!bDzjPGJx%`w$4h-7)$2?2FdRENW}(jwU32FRH^Z4|W!f8p zCK-JC{E;lw@Hl;XH@cBi$6hnt3=#C)ZZ{-z&!>M>U*8B7bW7lmP)O*pRggq9mh1fI-{#Hhkd6>D~xUt zXe%~NKASRA&uI!?&vAtK&PGAh%><&IOqm&fTMwtBH36%XMQqJl2Yel2N8Q%dl^$|1 zc~9&{YlR7N{9EhMuM|~X38b3(2|j|PAxZwaD03;CfvPRPS^_vJ5MOOl_mh(WFZPkg zsi$zVfv4}uCXI9#T?C6ztw}SJopdpamLd(7?YzUw#FyDwGI!8h40w_ySn9!l`(Rp> XD{BhV^;`>NzKJ00b8d(xSgiOLEN_TF literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000042.png b/test/refs/delayed_shorthands_0000000042.png new file mode 100644 index 0000000000000000000000000000000000000000..eb1c1867374cddeae6d824c09e0a2305ad09d648 GIT binary patch literal 2682 zcmeH}TTl~M9L5g_Vnk%dlmb>Cef&iuarx%}sw z@64RD34E^G>ep5S0Nmns$0h>cF#B?>a-@~m8@ny^Os*uYc^lCzd! z*@NXA{2y;Y`or*k>OTAtr(M^<61qR>^f&4aWmE&&G^NtFy1P^b;lJBP>{D=bS(3>3 z!kBKZH>8pnuB{vE$WvVwh8jZ6*CMmx)lH^&BL_;d2#kUc!*O`S%Os^JTU0JGdAH$Rlk1mj|%sfDl+-$$k+>K@}!s>A-N#Gjo^ zjKKMvrljKXh5cCD;^r_{X3p$Y6l0kuB9Kv0fI3xrE))+RM2ZYMl_Pyb5qSv>>dj#O zIqgPqsq6lCuECl0P^P4Yo%}ePP}0iqdg6Vm3a_lqI9FwUNPc*;SZLY-iLiiPFJ?|& zCP$l}2U!lpYvyIHf%s}`lGR%BjDST82@(f(n2u{A-{l6hSX-i8`A4O{%~zt``31W$ zMAyz*!#^UG%}>K6Hqsj^!?uU17;C3IC}(9?y(*Om!6$fAtdqE`RkwTuC@{!_V#oYpna^t@AQw?N}Qtb&&8v5Sw`iewHUm9#s2H3*!Tk}{fz3atzG3(VO>An6L&CAPpb43w8?)*d2OnX(eO}DhFl*Ca(&2y1t zGjqex3hE^MF?Tw2sk0|4-$E~+7Wb9D!T3R}NvG-S4GB{+){>%)_v%+Rh0vmY3Tc9X zyJ>RCgIqNYPnt_*L$zafM+F*W;+F-!B#|}%gR(`|l=%c~$C7tu(mpVvG3i}=cj7pv zIi~h3Y>Z6PZ&Zvp_0N4teG3=c#(fE^G^uXv>0*1is=U2(X232RbL6$%));!s`QcmU zjB+Q>OsPktC;+)h{-msQA-6)gk|6f*BN-({uOP%D3|$QC4P?GKJq5>MT7Rgfyi?3f zyUHlkb|FaJ5!5TxEO++IkwV81xiOU>_>-Z;X*iJ1Sk7#<{XCq_(J`M1ED3rKMJ3}r zoXf$EAvUUHu7|>)B09mtq|T0@I2ng5o8O?B1N?H^eDX>DH70B)5e-_s-J-OG>V) z$J{UNd>jAdk0`PmRU@rgrcUx6^%Z=)EKfw}7xK%#Uet{WPl$_*3wRJuqO})T_7_q5 zv?SqdN_}g*Gk2%Mi@qr5^*qoT;?OqWbSs<*$Yoge;J^H%zE2;z3} JW09B)=|6JhZbtwB literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000101.png b/test/refs/delayed_shorthands_0000000101.png new file mode 100644 index 0000000000000000000000000000000000000000..c4474c8cbbfc7901d0f7d68bc382ba9761df9cac GIT binary patch literal 9241 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 I&~bY7KOw^r_5c6? literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000151.png b/test/refs/delayed_shorthands_0000000151.png new file mode 100644 index 0000000000000000000000000000000000000000..06db71c30e5d252e3d171d31c8ea02814ed6709d GIT binary patch literal 6823 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 literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000152.png b/test/refs/delayed_shorthands_0000000152.png new file mode 100644 index 0000000000000000000000000000000000000000..c72aab396d9483ac19e2975a2ef9e5103b109275 GIT binary patch literal 6866 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 Qk4_-3-Fw~ZTuHS50YCZATL1t6 literal 0 HcmV?d00001 diff --git a/test/refs/delayed_shorthands_0000000200.png b/test/refs/delayed_shorthands_0000000200.png new file mode 100644 index 0000000000000000000000000000000000000000..dc5b0b91cf8a622499f9083ec42e745a41cb0f15 GIT binary patch literal 9666 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 UP5Zurm#iR8D7U?B_Q4td2a8Hr Date: Thu, 24 Feb 2022 19:19:12 +0100 Subject: [PATCH 27/36] Change from PointOrDelayed to Luxor.AbstractPoint --- src/Javis.jl | 2 +- src/shorthands/JBox.jl | 16 ++++++++-------- src/shorthands/JCircle.jl | 4 ++-- src/shorthands/JEllipse.jl | 16 ++++++++-------- src/shorthands/JLine.jl | 4 ++-- src/shorthands/JPoly.jl | 4 ++-- src/shorthands/JRect.jl | 4 ++-- src/shorthands/JStar.jl | 2 +- src/structs/Delayed.jl | 4 +--- src/structs/Layer.jl | 4 ++-- test/delayed.jl | 2 +- 11 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/Javis.jl b/src/Javis.jl index c275bb8d5..fc700eb17 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -570,7 +570,7 @@ function get_javis_frame(video, objects, frame; layers = Layer[]) # check if any layers have been defined if !isempty(layers) - starting_positions = PointOrDelayed[] + starting_positions = Luxor.AbstractPoint[] # render each layer's objects and store the layer's Drawing as an image matrix for layer in layers push!(starting_positions, layer.position) diff --git a/src/shorthands/JBox.jl b/src/shorthands/JBox.jl index e58308a00..839383dee 100644 --- a/src/shorthands/JBox.jl +++ b/src/shorthands/JBox.jl @@ -1,6 +1,6 @@ function _JBox( - cornerpoint1::PointOrDelayed, - cornerpoint2::PointOrDelayed, + cornerpoint1::Luxor.AbstractPoint, + cornerpoint2::Luxor.AbstractPoint, color, action::Symbol, vertices::Bool, @@ -18,7 +18,7 @@ function _JBox(points::Array, color, action::Symbol, vertices::Bool) return verts[2] end function _JBox( - pt::PointOrDelayed, + pt::Luxor.AbstractPoint, width::Real, height::Real, color, @@ -31,7 +31,7 @@ function _JBox( return Point(pt.x - width / 2, pt.y + height / 2) end function _JBox( - pt::PointOrDelayed, + pt::Luxor.AbstractPoint, width::Real, height::Real, cornerradius::Float64, @@ -51,8 +51,8 @@ Create a box (rectangle) between two points and do an action. Returns the top left corner point of the box. """ JBox( - cornerpoint1::PointOrDelayed, - cornerpoint2::PointOrDelayed; + cornerpoint1::Luxor.AbstractPoint, + cornerpoint2::Luxor.AbstractPoint; color = "black", action = :stroke, vertices = false, @@ -82,7 +82,7 @@ JBox(points::Array; color = "black", action = :stroke, vertices = false) = Create a box/rectangle centered at point pt with width and height. Use vertices=true to return an array of the four corner points rather than draw the box. """ JBox( - pt::PointOrDelayed, + pt::Luxor.AbstractPoint, width::Real, height::Real; color = "black", @@ -113,7 +113,7 @@ JBox(x::Int64, y::Int64, width::Real, height::Real; color = "black", action = :s Draw a box/rectangle centered at point pt with width and height and round each corner by cornerradius. """ JBox( - pt::PointOrDelayed, + pt::Luxor.AbstractPoint, width::Real, height::Real, cornerradius::Float64; diff --git a/src/shorthands/JCircle.jl b/src/shorthands/JCircle.jl index 029d842ea..8384d0e37 100644 --- a/src/shorthands/JCircle.jl +++ b/src/shorthands/JCircle.jl @@ -24,7 +24,7 @@ Draw a circle at `center` with the given `radius` Returns the center of the circle """ JCircle( - center::PointOrDelayed, + center::Luxor.AbstractPoint, radius::Real; color = "black", linewidth = 1, @@ -42,7 +42,7 @@ JCircle( JCircle(center_x::Real, center_y::Real, radius::Real; kwargs...) = JCircle(Point(center_x, center_y), radius; kwargs...) -JCircle(p1::Point, p2::Point; kwargs...) = +JCircle(p1::Luxor.AbstractPoint, p2::Luxor.AbstractPoint; kwargs...) = JCircle(midpoint(p1, p2), distance(p1, p2) / 2; kwargs...) JCircle(radius::Real; kwargs...) = JCircle(O, radius; kwargs...) diff --git a/src/shorthands/JEllipse.jl b/src/shorthands/JEllipse.jl index 4a5cb0011..30361faa9 100644 --- a/src/shorthands/JEllipse.jl +++ b/src/shorthands/JEllipse.jl @@ -1,4 +1,4 @@ -function _JEllipse(cpt::PointOrDelayed, w::Real, h::Real, color, linewidth, action::Symbol) +function _JEllipse(cpt::Luxor.AbstractPoint, w::Real, h::Real, color, linewidth, action::Symbol) sethue(color) setline(linewidth) cpt = get_position(cpt) @@ -7,8 +7,8 @@ function _JEllipse(cpt::PointOrDelayed, w::Real, h::Real, color, linewidth, acti end function _JEllipse( - focus1::PointOrDelayed, - focus2::PointOrDelayed, + focus1::Luxor.AbstractPoint, + focus2::Luxor.AbstractPoint, k::Union{Real,Point}, color, linewidth, @@ -37,7 +37,7 @@ Returns the center of the ellipse. - `action::Symbol` :stroke by default can be `:fill` or other actions explained in the Luxor documentation. """ JEllipse( - cpt::PointOrDelayed, + cpt::Luxor.AbstractPoint, w::Real, h::Real; color = "black", @@ -64,8 +64,8 @@ Build a polygon approximation to an ellipse, given two points and a distance, k, required to go from one focus to the perimeter and on to the other focus). """ JEllipse( - focus1::Point, - focus2::Point, + focus1::Luxor.AbstractPoint, + focus2::Luxor.AbstractPoint, k::Real; color = "black", linewidth = 2, @@ -88,8 +88,8 @@ JEllipse( Build a polygon approximation to an ellipse, given two points and a point somewhere on the ellipse. """ JEllipse( - focus1::Point, - focus2::Point, + focus1::Luxor.AbstractPoint, + focus2::Luxor.AbstractPoint, pt::Point; color = "black", linewidth = 2, diff --git a/src/shorthands/JLine.jl b/src/shorthands/JLine.jl index 7c9cd007f..9791302bd 100644 --- a/src/shorthands/JLine.jl +++ b/src/shorthands/JLine.jl @@ -19,8 +19,8 @@ end Draw a line between the points pt1 and pt2. Returns the final point of the line """ -JLine(pt1::PointOrDelayed, pt2::PointOrDelayed; linewidth = 1, color = "black") = +JLine(pt1::Luxor.AbstractPoint, pt2::Luxor.AbstractPoint; linewidth = 1, color = "black") = (args...; color = color, linewidth = linewidth, pt1 = pt1, pt2 = pt2) -> _JLine(pt1, pt2, linewidth, color) -JLine(pt::PointOrDelayed; kwargs...) = JLine(O, pt; kwargs...) +JLine(pt::Luxor.AbstractPoint; kwargs...) = JLine(O, pt; kwargs...) diff --git a/src/shorthands/JPoly.jl b/src/shorthands/JPoly.jl index 98685adf2..33338f40a 100644 --- a/src/shorthands/JPoly.jl +++ b/src/shorthands/JPoly.jl @@ -18,13 +18,13 @@ Draw a polygon around points in the pointlist. - `reversepath` can be set to `true` to reverse the path and create a polygon hole """ JPoly( - pointlist::Vector{T}; + pointlist::Vector{Luxor.AbstractPoint}; color = "black", linewidth = 2, action = :stroke, close = true, reversepath = false, -) where {T<:PointOrDelayed} = +) = ( args...; pointlist = pointlist, diff --git a/src/shorthands/JRect.jl b/src/shorthands/JRect.jl index f42cb9314..64cd3aa63 100644 --- a/src/shorthands/JRect.jl +++ b/src/shorthands/JRect.jl @@ -1,5 +1,5 @@ function _JRect( - cornerpoint::PointOrDelayed, + cornerpoint::Luxor.AbstractPoint, w::Real, h::Real, color, @@ -27,7 +27,7 @@ You can specify the `linewidth` and the `color` of the rectangle. - `action` Defines whether the rectangle should be outlined (`:stroke`) or filled (`:fill`) """ JRect( - cornerpoint::PointOrDelayed, + cornerpoint::Luxor.AbstractPoint, w::Real, h::Real; color = "black", diff --git a/src/shorthands/JStar.jl b/src/shorthands/JStar.jl index 032761a4c..a15909120 100644 --- a/src/shorthands/JStar.jl +++ b/src/shorthands/JStar.jl @@ -34,7 +34,7 @@ Return the center of the star. - `reversepath` if true it reverses the path and therefore creates a hole (default: true) """ JStar( - center::PointOrDelayed, + center::Luxor.AbstractPoint, radius; color = "black", linewidth = 2, diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 8d962572f..3ce5e7dc6 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -5,14 +5,12 @@ This struct is used in place of a `Point` as a hook that will let you access the position of an object at the starting frame of an `Action`. One should not need to call this directly, rather check [`delayed_pos`](@ref). """ -mutable struct DelayedPosition +mutable struct DelayedPosition <: Luxor.AbstractPoint obj::AbstractObject position::Point called::Bool end -PointOrDelayed = Union{Point,DelayedPosition} - import Base: +, - -(dp::DelayedPosition) = DelayedPosition(dp.obj, -get_position(dp), dp.called) diff --git a/src/structs/Layer.jl b/src/structs/Layer.jl index 3c05ce513..9b4b0df26 100644 --- a/src/structs/Layer.jl +++ b/src/structs/Layer.jl @@ -18,7 +18,7 @@ mutable struct Layer <: AbstractObject frames::Frames width::Int height::Int - position::PointOrDelayed + position::Luxor.AbstractPoint layer_objects::Vector{AbstractObject} actions::Vector{AbstractAction} current_setting::LayerSetting @@ -40,7 +40,7 @@ function Layer( frames, width, height, - position::PointOrDelayed; + position::Luxor.AbstractPoint; layer_objects::Vector{AbstractObject} = AbstractObject[], actions::Vector{AbstractAction} = AbstractAction[], setting::LayerSetting = LayerSetting(), diff --git a/test/delayed.jl b/test/delayed.jl index 6cb358415..e64dc4871 100644 --- a/test/delayed.jl +++ b/test/delayed.jl @@ -173,7 +173,7 @@ end o6 = Object( 100:200, JPoly( - Javis.PointOrDelayed[O, Javis.delayed_pos(o1), Javis.delayed_pos(o2)], + Luxor.AbstractPoint[O, Javis.delayed_pos(o1), Javis.delayed_pos(o2)], color = "navyblue", action = :stroke, linewidth = 10, From f1fb9e22973c53fa7260a950b1df6ea3f7fb1b64 Mon Sep 17 00:00:00 2001 From: gpucce Date: Thu, 24 Feb 2022 19:23:34 +0100 Subject: [PATCH 28/36] format --- src/shorthands/JEllipse.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shorthands/JEllipse.jl b/src/shorthands/JEllipse.jl index 30361faa9..2271e0617 100644 --- a/src/shorthands/JEllipse.jl +++ b/src/shorthands/JEllipse.jl @@ -1,4 +1,11 @@ -function _JEllipse(cpt::Luxor.AbstractPoint, w::Real, h::Real, color, linewidth, action::Symbol) +function _JEllipse( + cpt::Luxor.AbstractPoint, + w::Real, + h::Real, + color, + linewidth, + action::Symbol, +) sethue(color) setline(linewidth) cpt = get_position(cpt) From e0b6cb78b18285d0ab44da5debcb5aff97139740 Mon Sep 17 00:00:00 2001 From: gpucce Date: Fri, 25 Feb 2022 19:04:05 +0100 Subject: [PATCH 29/36] Minor changes --- src/shorthands/JPoly.jl | 4 ++-- src/structs/Delayed.jl | 40 +++++++++++----------------------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/src/shorthands/JPoly.jl b/src/shorthands/JPoly.jl index 33338f40a..932262f29 100644 --- a/src/shorthands/JPoly.jl +++ b/src/shorthands/JPoly.jl @@ -18,13 +18,13 @@ Draw a polygon around points in the pointlist. - `reversepath` can be set to `true` to reverse the path and create a polygon hole """ JPoly( - pointlist::Vector{Luxor.AbstractPoint}; + pointlist::Vector{T}; color = "black", linewidth = 2, action = :stroke, close = true, reversepath = false, -) = +) where {T<:Luxor.AbstractPoint} = ( args...; pointlist = pointlist, diff --git a/src/structs/Delayed.jl b/src/structs/Delayed.jl index 3ce5e7dc6..7f0a40730 100644 --- a/src/structs/Delayed.jl +++ b/src/structs/Delayed.jl @@ -11,38 +11,20 @@ mutable struct DelayedPosition <: Luxor.AbstractPoint called::Bool end -import Base: +, - +import Base: +, -, *, / +import Luxor: distance +*(k::Number, dp::DelayedPosition) = DelayedPosition(dp.obj, k * get_position(dp), dp.called) +*(dp::DelayedPosition, k::Number) = *(k, dp) +/(dp::DelayedPosition, k::Number) = DelayedPosition(dp.obj, get_position(dp) / k, dp.called) -(dp::DelayedPosition) = DelayedPosition(dp.obj, -get_position(dp), dp.called) - -function +(dp::DelayedPosition, p::Point) - DelayedPosition(dp.obj, get_position(dp) + p, dp.called) -end - +-(dp::DelayedPosition, p::Point) = DelayedPosition(dp.obj, get_position(dp) - p, dp.called) +-(p::Point, dp::DelayedPosition) = DelayedPosition(dp.obj, p - get_position(dp), dp.called) ++(dp::DelayedPosition, p::Point) = DelayedPosition(dp.obj, get_position(dp) + p, dp.called) +(p::Point, dp::DelayedPosition) = +(dp, p) -function -(dp::DelayedPosition, p::Point) - return DelayedPosition(dp.obj, get_position(dp) - p, dp.called) -end - -function -(p::Point, dp::DelayedPosition) - return DelayedPosition(dp.obj, p - get_position(dp), dp.called) -end +translate(pos::DelayedPosition) = translate(get_position(pos)) -function translate(pos::DelayedPosition) - return translate(get_position(pos)) +function distance(p1::T1, p2::T2) where {T1<:Luxor.AbstractPoint,T2<:Luxor.AbstractPoint} + return distance(get_position(p1), get_position(p2)) end - - -import Luxor: distance - -distance(dp1::DelayedPosition, dp2::DelayedPosition) = - distance(get_position(dp1), get_position(dp2)) - -function distance(dp::DelayedPosition, p::Point) - return distance(get_position(dp), p) -end - -distance(p::Point, dp::DelayedPosition) = distance(dp, p) - -Base.:/(dp::DelayedPosition, k::Number) = get_position(dp) / k From a309fb25547c205f36b724bff5f8abec0197245b Mon Sep 17 00:00:00 2001 From: gpucce Date: Sat, 26 Feb 2022 11:59:22 +0100 Subject: [PATCH 30/36] reenable some unit tests --- test/unit.jl | 122 +++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/test/unit.jl b/test/unit.jl index 54ce4433a..5d14f1e2b 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -27,7 +27,7 @@ video = Video(500, 500) Background(1:100, (args...) -> 1) # test objects matrix - objects = [Object(1:100, (args...) -> Point(1, 1)) for i in 1:9, j in 1:9] + objects = [Object(1:100, (args...) -> Point(1, 1)) for i = 1:9, j = 1:9] act!(objects, Action(1:100, anim_translate(Point(1, 1), Point(100, 100)))) Javis.preprocess_frames!(video.objects) @@ -301,64 +301,64 @@ end end - # @testset "anim_" begin - # s = anim_scale(1, 2) - # @test s.from == Javis.Scale(1, 1) - # @test s.to == Javis.Scale(2, 2) - - # s = anim_scale(Javis.Scale(1, 1), 2) - # @test s.from == Javis.Scale(1, 1) - # @test s.to == Javis.Scale(2, 2) - - # s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) - # @test s.from == Javis.Scale(1, 1) - # @test s.to == Javis.Scale(2, 2) - - # s = anim_scale((1, 1), Javis.Scale(2, 1)) - # @test s.from == Javis.Scale(1, 1) - # @test s.to == Javis.Scale(2, 1) - - # s = anim_scale(Javis.Scale(2, 1)) - # @test s.from == :current_scale - # @test s.to == Javis.Scale(2, 1) - # end - - # @testset "Test warning if background not defined" begin - # video = Video(100, 100) - # Background(1:10, (args...) -> 1) - # Object(1:11, (args...) -> 2) - # @test_logs (:warn,) render(video; pathname = "") - # end - - # @testset "Test warning if action outside frame range" begin - # video = Video(100, 100) - # Background(1:20, (args...) -> 1) - # act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) - # @test_logs (:warn,) render(video; pathname = "") - # end - - # @testset "Linear scale" begin - # scale_val = scale_linear(-10, 10, 10, -10) - # @test scale_val(-20) == 10 # clamped - # @test scale_val(-5) == 5 - # @test scale_val(20) == -10 - - # scale_val = scale_linear(-10, 10, 10, -10; clamp = false) - # @test scale_val(-20) == 20 # clamped - - # scale_val = - # scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) - # @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped - # @test scale_val(Point(-5, -7)) == Point(5, 7) - # @test scale_val(Point(20, -10)) == Point(-10, 10) - - # scale_val = scale_linear( - # Point(-10, -10), - # Point(10, 10), - # Point(10, 10), - # Point(-10, -10); - # clamp = false, - # ) - # @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped - # end + @testset "anim_" begin + s = anim_scale(1, 2) + @test s.from == Javis.Scale(1, 1) + @test s.to == Javis.Scale(2, 2) + + s = anim_scale(Javis.Scale(1, 1), 2) + @test s.from == Javis.Scale(1, 1) + @test s.to == Javis.Scale(2, 2) + + s = anim_scale(Javis.Scale(1, 1), Javis.Scale(2, 2)) + @test s.from == Javis.Scale(1, 1) + @test s.to == Javis.Scale(2, 2) + + s = anim_scale((1, 1), Javis.Scale(2, 1)) + @test s.from == Javis.Scale(1, 1) + @test s.to == Javis.Scale(2, 1) + + s = anim_scale(Javis.Scale(2, 1)) + @test s.from == :current_scale + @test s.to == Javis.Scale(2, 1) + end + + @testset "Test warning if background not defined" begin + video = Video(100, 100) + Background(1:10, (args...) -> 1) + Object(1:11, (args...) -> 2) + @test_logs (:warn,) render(video; pathname = "") + end + + @testset "Test warning if action outside frame range" begin + video = Video(100, 100) + Background(1:20, (args...) -> 1) + act!(Object(1:11, (args...) -> 2), Action(1:20, anim_translate(0, 10))) + @test_logs (:warn,) render(video; pathname = "") + end + + @testset "Linear scale" begin + scale_val = scale_linear(-10, 10, 10, -10) + @test scale_val(-20) == 10 # clamped + @test scale_val(-5) == 5 + @test scale_val(20) == -10 + + scale_val = scale_linear(-10, 10, 10, -10; clamp = false) + @test scale_val(-20) == 20 # clamped + + scale_val = + scale_linear(Point(-10, -10), Point(10, 10), Point(10, 10), Point(-10, -10)) + @test scale_val(Point(-20, -10)) == Point(10, 10) # clamped + @test scale_val(Point(-5, -7)) == Point(5, 7) + @test scale_val(Point(20, -10)) == Point(-10, 10) + + scale_val = scale_linear( + Point(-10, -10), + Point(10, 10), + Point(10, 10), + Point(-10, -10); + clamp = false, + ) + @test scale_val(Point(-20, -10)) == Point(20, 10) # clamped + end end From dfe7d4985a1d551a9ca6880dfaaba736379dffc4 Mon Sep 17 00:00:00 2001 From: gpucce Date: Sat, 26 Feb 2022 12:03:04 +0100 Subject: [PATCH 31/36] format --- test/unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit.jl b/test/unit.jl index 5d14f1e2b..1b0ffdd53 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -27,7 +27,7 @@ video = Video(500, 500) Background(1:100, (args...) -> 1) # test objects matrix - objects = [Object(1:100, (args...) -> Point(1, 1)) for i = 1:9, j = 1:9] + objects = [Object(1:100, (args...) -> Point(1, 1)) for i in 1:9, j in 1:9] act!(objects, Action(1:100, anim_translate(Point(1, 1), Point(100, 100)))) Javis.preprocess_frames!(video.objects) From dce3bda271710df67f2d33b629e0f73d07ab92b1 Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 2 Mar 2022 10:05:18 +0100 Subject: [PATCH 32/36] export get_delayed_position --- src/Javis.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Javis.jl b/src/Javis.jl index fc700eb17..0be143ca2 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -738,6 +738,7 @@ export Video, Object, Background, Action, RFrames, GFrames export @JLayer, background export Line, Transformation export val, pos, ang, scl, get_value, get_position, get_angle, get_scale +export get_delayed_position, delayed_pos export projection, morph_to export appear, disappear, rotate_around, follow_path, change export rev From 9a24a21a497272edceaa587f0f3ba8ff2ae33dba Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 2 Mar 2022 10:05:57 +0100 Subject: [PATCH 33/36] fix types --- src/structs/Transitions.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/structs/Transitions.jl b/src/structs/Transitions.jl index d433667b2..11b06f763 100644 --- a/src/structs/Transitions.jl +++ b/src/structs/Transitions.jl @@ -5,8 +5,8 @@ =# struct Translation <: AbstractTransition - from::Union{Object,Point,DelayedPosition} - to::Union{Object,Point,DelayedPosition} + from::Union{Object,Luxor.AbstractPoint} + to::Union{Object,Luxor.AbstractPoint} end """ @@ -30,8 +30,8 @@ act!(obj, Action(1:50, anim_translate(10, 10))) anim_translate(x::Real, y::Real) = anim_translate(Point(x, y)) anim_translate(tp::Point) = Translation(O, tp) anim_translate( - fp::Union{Object,Point,DelayedPosition}, - tp::Union{Object,Point,DelayedPosition}, + fp::Union{Object,Luxor.AbstractPoint}, + tp::Union{Object,Luxor.AbstractPoint}, ) = Translation(fp, tp) struct Rotation{T<:Real} <: AbstractTransition From a20bd275f3a92ebf5f43965a64134428b4e83b8c Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 2 Mar 2022 10:08:40 +0100 Subject: [PATCH 34/36] add docs to centered_point --- src/Javis.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Javis.jl b/src/Javis.jl index 0be143ca2..9b296dac9 100644 --- a/src/Javis.jl +++ b/src/Javis.jl @@ -135,6 +135,13 @@ function centered_point(pos::Point, width::Int, height::Int) Point(pos.x - width / 2, pos.y - height / 2) end +""" + centered_point + +Dispatch centered_point to DelayedPosition to adjust layer position. +# Returns +- `dp::DelayedPosition`: the "delayed" location of the center of a layers wrt global canvas. +""" function centered_point(pos::DelayedPosition, width::Int, height::Int) Point(get_position(pos).x - width / 2, get_position(pos).y - height / 2) end From 0b702a1d2ab0c5e42c43fc57892c901f0f02e32a Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 2 Mar 2022 10:11:52 +0100 Subject: [PATCH 35/36] fix example in howto.md --- docs/src/howto.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/src/howto.md b/docs/src/howto.md index d37c60428..8e3d6a0d4 100644 --- a/docs/src/howto.md +++ b/docs/src/howto.md @@ -235,6 +235,7 @@ Both `get_position` and `pos` are a bit unintuitive in the sense that one may th vid = Video(500, 500) Background(1:50, (args...)->background("black")) o1 = Object(JCircle(O, 10, action=:fill)) +o2 = Object(JCircle(pos(o1), 5, action=:fill)) render(vid) ``` @@ -264,6 +265,6 @@ Background(1:50, (args...)->background("black")) o1 = Object(JCircle(O, 10, action=:fill, color="red")) # it works with or w/o this line and the effect changes coherently!!! act!(o1, Action(anim_translate(Point(100, 0)))) -o2 = Object(25:50, JCircle(Javis.get_delayed_position(o1), 5, action=:fill, color="blue")) -embed(vid) +o2 = Object(25:50, JCircle(delayed_pos(o1), 5, action=:fill, color="blue")) +render(vid) ``` From 207f03b23a2428fcdae2b0fd0ea48abedd6ec859 Mon Sep 17 00:00:00 2001 From: gpucce Date: Wed, 9 Mar 2022 12:22:19 +0100 Subject: [PATCH 36/36] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eee3c8bf..413e77d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ##for PR - change font scaling in svg2luxor from 1/2 to 425/1000 - change default line width to 2.0 like luxor +- add `get_delayed_position` and `delayed_pos` ## v0.8.0 (1st of February 2022) - Allow Luxor v3.0