From 1fdbe05905995641f02b4c4c3b2d7e27be6ecf3a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 11 Sep 2023 17:21:38 +0200 Subject: [PATCH] Photoshop: fixed blank Flatten image (#5600) * OP-6763 - refresh all visible for Flatten image Previously newly added layers were missing. * OP-6763 - added explicit image collector Creator was adding 'layer' metadata from workfile only during collect_instances, it was missing for newly added layers. This should be cleaner approach * OP-6763 - removed unnecessary method overwrite Creator is not adding layer to instance, separate collector created. * OP-6763 - cleanup of names Was failing when template for subset name for image family contained {layer} * OP-6763 - cleanup, removed adding layer metadata Separate collector created, cleaner. Fixed propagation of mark_for_review * OP-6763 - using members instead of layer data Members should be more reliable. * OP-6763 - updated image from Settings Explicit subset name template was removed some time ago as confusing. * OP-6763 - added explicit local plugin Automated plugin has different logic, local would need to handle if auto_image is disabled by artist * OP-6763 - Hound * OP-6345 - fix - review for image family Image family instance contained flattened content. Now it reuses previously extracted file without need to re-extract. --- .../plugins/create/create_flatten_image.py | 40 +++++++++--- .../photoshop/plugins/create/create_image.py | 17 ++--- .../publish/collect_auto_image_refresh.py | 24 +++++++ .../plugins/publish/collect_image.py | 20 ++++++ .../plugins/publish/extract_image.py | 8 ++- .../plugins/publish/extract_review.py | 59 +++++++++++++++--- website/docs/admin_hosts_photoshop.md | 7 +-- .../assets/admin_hosts_photoshop_settings.png | Bin 14364 -> 16718 bytes 8 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 openpype/hosts/photoshop/plugins/publish/collect_auto_image_refresh.py create mode 100644 openpype/hosts/photoshop/plugins/publish/collect_image.py diff --git a/openpype/hosts/photoshop/plugins/create/create_flatten_image.py b/openpype/hosts/photoshop/plugins/create/create_flatten_image.py index 9d4189a1a3..e4229788bd 100644 --- a/openpype/hosts/photoshop/plugins/create/create_flatten_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_flatten_image.py @@ -4,6 +4,7 @@ from openpype.lib import BoolDef import openpype.hosts.photoshop.api as api from openpype.hosts.photoshop.lib import PSAutoCreator from openpype.pipeline.create import get_subset_name +from openpype.lib import prepare_template_data from openpype.client import get_asset_by_name @@ -37,19 +38,14 @@ class AutoImageCreator(PSAutoCreator): asset_doc = get_asset_by_name(project_name, asset_name) if existing_instance is None: - subset_name = get_subset_name( - self.family, self.default_variant, task_name, asset_doc, + subset_name = self.get_subset_name( + self.default_variant, task_name, asset_doc, project_name, host_name ) - publishable_ids = [layer.id for layer in api.stub().get_layers() - if layer.visible] data = { "asset": asset_name, "task": task_name, - # ids are "virtual" layers, won't get grouped as 'members' do - # same difference in color coded layers in WP - "ids": publishable_ids } if not self.active_on_create: @@ -69,8 +65,8 @@ class AutoImageCreator(PSAutoCreator): existing_instance["asset"] != asset_name or existing_instance["task"] != task_name ): - subset_name = get_subset_name( - self.family, self.default_variant, task_name, asset_doc, + subset_name = self.get_subset_name( + self.default_variant, task_name, asset_doc, project_name, host_name ) @@ -118,3 +114,29 @@ class AutoImageCreator(PSAutoCreator): Artist might disable this instance from publishing or from creating review for it though. """ + + def get_subset_name( + self, + variant, + task_name, + asset_doc, + project_name, + host_name=None, + instance=None + ): + dynamic_data = prepare_template_data({"layer": "{layer}"}) + subset_name = get_subset_name( + self.family, variant, task_name, asset_doc, + project_name, host_name, dynamic_data=dynamic_data + ) + return self._clean_subset_name(subset_name) + + def _clean_subset_name(self, subset_name): + """Clean all variants leftover {layer} from subset name.""" + dynamic_data = prepare_template_data({"layer": "{layer}"}) + for value in dynamic_data.values(): + if value in subset_name: + return (subset_name.replace(value, "") + .replace("__", "_") + .replace("..", ".")) + return subset_name diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index 8d3ac9f459..af20d456e0 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -94,12 +94,17 @@ class ImageCreator(Creator): name = self._clean_highlights(stub, directory) layer_names_in_hierarchy.append(name) - data.update({"subset": subset_name}) - data.update({"members": [str(group.id)]}) - data.update({"layer_name": layer_name}) - data.update({"long_name": "_".join(layer_names_in_hierarchy)}) + data_update = { + "subset": subset_name, + "members": [str(group.id)], + "layer_name": layer_name, + "long_name": "_".join(layer_names_in_hierarchy) + } + data.update(data_update) - creator_attributes = {"mark_for_review": self.mark_for_review} + mark_for_review = (pre_create_data.get("mark_for_review") or + self.mark_for_review) + creator_attributes = {"mark_for_review": mark_for_review} data.update({"creator_attributes": creator_attributes}) if not self.active_on_create: @@ -124,8 +129,6 @@ class ImageCreator(Creator): if creator_id == self.identifier: instance_data = self._handle_legacy(instance_data) - layer = api.stub().get_layer(instance_data["members"][0]) - instance_data["layer"] = layer instance = CreatedInstance.from_existing( instance_data, self ) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_auto_image_refresh.py b/openpype/hosts/photoshop/plugins/publish/collect_auto_image_refresh.py new file mode 100644 index 0000000000..741fb0e9cd --- /dev/null +++ b/openpype/hosts/photoshop/plugins/publish/collect_auto_image_refresh.py @@ -0,0 +1,24 @@ +import pyblish.api + +from openpype.hosts.photoshop import api as photoshop + + +class CollectAutoImageRefresh(pyblish.api.ContextPlugin): + """Refreshes auto_image instance with currently visible layers.. + """ + + label = "Collect Auto Image Refresh" + order = pyblish.api.CollectorOrder + hosts = ["photoshop"] + order = pyblish.api.CollectorOrder + 0.2 + + def process(self, context): + for instance in context: + creator_identifier = instance.data.get("creator_identifier") + if creator_identifier and creator_identifier == "auto_image": + self.log.debug("Auto image instance found, won't create new") + # refresh existing auto image instance with current visible + publishable_ids = [layer.id for layer in photoshop.stub().get_layers() # noqa + if layer.visible] + instance.data["ids"] = publishable_ids + return diff --git a/openpype/hosts/photoshop/plugins/publish/collect_image.py b/openpype/hosts/photoshop/plugins/publish/collect_image.py new file mode 100644 index 0000000000..64727cef33 --- /dev/null +++ b/openpype/hosts/photoshop/plugins/publish/collect_image.py @@ -0,0 +1,20 @@ +import pyblish.api + +from openpype.hosts.photoshop import api + + +class CollectImage(pyblish.api.InstancePlugin): + """Collect layer metadata into a instance. + + Used later in validation + """ + order = pyblish.api.CollectorOrder + 0.200 + label = 'Collect Image' + + hosts = ["photoshop"] + families = ["image"] + + def process(self, instance): + if instance.data.get("members"): + layer = api.stub().get_layer(instance.data["members"][0]) + instance.data["layer"] = layer diff --git a/openpype/hosts/photoshop/plugins/publish/extract_image.py b/openpype/hosts/photoshop/plugins/publish/extract_image.py index cdb28c742d..680f580cc0 100644 --- a/openpype/hosts/photoshop/plugins/publish/extract_image.py +++ b/openpype/hosts/photoshop/plugins/publish/extract_image.py @@ -45,9 +45,11 @@ class ExtractImage(pyblish.api.ContextPlugin): # Perform extraction files = {} ids = set() - layer = instance.data.get("layer") - if layer: - ids.add(layer.id) + # real layers and groups + members = instance.data("members") + if members: + ids.update(set([int(member) for member in members])) + # virtual groups collected by color coding or auto_image add_ids = instance.data.pop("ids", None) if add_ids: ids.update(set(add_ids)) diff --git a/openpype/hosts/photoshop/plugins/publish/extract_review.py b/openpype/hosts/photoshop/plugins/publish/extract_review.py index 4aa7a05bd1..afddbdba31 100644 --- a/openpype/hosts/photoshop/plugins/publish/extract_review.py +++ b/openpype/hosts/photoshop/plugins/publish/extract_review.py @@ -1,4 +1,5 @@ import os +import shutil from PIL import Image from openpype.lib import ( @@ -55,6 +56,7 @@ class ExtractReview(publish.Extractor): } if instance.data["family"] != "review": + self.log.debug("Existing extracted file from image family used.") # enable creation of review, without this jpg review would clash # with jpg of the image family output_name = repre_name @@ -62,8 +64,15 @@ class ExtractReview(publish.Extractor): repre_skeleton.update({"name": repre_name, "outputName": output_name}) - if self.make_image_sequence and len(layers) > 1: - self.log.info("Extract layers to image sequence.") + img_file = self.output_seq_filename % 0 + self._prepare_file_for_image_family(img_file, instance, + staging_dir) + repre_skeleton.update({ + "files": img_file, + }) + processed_img_names = [img_file] + elif self.make_image_sequence and len(layers) > 1: + self.log.debug("Extract layers to image sequence.") img_list = self._save_sequence_images(staging_dir, layers) repre_skeleton.update({ @@ -72,17 +81,17 @@ class ExtractReview(publish.Extractor): "fps": fps, "files": img_list, }) - instance.data["representations"].append(repre_skeleton) processed_img_names = img_list else: - self.log.info("Extract layers to flatten image.") - img_list = self._save_flatten_image(staging_dir, layers) + self.log.debug("Extract layers to flatten image.") + img_file = self._save_flatten_image(staging_dir, layers) repre_skeleton.update({ - "files": img_list, + "files": img_file, }) - instance.data["representations"].append(repre_skeleton) - processed_img_names = [img_list] + processed_img_names = [img_file] + + instance.data["representations"].append(repre_skeleton) ffmpeg_args = get_ffmpeg_tool_args("ffmpeg") @@ -111,6 +120,35 @@ class ExtractReview(publish.Extractor): self.log.info(f"Extracted {instance} to {staging_dir}") + def _prepare_file_for_image_family(self, img_file, instance, staging_dir): + """Converts existing file for image family to .jpg + + Image instance could have its own separate review (instance per layer + for example). This uses extracted file instead of extracting again. + Args: + img_file (str): name of output file (with 0000 value for ffmpeg + later) + instance: + staging_dir (str): temporary folder where extracted file is located + """ + repre_file = instance.data["representations"][0] + source_file_path = os.path.join(repre_file["stagingDir"], + repre_file["files"]) + if not os.path.exists(source_file_path): + raise RuntimeError(f"{source_file_path} doesn't exist for " + "review to create from") + _, ext = os.path.splitext(repre_file["files"]) + if ext != ".jpg": + im = Image.open(source_file_path) + # without this it produces messy low quality jpg + rgb_im = Image.new("RGBA", (im.width, im.height), "#ffffff") + rgb_im.alpha_composite(im) + rgb_im.convert("RGB").save(os.path.join(staging_dir, img_file)) + else: + # handles already .jpg + shutil.copy(source_file_path, + os.path.join(staging_dir, img_file)) + def _generate_mov(self, ffmpeg_path, instance, fps, no_of_frames, source_files_pattern, staging_dir): """Generates .mov to upload to Ftrack. @@ -218,6 +256,11 @@ class ExtractReview(publish.Extractor): (list) of PSItem """ layers = [] + # creating review for existing 'image' instance + if instance.data["family"] == "image" and instance.data.get("layer"): + layers.append(instance.data["layer"]) + return layers + for image_instance in instance.context: if image_instance.data["family"] != "image": continue diff --git a/website/docs/admin_hosts_photoshop.md b/website/docs/admin_hosts_photoshop.md index de684f01d2..d79789760e 100644 --- a/website/docs/admin_hosts_photoshop.md +++ b/website/docs/admin_hosts_photoshop.md @@ -33,7 +33,6 @@ Provides list of [variants](artist_concepts.md#variant) that will be shown to an Provides simplified publishing process. It will create single `image` instance for artist automatically. This instance will produce flatten image from all visible layers in a workfile. -- Subset template for flatten image - provide template for subset name for this instance (example `imageBeauty`) - Review - should be separate review created for this instance ### Create Review @@ -111,11 +110,11 @@ Set Byte limit for review file. Applicable if gigantic `image` instances are pro #### Extract jpg Options -Handles tags for produced `.jpg` representation. `Create review` and `Add review to Ftrack` are defaults. +Handles tags for produced `.jpg` representation. `Create review` and `Add review to Ftrack` are defaults. #### Extract mov Options -Handles tags for produced `.mov` representation. `Create review` and `Add review to Ftrack` are defaults. +Handles tags for produced `.mov` representation. `Create review` and `Add review to Ftrack` are defaults. ### Workfile Builder @@ -124,4 +123,4 @@ Allows to open prepared workfile for an artist when no workfile exists. Useful t Could be configured per `Task type`, eg. `composition` task type could use different `.psd` template file than `art` task. Workfile template must be accessible for all artists. -(Currently not handled by [SiteSync](module_site_sync.md)) \ No newline at end of file +(Currently not handled by [SiteSync](module_site_sync.md)) diff --git a/website/docs/assets/admin_hosts_photoshop_settings.png b/website/docs/assets/admin_hosts_photoshop_settings.png index aaa6ecbed7b353733f8424abe3c2df0cb903935a..9478fbedf785ca8ae66132a14cb400c38e2dccc9 100644 GIT binary patch literal 16718 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 literal 14364 zcmc(Gd03KZ+xOix*{-cZxwTBI=2DYeDDAfDIF(B(gr-)mq_~1qR+b{vG^XWNIa5t8 zxa5jRxj<&Zm?M*q5VGtz;|>2nDud<0r-i_$KjRWpII?KyX^(an5M(vKi`M$ zIlcz~Do6{bQFFlm=SLs%jR63|7X8mGM%2@@0N_w@c>kW02?!}S;6}(~exLfxvNX&u zndrT1zTbD%E2`*rT!?ae*U`Ykp3-w$N_(F=>@@sU6zKOD`n2c1f#*p0hkgUuuP#4c zK=w)B+owK%ue@S|U3wX}mOn4|xV5pB0eNntxoy2&{r1*dSN-#*@uE+OOedBsu{i0O z<_{6pz%`Z~!<;PCIraRE*YHJ&Q}6`&CmSySu-$1f^=i}Ht9Afz=Q$dRmvCs#ihDNL z#Q-q+TL~uB)&My3b7k-1W+-s!aQkV8c|icMaYGn)4Ph3L^XtELKs<~f^M-ivOABB) zpZwoAg=x6FsMU0-dVQQR)xNdx64@NnT#>C}?bMAv~_J#UN zuJ2k-_s%vd&gfu7tchPr$(`roOhR9?1755+TWS)wj4q? zUQAcabJ>OW3Fv{_m}fp3uNz?_6Nyr8!V{|CbZ1{NDWg9B&0d#S%YKK#?r=iKTx!g? z_v=|eT^Z<@d$Z$+YkJFLlqt%$+0HAA(%0C?C))8t>%@as#h&xujhaG4>f$@yk6hVe zf$NDY4Kq`oH`(2DKQ#supR@?dc0GBiTK1-bI)5af^ulc5n0IdjDimcJXVQim-+W+x z=f*XZ-6P*sLI_Gl^QY=%C2n#Iq`Ydg_B7^VKOxaGEnKbK?94V}N00;tmi3gJ6T1%9 z;_aqq?@_D<08Ynghmju%Eu)Vd&qg&R_bu$R-m4*PSyZ%r;cI!AFElF7UxA6RCkMPa z44n-O-US!LY)Pm!w)h=-+TvktP2ixEjqk1F#Y19Fn-+1b!Dk-1F^n5Mfr6!&27O56 zCC1X9MZuO2!d6#I)%m>4WV43ueT-;Hkmfbmy^dpnMn_J93;GV_|1PRrGPI*6OREu> zF>*x%5pCh8;@Z#xkE*(c5oT?M6GoFgR&b!o<97h)yY}sopA1GX23}Z$PwuK5u?!5t z+OG#s{R{ZC>$dqy3{Z=J7r*Jh)}P*Asw0ajsb>>G>-Py#ERl#9v{OwDVh-{CfsCCAf)5#l>z$#Z>~V z=A}~;G61%fjZLxP8v@I-l^2%Kk7m^+Ohqa`4!4MZ;4-;?rdZg>HgOEu?Y|=_K>4xW zVpLS~1XT?`grxmZ)IGPSt?0&8uM*P&p~jGV5XvuRhQzEQaX6~adoVxt9Ta~JEcxrK z_deTF-g2JIrx&;^7M@bToN+z@i&Kun%dFkqid&S_MD{Z~;D<`Y;^dX|T_nM>B>}Kj zRxC}XQxC-9`4|= zQ|CpJx#SIi&n@MJK8h_bz?8K<_WV3HE6`r^?#Q{kH+#3t7aUj78j(YvP|NEV7T*pi zfgyZ4CF{tD`6F$|TzU;eu$!WD-MHRN&(;NJDbi>AeU_i4zPDoIdS@O6$|rcHQ@4%P z4_jwOQnG>!W>JQ7j+PZ8c1jUZ+scSc#xRZ7_6e(#1hhzb?3D_uFYuFD0t$Np=>)Lb zTGCUVjcUB(I2wo=PVa|pFSFKIMg<&-csh#ie;W$r%;YYg!LD$C?1lswJ}kS2XO&aKS{nTtEHOa-yXonaX*>brKObH2gPyj z#FUxDv}4SAJo_U_cJ3J|zg{0@zxb>v-|FZ(mgV5`$>=v-t|p{2z=LhX*Z=R@kIH^Kbfw_sH#xGH&Ee zn$#HwotJ1Kgur0b?_{$e;~l{|-=7ZbK5%J+hP>z%CTImU`6NDRui06xU0TpPO(z}M zII2W74(AlNIF9m1j-%1jYZjSw`U?eb0vk?{`w*hlk?JO)BAmz(#t^(q56ymYGMKvB z(3Q~db+g*JVQOh|TJ`0e1BxnTxJ)u(^gZyxzqfb~)PtuLubVkC)2Nk9N6x9DZBJ&n z6oy6=if|F$wWY?hcW>2W-6k8a?QZyde4?Z0pp$b-uO*$OZgSN~=3Jtz|My_w*P`P; z!!7KN9SqakG^s(DH|wcbBF@@<&BTRHazo4y6q=}pT0I) zW03_VGsN}IGzXLT#v~Vu_%>`v1J3;9rflxCdA1~sft)9hvky@32OuP5KrO_cqPtSU z=@HE-?K#1bn?4xbDJM zUrWSTN+m4`aqzpDtAc#C7yzno>CEW;7f)K96Xz{Bwz+0QDk-yzL%q zH-%-`;+V^hp6Q^EAo)X$2I|dTYz_Vp03;B?* z(lxZ|L)BDgoHV7XoIt`!T!QjiFN`c_y|*VVA7?}ex5Fa)u~QAW*H9CeAQ(KgP%k`T znj|nag6~RHcrX-~w-V?;0=)OwfA`9GyPhu0=mm~~U#=fApmwI<+=#8u)>vZte z0?f4uV=f_ie05-b81qk3puXgN+3_D!MlV54^E4K}k@@eshEv5uU6h_XPfGQ*VmFqb z@09XWfD6t)-)s}dKKf#RZd6@k;pkkz_LOhT_0;)-e1?3u#n&H^wWcXyyl&?2P%?#@ zz9&fT@r5w5jh+=rh@i6%KxgN!q*F2k%d(|M(B{qR;tXe)Ec+H%6IR2?wPt)9hW*k2 zOHbU}jP4{|*Vfot?bFr-7cW-NBsG&R4I65R507fvl&!EU3!Gt4Psx3j@}tYDd06t1 zs}6g38B^PYi-56`vz@C9tqJkV7)rsSr5C~3!;>NRcaS8nMrbJ*#JcAh!Y3Q%QG(WQ zT)(?RRb~A%M`7Btwx1Bclu>AmITUFd$$D#R_-PQ5t$0wXwnVZ7b@82+Lg$! zU;qwA7Eb15#H@m{FerEK*5qVjglrD*V#hB#Lmi*mGHU`l=qOnFD{F)0#~1NTV6Sa! zQP52_3k8#jy|SvLvJ3`E*z_q6jOeTqre;f8r`q&5DX=IzkP42O}Og&+Skd7|60w1Q>j@142J zVWGsG8kn4E%R5^})tta@J>Vjnxu6cwo4Ttvm1DMLsec+;l{N>sq`kc}bP3(R8>|}4 z)s9gXcRqVvFP%3VNVX0G!>InT&suYrjp!}uvo2|~^&`KgTxpURGl>GlP zK;;V71n+(S=?j`|Q1cAO0^w`9Ry;JUM+u|iJF&Zf7b&mq?>Od65Xf%^TebyN@CO)M zPj?2boOIgd_QdE}hTGC#{w17TBs)u3^%zfpPq}q{%m)^emmeh@|6uj1?8p)%EXiNjIR6bNCe~cke;kSoxSLpeUtVJ* z2v*cj!W^Rg%YM%gbjN-3pfT}yUvVoIwGO*FSSR|h29TYGzF|0=zI|6w} zp@bEa!goL7!=n2nZ40=hrpriZCphaA)`pmDIUW3FMoDg9o|fG&`wCQ)G!s5}>w$ph zCEl5^&$zrl<=({j&5?=VK;4g5m-kOzPzHUs6s|`ujg{@L4PV5z1t4^p%h_#SH=mC7 z%`3lAQ>iUkNKwJuFxZ`ffL8gF17=7Q!mc}|P&hO*rfSk3U!c`^5i{#C6$9FrfoIP{ z)3(c?MGFU#Xfrul89!ZO`iA1#wD7$(fgJz=%ER<~V?lptLGD)t7j&e{zoOb4KhL3J z!)J((7*uu{Ec-<`{oY(Jg}?M%b$l^egn~I3Hg4EcJB+ou3=z7V#_&~|1;C(BZ{CMB&5rx)LdfJV{sneCM}pgjo;fEU&3~GlN}DP4TmC4F zA>{}?)5Dmd{gNvETL=Ilw);!Um@KsF>B!;M~aZ>x11TMzff*)V@ zkDS2Y->-d2zmJ|jtgT-6XQgDD?+H8`-gWpM5diO^=WZgm6}=x&kFot9+{+@btwQ0#Cd`N zZwX`TjH;Vo%D)9EbX^+tJR>xn?dmG;f=EKsa~Yc+PuTD(@<)vz)Mx{s;Exip9J%g? zp*7ra+souIerU)-SvCV>gJ9;kYB%`o??C%L@!wL(`~$MRH<&4cPa;oR=*A&$BVMF@ zvtM_4o}f_MjrTHbF$42spT^eU5>90?(+)q;hSv?VW*mCb;Hrhgt}pZ)@_T~@TcWPj zZZHA_-^d3Rba|oUb;?ob>=%m(EsitG8PN{&gMhlrRs;bYy(pdp8Z+@R{x<4>epJZ< zflj2;>P@WGn>cd{%E0SJ`C8-sVMb|Z+rb8kfnsQ;<4L_cu+<|`$nx1oKz95R`J0$L8cSl%KRlVEh z_8a;q6LVV!6&R_E(>vvv$lbh>{=&axh1&`S9xsMZlDl!2wA(XniKiIxyk|{nrmAZR zsz!#wLWBtctkHof&q=HAPC#28Y9^kzBFU?D_jF(O^{{Y5JHV%ya&JEr|0z?(E+)za zww1r!da4sQ`SuihTXJZ0a;KNIppGYzVQZ(3#7|%O(9}68sJ=)XwY%IeZ^3E0P9pbJ zMszy~XBlf^*%lAIQf3CGyRL0g;`&nD6%~{SXg!NQ&vMXyWN3Qshy1BVqyhnMd@sa zEGnfGh*lq4L*M{6eV%#~8Ebn;q_{$Rf~)W8 zas+QHrr3Pb9fc<}7~M>3Vz(r`wv%bsG>RQLUWQ4C5TLWa=T>OpYVQduE2b2P!6$~*GYaZa@}_a&uTr+oH5^@<8g`V$r(OTp zRQ8TW5}<#Pi4vw?Vv`u}$WeG&HWMY#^uS#?y@irrBtD5{UFa%pRXy;68#4y>DtdHb zyn*-VRL?_%<}+)ZyH{3j*i#w1b6Y=LWyY%d%nWc7pW)nhGE_w@QvIP6Rp6jD`6uGI z=y3G_U11X7mju_a%Rg%VteSR>w0GA^{-AEs7TTCEM>>ddkly%0t4PMufzjkrnMjP> zp_NJBJ9`y`VKehbPS1Kj>NI9cQhnCO0=+1kYLRrF%vuL1ER{Lb@&$;`5CCh^gW+i_CAL<WacQL*})n#TQ$aFB8GPL3gp%|nj;p4PtS@1!#odLI7pF7F zk1WvzDk~sxKiq_%u*`M*w#Rob^2fU%h%(oiKUiLcx-Z2&Ec_@)j>|At?QF-|vzvTy zP5b4HqbovnbHUB;aziBiF*OJwz2$41o1xHz$t-fOWm~`Q58y?Bu_Z&U@mFb(OXx3l zml!8wzq_<=JjOy3t9^RruTL92*J|L)0mtwEHt;B}YKpl_=EYCm#)*6S70Wd}@x;oA zU9tZJ=Jo~xsyw_56^4%DKWoa5BwK3^|1;UqNKLvSCLd(2ccvq-xJF$jA{uThiFCwMe{p{qlK#u@!71^GfFlPUpkGE$lKv2Iert+{xdD_E8q z(VxJkUFQz!X0#&`Rv1Ud`69_7aU;SQ0d;8|#DE|44scUt1le5h}Jxl(__MEqe%9df}>^U?GYC}ob8yeB|bPV zt|iEgu`*RNcpxB&Y|@T=*L&3pT zX86ts<72tkc*W`I$(9SLOgYQ>YvTGW3lgg_zjWyb)Ol8@64%wo|QdGE{4wzQ9r^$~|-`1@A zZtl|Cb6O{=p+z@GeUJ5sKJUeraSGae_|2*;L4=8qqzv3pafN{>e{OG_B3ylbF;VI^ zcnojeu0DU(G26s{pK9Q)8lU*5N>nXXN3>zis%?l;1ZPO|b}2Z|b`-4p`@_rU9FFc; z+SPW*_;$y-Qin+Rk!8LF<+gC76R+lS_2~U1xW!;bBxhP86*~Rs7-vgk{^GP)bgZH3h9 zLX5u?)~9MPmf=@Ft2VhVe=G5c*Lih*dnDjdNcz2W|6W#L>v#>-j`-?};w6;2+l0hj zn7#2z5@(8`WI3f*e&S?j)&`&H(PRf@r@W;HHexhXEnU*7g%UWC$X%?5s8`oN)Emo! zUEM>^Ly=%3BSDv@rbM9;92{RLLe>$xro~7`?o84#ut+uRk8R1h{liB`SkX#h1Xx2F z-m`tYfnbEBGz=nfJg|lQ{?`1U)6El0dRQye7Fl&KFQ7q81NVGU_%Z10=vPu7DudI6evY#*H4O z`B2B+TK2fP&M1a;V73kb$v^B+ccCSXOg&9~9$4)-FX+r4tm$}Uv8(!%x5Qy9IA#TF z1#NngT;jiFR9~Hc>r#V&@r~j5-vDy?I~$w?|7=FZ*K)<1@MC{55;OAlZVNA@j$Zo~ z9~U#)CT_9NO^SnTQtZtjfa*5ruC_V*8GlMzEPjF?XY?e?@a1a|ctt7y57+4mj}4x% z@t6&_kO{*JCli4)B+%oRQCbz}{1TE@h@31wzle0eG*mR}5^f#g12cg-#p|wp7WIS^ zx5>QFr{-svv8EJX^5{dw0zj1y-fYIC4thn1RHLtmvHVV#Tw7vjdeuCHFiM+m@!MLM zF$=Ud`x0&~;e+vhC{0Uu5Rs`WubTo6X&~T+LtpT$#$zLe*Tx=!Ji)9NO-ty}3yquW z5K<|5HG{2K`AJ4KCVxe9fdI@JU?uDA@fGqi={~S{YEpm&-yCuq(KK2^YJ1{w_N%e9 zu}33Vpxg$$U|m7yF$MNb=5xln;)`o3Js<5)hc4xea`s2T3E3piLP;l^BghTnrG%Ql z%jj}F+XlV#$1>0b@u>mch0!%}nzjBW3>j7#Ul(OV@XoX|lrC$xD-3zlN2ZAzU+tg+ z$Fjgp_!F6BR%Q%QD(FSg)(u+8(@1Zu25xax{@PBc>AX_6_+#4x#K#j`fSj$UMYZ5H zs%7PebwjaZb*-CR85;R=FSK^;F09of9dtiFxb7U-R5}=5bEWYtA*mUHLQJ&a)gR!*$ zrbTHDC?IJvVOOvPp_^#UQ0{0mF9hCOgQ)k9Qj7odAqMF^no^3)pL_#pG5}>(;Eglk zFMi$D45USD@LJYFFen~_>^aC3A&Joz%pO3B5K?dp-~s__2Wm&vkIaBVi; zUpJAg`{>pqp-q}79s4Ih-i`$FBOhBPvdFa4+Akdb;q`Sgo9Xv9-gpHAPn#On=o*q_ zS|j6D30`0^Q$E#fGxKwjImi$0>&-*GMVVSQ@(0$W@7s?yZVe(GHT839D%14z7yYgO z7zbR+1$zgk`=M^PKq_ZB$>Z!&m@&!2%5RH#hIXhTeFTg9O8Pl}=SMR43Vkx!v@2%% zK||71o%1gDnuw1GlQJAAMd{G=csA&20;jk0istTGZ3LY01R0_;&5ma|UN^zuTw)G# z78*H)$=Aq9Zxx++u6fr!oti(Cu`E@t$nY~16e%28k3` z;PUreL%*uAsT$3U%TGuR(3whFXZj~sE9&0tn@GWQT^Dvuwrqq^KEsG^i|>Eq_YOq< zo!`S6SCkejl1(yqu{)^{wsLE%X}8~}0B1xzR_1y0rCeHVRAW=fX%B9+FFdNi*in$u zzDH)j=XP*c{Gn;#g~yCv>ghbWlh;jcm7=Hemg(oA@^09(Kk-`ebPDF}ff)F@^(jXk z3$mo4*%8NTL{86USFMt*Bf__d9}J!uyw_$M>GiN9tZKsF1yQRTF`6S4CoUfr*z&?l zW-7cf`)e6S^hnlR;1~kjviHr7oTfK1zIMEI1RM9{J#4TK;ivV#@uq26bIU7#e^hD2 z&QWZ2@&j6PV`O93*2o=C(DRI1;)*K7h1p@dqVQIV!(<4M)A()QY9g{kUkGxr8DTVV z8gldI#xt_4CE<_I=UQytL84@8l|Us*)!IX&j9UU4Sp_>}Q3S91c&W$l;6P8-O zQTiN}?f83pXhexAU_JRcR$d#vA!bEd{#j-0gIenRmu+bK06RqF^yUK>x8)MpqcNUC z4Krxt-XfJ zZa~3&N^w8I*JHhC{gEqf%L(Z4+){H=OI`n_N8=?aCxbfcW(#bsLqt-q5QkM{3jG$9 zN3D73!<`H&RQV3gXw6DOW&O}>Dk!q+{~Jxxgsz)tO-hO$;L1j}dIc7ctL|JioN zKQ}~BvKBDW7l3650Q{>=KZ1j5>g)j^Zi~L}@>Mz1ef|pzf}twp^l4=e z(o!@b!T&MU^Mr=TpMLLfcWM+qkuO&3`r&0W@2To%g)<%SGW;|Z|D{N*+Vd0RHCO5+S;66a`TU?Al z4IYT%w!^l>mAt5kC2eaTIW8QkU~C|kn#!90vCEOXSp!SQt@ajyPW2$;8R6RvK;bKR zXj111=Dh`v`H=jk)fEQ#`)dmX3G=$0PnLZif4N3n088@8&lhS&-^f$N;$eY!#Ie7o zmul~v#whf!QP3LU{90EJ|L#=r)8vRSNs;RFw0wjY;D1+33?hP1*`Ej|mh#PD!_gLH zS{YH?x}(i^9;t0dn|2~VB-2i~4Nr!+TiEaM_CN40D<`86Id~E3ur`rvTi`Z^EeNo3 z%TukZqco*hMMdD=Su;by+7!qDS#YoyyB36w28RL6(Be34Ov!Rhs3`1B&~~E+d*P9j z=K1h&F9hWUtO-fJ(c87^$jQR-b+tVF^99@p_|}Tkq@EZ|N>mX#l>U-ax`-`&NnKJB zJS`VbV5fuGyNClHaJi+%tkx7k5FH80MOXsS<@!k>;G~=G9EjfNiVMUNPX+2mu+`P1 zRk3#LME`)rd+n~M^bmO#KD938=;!>e5IJ29LS$F$TyL5rW)%XZ+uR< zWX3q(pR$Ssi}h@%quMp``eZz-8cI$f(qosbJ2}{08#EQPDaJRs6nOCvq?kdN4&`Jg zT3gcnuF4PGr1neN1@pPj&NqB9Eq<n zS$}m)LU-64!0_jPft!AIi@7niOYar$L(d4SiaX{icQl78bEOBnAS@`O=2~c?XzeOZ zDAw*Fe;K&+H) z3veQ`*QYyZvt`Dv8-_d~_d534{aS9~Vr{2;!~0N^FxyWN9vPLljNF1>Qk487s;4eP zc$v!&HP2sYS!oHMAJ_r{HU7al2HzDl$zA|_?E-#maco@>1@l_UG9@SPL%_V`8r`@> zPgHq^N8t?%!M&jbY%?ukE>Nxm4;WbRfhzO=nGWn%A^U$!0V3mU;6;@l6#rS_t1mmh zO2#h!|B#H4V`&Y4Q}doJlB$cV+=^AQ5|em8in&dA(l!8yKl+b~-lpV;J|);p4anmi zRRx4_Y>6?hWo70rPl?7VDP(m7TE?o{IkgYAeAfS|>5T2+n?3gN6 zxCuSCVIi1AqI15fIYFI=H9@o%8_R2z_av6A-ei{u)`98lkmBE@uKLoDT3$eQCNZFR z9NGDv858;psu|;E}41kU?R}wpEHRDVU!} z1!tI5@N-raUL@FnR)8Ajz7AX7aZ{NsL6EcTQbsZJ=um~G;c6%qze@HIRLIGnn#Mbu z)}}PB_j*oYxE@I`BnQ>u9Y`CGIpn$dU?P;04%C{E!dT`}uo^mp*GopX6RM;f6PF_u z_S5OVThbM$dhaBi!ua}=nnw59F`ayzq$-K<=d+d#0&OzK%WY;t5(rCisP(-;(ygfo ze-mGvVI7y9SszUWvkWL+ERP5EB9wweD64h-(tsP0%Sc>Thk0*b7R{+rY!bOMcg8Cc z3FL?bY?a4yt)#gQqG)gYBAEm9S$y005v9Zr`)lCln+#qNaQySO(W;(w`7v2PC+V6! zhm4Cj1?8VL7lct%>2k5{D19{|3U2~#O%}K{xwbqi1~usCSysrA(&k5+(l_kpgeFU* zVSd{+(X!e^L*SCgMlaBkUFFOZY!88jpv^5xZ?1E$2UVz1?( z*emE-U9wfthpxH6nFZhh`xfT^UX}beWoXL|km>>Y;{U6gW5Pz%h+qI50nw|?zP>*2 zKO_A7XKkt6eUNNj(B$WmI92X^xHhelRn+$cjhT`3_-ZlnZ#D)E)@b~g!w8B_Ut)mG zigLU@5|``WSlKf*g$aHccX1VYWwu(RF^4}b8>)5#6$Yc#rKO~SA_b$f-omBC+PWi! zu{7&z(Gj(b9`L|0AS)(6d}RrTseipA9#ov7$ju4a=)nVHZRgdeZOk=Gu~X%Vr4}82 zeiqdkid7s?hLQD|I95>V&c84QUX$OCwkPcz34qG1h>UNA!rIy;C5#OQl&6bQPqFP+ zbmX{+jB@2-Ib)WSQ4ch}<}_@%CX;k{-SamayrM%H+X7}Wzr);-Gm1Z%n4TC7i?;y5 z=ehb>JTEIIlHpf}=Yn@q&ffu`c4_ZHYF|Dp4&6my`rOXU|x3qo&{;#12;L7 z^#kk<$Izn9;M)OaRaSfN)W=$~GDtyhS`t2^F%=!Qh@9?ozb8raC~~^m2zcNBZL2~# zWnt#Q5x1&e+Gl*U{}^IPk!n~;SnVG}6dS3jvQ z^Mr1?jvCAbQ__yRV9XcWG7+@f_R~XTt;AyPtm!)3$w!bo?dhRSfiOeLsIrnjnW_>| z(GdEu#T~bE_Sv6)u|*_oyO$hK^z*kfKOzKxF#;&SRBa?gxj_P{2^nlk*4t}`Bzws> zhd;5Pq?X9TyO~!Mt5L9=j#Tl-@f3_PYlNQLKVT=KD+=I2d6{h7*})O>@YVDxGDH1@ zQY#U{%=OFcNZM(d0A-~