From b5d7ee0752ee1f2dddf1da4ac817f138296e1c96 Mon Sep 17 00:00:00 2001 From: Anthony Taormina Date: Tue, 3 Dec 2024 01:54:08 -0600 Subject: [PATCH] feat: Add baseColor to Shadow3DDecorator (#3375) The Shadow3DDecorator is very useful, but the shadow defaults to being pure black. While this is fine in most cases, sometimes a designer might request something a little bit different, so this change to allow the base color of the shadow to be changed if so desired. --- .../lib/src/rendering/shadow3d_decorator.dart | 17 ++++++++++++++--- .../test/_goldens/shadow3d_decorator_2.png | Bin 1655 -> 1663 bytes .../test/_goldens/shadow3d_decorator_3.png | Bin 1364 -> 1368 bytes .../rendering/shadow3d_decorator_test.dart | 5 ++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/flame/lib/src/rendering/shadow3d_decorator.dart b/packages/flame/lib/src/rendering/shadow3d_decorator.dart index a8849f33d50..ff03b2c7c0e 100644 --- a/packages/flame/lib/src/rendering/shadow3d_decorator.dart +++ b/packages/flame/lib/src/rendering/shadow3d_decorator.dart @@ -1,7 +1,8 @@ import 'dart:ui'; +import 'package:flame/src/palette.dart'; import 'package:flame/src/rendering/decorator.dart'; -import 'package:vector_math/vector_math_64.dart'; +import 'package:vector_math/vector_math_64.dart' show Matrix4, Vector2; /// [Shadow3DDecorator] casts a realistic-looking shadow from the component /// onto the ground. @@ -24,13 +25,15 @@ class Shadow3DDecorator extends Decorator { double? yScale, double? blur, double? opacity, + Color? baseColor, }) : _base = base?.clone() ?? Vector2.zero(), _ascent = ascent ?? 0, _angle = angle ?? -1.4, _shift = xShift ?? 100.0, _scale = yScale ?? 1.0, _blur = blur ?? 0, - _opacity = opacity ?? 0.6; + _opacity = opacity ?? 0.6, + _baseColor = baseColor ?? BasicPalette.black.color; /// Coordinates of the point where the component "touches the ground". If the /// component is airborne (i.e. [ascent] is non-zero), then this should be the @@ -117,10 +120,18 @@ class Shadow3DDecorator extends Decorator { _paint = null; } + /// Shadow's base color before opacity. This defaults to pitch-black. + Color get baseColor => _baseColor; + Color _baseColor; + set baseColor(Color value) { + _baseColor = value; + _paint = null; + } + Paint? _paint; Paint _makePaint() { final paint = Paint(); - final color = Color.fromRGBO(0, 0, 0, opacity); + final color = baseColor.withOpacity(opacity); paint.colorFilter = ColorFilter.mode(color, BlendMode.srcIn); if (_blur > 0) { paint.imageFilter = ImageFilter.blur(sigmaX: blur, sigmaY: blur / _scale); diff --git a/packages/flame/test/_goldens/shadow3d_decorator_2.png b/packages/flame/test/_goldens/shadow3d_decorator_2.png index cc906b513ce0da8d12fd33a4a17b6a48297c583f..f4ac453ddc4716f6b52a44a30cd75939e08771e0 100644 GIT binary patch delta 1258 zcmVYTgUmC?JPY$CvWo@@ zNsxhkb)>Rr`olB=@jfR$9>np%?Kf3dMbXjs@83@bd{Vsh3&3-co*|K*5Ehbj=@)Qs zfBpB*(l6nz{{7?coBn>RlMw;UlW+k&f22#lfUkBsoqqXYc3S#neX+>@vE%V*Q50De zMK}4KR~wAS(f7UeeQ#~sTGw^f_uY?NPHT)NvL9Xi_&JIqYunb6B(XS-EslSGLs?xg z<50S;v%}$FbzNK2G*;KOeQW;w8BRZ1ah_WgMHa`gB}rnN&BpRPx3Vm)C<^Pke{T5q zr_<@TSDIA?b37jHcsyFyb=J16)pc#V-Ok?M-)+C&+kU^d!{K0E*A2h+*?A0Unhv2P zNizAfc_g>kmR1qW>2#We(lm|jcDqR|bzM(ldG^)C=aM*%ZL`@7t4mQ7!|IafxotKZ zi{qFX#zvv|jM6lX?f3g3mfdbQe_2(08}k45S$Ql;l312yRuqM8w_Dq8xAyk-W>r;L zQ4~W+x0qerQw9^xDL$Y0isGR(O=E4_PPU(C55>%eEhx(}E6Z{SWxL&4RaKVfxut1( zvq5+4>4F*0DL&AK+fUOpb~qfY@B3ARVl!Ki&ns_lZ^NommZfD`HpFtPe{E>&X@c>& zBOGYw<`fU*+2<4&Zb5mT&u&3kmRXV{H$8U=J$x|d<`mz0cDvnVpk3SJvISd^&nv#N zlw~;?Zg0H>g&sDTxjDrLT93ugSJpJAxbYS=eq{Dgw%hGpwxH0%1>>QN=M+Cf8LuiH z%9`dBH{OE$QMszB$#CmWe?e)Qe(4qzdZ=K0mFW9^7-+*)B^+qivi-R6sqNercf zjk^bPZcYgYT7OKQ-eXyhxh=>~ZGB}4x1gnCv3mydnK@-`ZxEg{cWOH~ulPaSQuE53 zFAv85(z~v^c%HK6ImOMraX7aH`5T8z&MR}iESR~AOyhTw{W$+{IIMn7u?KnM@D{!# zn2#A%+f6bxTnN!SlKVNx9e;0#!^@~iGgr~OtF^{>s zwvTpddyTWfaFOY$boZ4Pv5)2oaE_;-Zdn_e2E;4=EBYoUsDe1XY zW$xh3KmDI1$aX?{I&8QuMmn$$A8%IzWeHtoHGvNRU#RiJXXK@7Xz2AbCk!Ik)9!uo*owDf6n~F UiVoPl>;M1&07*qoM6N<$f~Go($N&HU delta 1264 zcmVK}{h^L_t(|obB9Aa^hALhT)_CA6P{;l@(+KnP-rB7S@}{F0dpd zL3UIq)3UIq&p zgkT^^mwp5H_UFHUFZ~wo>Yv~Ky6N}h3X$>dlTZO0e@VLZ8~AR=!GzM!lwm@t%K7;L}aTi12gwym{oYk%y2x4!Rf97h|+ap|{vGjSYSk|dVrxfMlW zWm#HPe^oXNgGEtfaU9$6c>Lun&8mX&2o8sX?e}|Y+t%LR-lkXEw$^psbk#Yo;40%W zq-kn-o?BH_7RRyWc|QI7Jd#^1OREUxcs$xTjy4Q~^?h$$*PVpovF!Kz)y0w|iDg+f zMdDYMs;aCgis@_2FhMBeIG!v$yWQ?XD83Axe-6IS$%oi*3EFHnw%u-Rv)Nc(*H)IL zWmz`OFSqiP!OZ6r59RIcZHlF7nkf{&qC9&jc3}ys>-r>?q9`m))0+*tp{EPRuP8py zwry)o)7Wmev)yiIP19J{byFyQRapbSs-$UZMNwE?*VC1yu4}8R%JMv)V!72a6ndIq zfBYBkb4nOWxcvC-^V&iQ=asT7Pp&GP&BltNusqK#Ns^oHyUaa&Fg~aFUP{+>)-=t@ z^5b(#7|NPr32&LJs+uC%ZnqzX+gmR|a}OKLxjDr{@s}?@?;CRKnNys{l4Y6Yd4944 zZ8n>`EJ1S*7mWYX=X1(@pk3>n;{2+Te`VP;uWYy5Xzv~Jm+yB$Wm$f>WxnSUH1`m}T$)qP?We49PI2Kab5Ru2yb>-!;VtvMt}3BLg9+!9 zzVB_n-=7_5*F2}V@GdA^f_%XBB`8hPyDmXt32 z(lovKuI*RcJ(zP32*c&)73LIoZrAo_OVHA>*gb=p&nX_te4zC?Wi1Z~FPSevRaKoV zL4M2ZSCyrfpt)}kW*Nz?d|9UVC!}RI@BuSQj-;402#pjhUmV1BPV<~Ak-1_q!zk-Ax^nS%TWzJ_7 zzqZm((u26Oz>&n%q+_?tLyqD9uR(3xPu$M{P^S=m!P@S{{KPDH=e>7 z<<)};BM5(1{(6N_TpIpk!*%!7Be^6D<5eOFo!nNx`VRxwt#g#ex065yDU)6X3zJ?3 a3>80=p{1qGQ1__-0000%S}7QfP<`?^*#%LpX#?a~o}Lsh7W(Jzca2_Nq&#o?S@j7+ zWoKtfW-}$Lm9n!l6{FE!e)Pcy6C{bE$4ABUx#Hzg;oF;36m37NK4GZr^i;{!m6F+P zud(Q$gDDDy>$ReX2gUQbqK5~C>-FKsa&n?{I;|xZ9c(Z~q44cZ@p7qnu~2`sS}919 zwqI4RAW(jMyou%dTG{!zifI4;yayLdkmm|tUKHQmDPAlzdU{fjWo(hauk3#? zLmaoId^}cqdAZpv7Z=KFjzxdH4`w@V@9#IU3}M`s@}r|oEH^hwx3L64?Z3CT!3=WT zmWuIM*~P_Xvs_*(ACDV}MSTrskmI&g#Ie$g3$0s-MSTorkmI(rjpgSj%h6Gzv8Y$U z40zm1QV~T;Cle*t*Gi^S<;Ta3$D-Z@GvINnGL~#IQ8Jq;olaZ%WZ8e}d@wkYyS@KYxtd=jXwUTWw?6o+(^iDL*+; z(PAv>axg<4x00mMNO{L%Q73~L__&pJZ(7pXO!?{Q-p>@it6RYgeB4U)A3#;rnP7%K zZlz`ppsMObFhd`=QgeR?P*t`5q99EbtyY^@mP>`Nufy6aYW4uCs`g&RxZP;@0II5X zUdFiHXyE{=s>Xw1+?(YXZZq?BPsH*l8%&+5iu~78zFz9hBb@u?O zs>;DIZa>lC1E{Jh1;e=gM8^-Hs`_>?jN4E2-~g&BKN!aC=X!DgRh9P_6@|k0cSZO2 z8gIY3U9W3=m4s!um4qfuF>0@qUBQK`Ft~O)3nyd^+L}MpsM=%UsjH}?DSOc qKYrBuD0Elu+&G!Sv`aZKia2Yu^WVlS1 zn-b6 N|$vd`u|(-HqGoJV<&cCWIrwRL6Mw_?^;<^UZQX6}OroD4Py@DRxiI{%9? z^Y`oh^_%LPR{i_??R#jw-2TJ_MTrOwHnFD0)`U?e+q9}{{2qrtR$MuKy8Dp9mHC(L zx5TY4wVJ!BE-Y!))m87_y)%*O-4dZwQeM71YHiun`L&-9zWH9QJKdYraly@;WpB$? zYji;s@4CCL?eIdk#TP@9FY2-jyG|_IJ@?t?olOcCYV5A(ZQuPf!fI|GTeG9m#us7D zor^qfzYW`b(-1D z&E6XI>ih3mK5FkbhG-@i-sAD7}`%i4Z>AB%@0ngy`#01dBu(*L9n0=Q1G+3EFZhB7nrUkFsyJ!mk zf=8#`g!bHif5{H0Wb$;wy#1#iF=(y3(wunb--M%#Au%i24)6H;@UgG=EcSrHrDA6u z7VP+OIu{taH-DO+PBA+9WSMH;5l{sG{`)WK&c1#7rkPE%xwGZS#0-O;+upAIuAV>x z_D-1&bc_&ZTVb`PKhT_5TZvns)wE4TEU-ngogM^Pm0&I`TeWTjB3WLB0i#Hi4WQ6$oPO z3lwp!s;%Ao5y?zyC{%vouaSy_B!rdDD9BhDAUJe0`c< xCRcnnFTB6M|KvWdouPm1c@#oPE`C1Q|GN93XzJX_$-t74!PC{xWt~$(699oSRCoXY diff --git a/packages/flame/test/rendering/shadow3d_decorator_test.dart b/packages/flame/test/rendering/shadow3d_decorator_test.dart index 6e587deadeb..24dc7c2cedf 100644 --- a/packages/flame/test/rendering/shadow3d_decorator_test.dart +++ b/packages/flame/test/rendering/shadow3d_decorator_test.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:flame/components.dart'; +import 'package:flame/palette.dart'; import 'package:flame/rendering.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -16,6 +17,7 @@ void main() { expect(decorator.yScale, 1.0); expect(decorator.blur, 0.0); expect(decorator.opacity, 0.6); + expect(decorator.baseColor, BasicPalette.black.color); }); testGolden( @@ -79,7 +81,8 @@ void main() { ..xShift = 250.0 ..yScale = 1.5 ..opacity = 0.4 - ..blur = 1.0, + ..blur = 1.0 + ..baseColor = BasicPalette.red.color, ), ]); },