From 5891c21179f651d9c08133692cda0c278dc724e6 Mon Sep 17 00:00:00 2001 From: Josh Tomlinson Date: Mon, 11 Dec 2017 17:30:22 -0500 Subject: [PATCH 1/2] First pass at camera publish from maya --- hooks/tk-multi-publish2/basic/collector.py | 42 +- .../tk-multi-publish2/basic/publish_camera.py | 363 ++++++++++++++++++ hooks/tk-multi-publish2/icons/camera.png | Bin 0 -> 769171 bytes 3 files changed, 396 insertions(+), 9 deletions(-) create mode 100644 hooks/tk-multi-publish2/basic/publish_camera.py create mode 100644 hooks/tk-multi-publish2/icons/camera.png diff --git a/hooks/tk-multi-publish2/basic/collector.py b/hooks/tk-multi-publish2/basic/collector.py index 1c033d1..19c8dd8 100644 --- a/hooks/tk-multi-publish2/basic/collector.py +++ b/hooks/tk-multi-publish2/basic/collector.py @@ -113,6 +113,8 @@ def process_current_session(self, settings, parent_item): if cmds.ls(geometry=True, noIntermediate=True): self._collect_session_geometry(item) + self._collect_session_cameras(item) + def collect_current_maya_session(self, settings, parent_item): """ Creates an item that represents the current maya session. @@ -225,21 +227,43 @@ def _collect_session_geometry(self, parent_item): :param parent_item: Parent Item instance """ - geo_item = parent_item.create_item( - "maya.session.geometry", - "Geometry", - "All Session Geometry" - ) - - # get the icon path to display for this item + # get the icon path to display for camera items icon_path = os.path.join( self.disk_location, os.pardir, "icons", - "geometry.png" + "camera.png" ) - geo_item.set_icon_from_path(icon_path) + for camera_shape in cmds.ls(cameras=True): + + # try to determine the camera display name + try: + camera_name = cmds.listRelatives(camera_shape, parent=True)[0] + except Exception: + # could not determine the name, just use the shape + camera_name = camera_shape + + cam_item = parent_item.create_item( + "maya.session.camera", + "Camera", + camera_name + ) + + cam_item.set_icon_from_path(icon_path) + + # store the camera name so that any attached plugin knows which + # camera this item represents! + cam_item.properties["camera_name"] = camera_name + cam_item.properties["camera_shape"] = camera_shape + + def _collect_session_cameras(self, parent_item): + """ + Creates items for each camera to be exported. + + :param parent_item: + :return: + """ def collect_playblasts(self, parent_item, project_root): """ diff --git a/hooks/tk-multi-publish2/basic/publish_camera.py b/hooks/tk-multi-publish2/basic/publish_camera.py new file mode 100644 index 0000000..ec62cd1 --- /dev/null +++ b/hooks/tk-multi-publish2/basic/publish_camera.py @@ -0,0 +1,363 @@ +# Copyright (c) 2017 Shotgun Software Inc. +# +# CONFIDENTIAL AND PROPRIETARY +# +# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit +# Source Code License included in this distribution package. See LICENSE. +# By accessing, using, copying or modifying this work you indicate your +# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights +# not expressly granted therein are reserved by Shotgun Software Inc. + +import fnmatch +import os + +import maya.cmds as cmds +import maya.mel as mel + +import sgtk + +HookBaseClass = sgtk.get_hook_baseclass() + + +class MayaCameraPublishPlugin(HookBaseClass): + """ + Publish2 plugin for publishing maya cameras to fbx files. + + This hook relies on functionality found in the base file publisher hook in + the publish2 app and should inherit from it in the configuration. The hook + setting for this plugin should look something like this:: + + hook: "{self}/publish_file.py:{engine}/tk-multi-publish2/basic/publish_camera.py" + + """ + + @property + def description(self): + """ + Verbose, multi-line description of what the plugin does. This can + contain simple html for formatting. + """ + + return """ +

This plugin handles publishing of cameras from maya. + A publish template is required to define the destination of the output + file. The FBXExport command is used to create the camera. +

+ """ + + @property + def settings(self): + """ + Dictionary defining the settings that this plugin expects to receive + through the settings parameter in the accept, validate, publish and + finalize methods. + + A dictionary on the following form:: + + { + "Settings Name": { + "type": "settings_type", + "default": "default_value", + "description": "One line description of the setting" + } + + The type string should be one of the data types that toolkit accepts as + part of its environment configuration. + """ + # inherit the settings from the base publish plugin + base_settings = super(MayaCameraPublishPlugin, self).settings or {} + + # settings specific to this class + maya_camera_publish_settings = { + "Publish Template": { + "type": "template", + "default": None, + "description": "Template path for published camera. Should" + "correspond to a template defined in " + "templates.yml.", + }, + "Cameras": { + "type": "list", + "default": ["camera*"], + "description": "Glob-style list of camera names to publish. " + "Example: ['camMain', 'camAux*']." + } + } + + # update the base settings + base_settings.update(maya_camera_publish_settings) + + return base_settings + + @property + def item_filters(self): + """ + List of item types that this plugin is interested in. + + Only items matching entries in this list will be presented to the + accept() method. Strings can contain glob patters such as *, for example + ["maya.*", "file.maya"] + """ + return ["maya.session.camera"] + + def accept(self, settings, item): + """ + Method called by the publisher to determine if an item is of any + interest to this plugin. Only items matching the filters defined via the + item_filters property will be presented to this method. + + A publish task will be generated for each item accepted here. Returns a + dictionary with the following booleans: + + - accepted: Indicates if the plugin is interested in this value at + all. Required. + - enabled: If True, the plugin will be enabled in the UI, otherwise + it will be disabled. Optional, True by default. + - visible: If True, the plugin will be visible in the UI, otherwise + it will be hidden. Optional, True by default. + - checked: If True, the plugin will be checked in the UI, otherwise + it will be unchecked. Optional, True by default. + + :param settings: Dictionary of Settings. The keys are strings, matching + the keys returned in the settings property. The values are `Setting` + instances. + :param item: Item to process + + :returns: dictionary with boolean keys accepted, required and enabled + """ + + publisher = self.parent + template_name = settings["Publish Template"].value + + # validate the camera name first + cam_name = item.properties.get("camera_name") + cam_shape = item.properties.get("camera_shape") + + if cam_name and cam_shape: + if not self._cam_name_matches_settings(cam_name, settings): + self.logger.debug( + "Camera name %s does not match any of the configured " + "patterns for camera names to publish. Not accepting " + "session camera item." % (cam_name,) + ) + return {"accepted": False} + else: + self.logger.debug( + "Camera name or shape was set on the item properties. Not " + "accepting session camera item." + ) + return {"accepted": False} + + # ensure a camera file template is available on the parent item + work_template = item.parent.properties.get("work_template") + if not work_template: + self.logger.debug( + "A work template is required for the session item in order to " + "publish a camera. Not accepting session camera item." + ) + return {"accepted": False} + + # ensure the publish template is defined and valid and that we also have + publish_template = publisher.get_template_by_name(template_name) + if publish_template: + item.properties["publish_template"] = publish_template + # because a publish template is configured, disable context change. + # This is a temporary measure until the publisher handles context + # switching natively. + item.context_change_allowed = False + else: + self.logger.debug( + "The valid publish template could not be determined for the " + "session camera item. Not accepting the item." + ) + return {"accepted": False} + + # check that the FBXExport command is available! + if not mel.eval("exists \"FBXExport\""): + self.logger.debug( + "Item not accepted because fbx export command 'FBXExport' " + "is not available. Perhaps the plugin is not enabled?" + ) + return {"accepted": False} + + # all good! + return { + "accepted": True, + "checked": True + } + + def validate(self, settings, item): + """ + Validates the given item to check that it is ok to publish. Returns a + boolean to indicate validity. + + :param settings: Dictionary of Settings. The keys are strings, matching + the keys returned in the settings property. The values are `Setting` + instances. + :param item: Item to process + :returns: True if item is valid, False otherwise. + """ + + path = _session_path() + + # ---- ensure the session has been saved + + if not path: + # the session still requires saving. provide a save button. + # validation fails. + error_msg = "The Maya session has not been saved." + self.logger.error( + error_msg, + extra=_get_save_as_action() + ) + raise Exception(error_msg) + + # get the normalized path + path = sgtk.util.ShotgunPath.normalize(path) + + cam_name = item.properties["camera_name"] + + # check that the camera still exists in the file + if not cmds.ls(cam_name): + error_msg = ( + "Validation failed because the collected camera (%s) is no " + "longer in the scene. You can uncheck this plugin or create " + "a camera with this name to export to avoid this error." % + (cam_name,) + ) + self.logger.error(error_msg) + raise Exception(error_msg) + + # get the configured work file template + work_template = item.parent.properties.get("work_template") + publish_template = item.properties.get("publish_template") + + # get the current scene path and extract fields from it using the work + # template: + work_fields = work_template.get_fields(path) + + # include the camera name in the fields + work_fields["camera_name"] = cam_name + + # ensure the fields work for the publish template + missing_keys = publish_template.missing_keys(work_fields) + if missing_keys: + error_msg = "Work file '%s' missing keys required for the " \ + "publish template: %s" % (path, missing_keys) + self.logger.error(error_msg) + raise Exception(error_msg) + + # create the publish path by applying the fields. store it in the item's + # properties. This is the path we'll create and then publish in the base + # publish plugin. Also set the publish_path to be explicit. + publish_path = publish_template.apply_fields(work_fields) + item.properties["path"] = publish_path + item.properties["publish_path"] = publish_path + + # use the work file's version number when publishing + if "version" in work_fields: + item.properties["publish_version"] = work_fields["version"] + + # run the base class validation + return super(MayaCameraPublishPlugin, self).validate(settings, item) + + def publish(self, settings, item): + """ + Executes the publish logic for the given item and settings. + + :param settings: Dictionary of Settings. The keys are strings, matching + the keys returned in the settings property. The values are `Setting` + instances. + :param item: Item to process + """ + + # keep track of everything currently selected. we will restore at the + # end of the publish method + cur_selection = cmds.ls(selection=True) + + # the camera to publish + cam_shape = item.properties["camera_shape"] + + # make sure it is selected + cmds.select(cam_shape) + + # get the path to create and publish + publish_path = item.properties["publish_path"] + + # ensure the publish folder exists: + publish_folder = os.path.dirname(publish_path) + self.parent.ensure_folder_exists(publish_folder) + + alembic_cmd = 'FBXExport -f "%s" -s' % (publish_path,) + + # ...and execute it: + try: + self.logger.debug("Executing command: %s" % alembic_cmd) + mel.eval(alembic_cmd) + except Exception, e: + self.logger.error("Failed to export camera: %s" % e) + return + + # Now that the path has been generated, hand it off to the + super(MayaCameraPublishPlugin, self).publish(settings, item) + + # restore selection + cmds.select(cur_selection) + + def _cam_name_matches_settings(self, cam_name, settings): + """ + Returns True if the supplied camera name matches any of the configured + camera name patterns. + """ + + # loop through each pattern specified and see if the supplied camera + # name matches the pattern + cam_patterns = settings["Cameras"].value + + # if no patterns specified, then no constraints on camera name + if not cam_patterns: + return True + + for camera_pattern in cam_patterns: + if fnmatch.fnmatch(cam_name, camera_pattern): + return True + + return False + + +def _session_path(): + """ + Return the path to the current session + :return: + """ + path = cmds.file(query=True, sn=True) + + if isinstance(path, unicode): + path = path.encode("utf-8") + + return path + + +def _get_save_as_action(): + """ + Simple helper for returning a log action dict for saving the session + """ + + engine = sgtk.platform.current_engine() + + # default save callback + callback = cmds.SaveScene + + # if workfiles2 is configured, use that for file save + if "tk-multi-workfiles2" in engine.apps: + app = engine.apps["tk-multi-workfiles2"] + if hasattr(app, "show_file_save_dlg"): + callback = app.show_file_save_dlg + + return { + "action_button": { + "label": "Save As...", + "tooltip": "Save the current session", + "callback": callback + } + } diff --git a/hooks/tk-multi-publish2/icons/camera.png b/hooks/tk-multi-publish2/icons/camera.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f84724b26144e58b0de2ee37d3dcf0340947c9 GIT binary patch literal 769171 zcmeI5349jSx&Ol!2tsAC3I-G`aif*erpT^P6mh?mx>v2Ow(4KS-P%TNY;D0^ui9&E zrPYdBwQhB(txF&TEEctwx&%c_EV14oDzapO|L@QwB;-xLJso0knN$fxX0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00i71z*qn`@&PX(009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY=^2rw4F7D?uWfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5Xg`~mkjq$Yxn+--2Pc!-mttG)27T!>i`dT+Pryl_lk;&VVgE>D$;ke3{jYU zyLRo`N8kIH?^?`y%VM^5>C&Z#)}Lwpsn%=t+m=QDoAsyWe|@jfZ_Bl=?A5DRWpQ!w z$J)*(1_a8>%Xe&OXejE|ty_`G#TS&1{p7aE_vUh-|67)e-uiz-i?YyE2Aa!;e*Z+v z3R51sckf=g@4oxKukV|+jSmDMAOeAiobP1k&!6946-luwpWPMf77;UREyJ~R*AnPQ zX@97+E0sv4socz>iu3Q|#*KSD(1bCbl7RA}y9DgZTJNnLOgR|QxHe_ub14t9xKa7P zUg>PP@R3JO=V?epOpB7Ul#%nPxFsDAs z`&v2llGbHfUhLPe-@=h2N1B!&9|(9&0AWj!y-SuX8N7b|`u!U#EhA)mrPwVFo7Sj8 zTVN_RBXnxfy{zvIad6xv9~UlMSfH{nPRo9#OlTP^|9ZLPW17CyYrnr~*&=iW1qJiz z)=rZgyTytC!q%8wrd6g&|C{>vI4u)YdHKkuS}{JL`0kxFY0~1x&{?G*p!_%8iwEeZ zQfud0WGURvXp_o9t>S!I2hHog<@s3IxI@kT_whtgP%=U0r>!P@7iTp{mRZ z!pH7bimK4eeYq_nH(|nr_uTR>cyG)g5RGCyUMU@`WoYmzI-f#~%EN;?H|D98Z@MrU zed&Cb;b2Pwi4iv4L)(7Ch7D)vO8i^_7}OF1-~U5E71$FURQaTqgLGSXvO77lEXtI;JvV^^4eKqHcOTE_f&xeJ`6jwoC`Q1 z@p?f?%+?jVxgX=rM;ACfbb({Ko-fv7hU)W4gMiAz``YaWt?y9RwRz5t4+NYg;H|J} zRNJ2FUb;x+PgDh#?`#e@?wBgFSGCMh3+@4}%?P`wKS%BGqg`_v3!tIx!Zx9HZ zfHxJtc_vNWO>@)*d1BZQ6PDfz-G4bxt+_{Cj$0zuO*6-wDIZI<^mEzQnESTTT=4Ym z+xO~Gqegue^H^}-69Tapw#NG>vs96lXfbo~@d<%|x+u+kxN~(s?yV4#%P0vwt7sm! zzeUTJGCGi*b0JVAfxA%m;_lDI2**Oe27y=$o4OsRtK0D=3ECbuU|=IN0unbfmD7y_ z1`N2$g(;j=9tu?+u2p$BHnT|B+ZF+pi5DbrXRAg3zqV{*2LhQAh)CE*UHR;Ct?Ds*#4#EB3-%P8-**4^E+OkF6kdC{q3UgfiznYs8@No ztxummSBxG#dQGce_y+=E5GX9IDv3zxvI|dY)?GJJF4NIwv`8E$^~)~sm>i`VZN8S% zq;hYD<+7fdAkYy3 zr-iL?(#Pv0XlHd41iv{;zC zwokxWk<%6W9ul|vwTx=teSV1n0V@?77d$b@>GWNEOf9)@t0lKO{X^Ij0_hWQQrIMF zCu_*ttqOx7Z|Ucy>w9KhnQ@Whde&y;pLrwRxWdQS zh$$KZP6(Uk%-UYF*gmRC%*>O-$8!Q|xvf)WcC@Ch_+xvas{8Rmm4`W6GAg5=TfKws z+YHN_F>T7s_H47=Z2~GE<{dg`YHeC{d?1h$fs87UoKkA%U^C0H1ny~7X8W|W3!D8U zP_Hh^(c+{LhtmMi{BEsoQCHRbbBu z-LQD#!|PlLs4}}$!@_49J7(tVb?esMrLQOCYM0~VNkHXczUJvVoO!z9nSZW$9htD1 z7p&FS*PCvs9bAEdAJGs{WpbS`t{%t5>h_W5$fBZn=@~5a^6Rs3O;Rf2~|j(G}TQ&hR?~ zAdsh4+^ao$^q4$$?ATAh0fBT0gf?@!841}qXarG9H+R?%0tqLeI%8B_UEQPR`PYP_ zAp8sngd%K>&#yf#zlLSt8@oaP0uacPxb0tEU44(%q10C(k3WIH3yQhYYJ4c0XV&6h zUWfn!kr0rm&C~$2TOvt(YofQD)O!$P0k-mp#kW93&RlKjs>@8J#jGQ-C=NIY0e1OfuAh2PQ zDtzW0HFJXw0Q(StK(YvE=wz*4{5DRXza=YjqD_}TAi^e5+e4!EvYcq|LAG@LV?PK$ z00OB9EZ2hyCuuY%8pc6X0k{= z5P$##!XWUO?!6Uf@+$W*oFa{A30P~f=^ooIy1{E+k<14I5P(2f1h#8vXt;mHiWR-W zN|1EiCtyX`)b-e1i+O;pzxyHMAp{`c69Lsb`&3m`UFTCw#F85UE5fFyC@)jtnvk0- z=^cI8iV1&bEI@j!*b4$lB%r$JOx=4sB#E&Tb6WyA-)~#Ic=7O!8#n$#rs)=F%a<(> zfIvtDbX(+|L4yYET~t)GF{C6(#!&(}x85XbHz+nl&Cv|TEeIrqfLd+4X@vGgNr{&@ z+b57yi%oADonBvGZ>IO>0|5v?AaVj~wXM^#mmcW;XXMV{Kx726Zn5c|H9a&k>88j$ zCt(Oc00P?(P^+!CmPiJbY(Bf_3dRC#lOYcLo3+So*sx)i3ez4A#DEJBfB*!V38-G0 zsX--En>X+!aRjmww#HXzmn4oB0Yd-+u^^ynxNecab&rL!IBA_gR>HP!-MVX3X!=_B z27?fQ00b-$Q2n>5bQ&f+Ee1Uw~h{;j`whp_;DX72V1>nuM*BdU%FWYl_7%WY4I+&|Rh&*-?0 z9N;$yKmYzeb`i?vU{2x^1R#)-fa7~Q z2tWV=?h;VFwVQ@a&UDv9JhM$8tp`8!Alvrq*RTJc3W)9W?b>@_+KZoecr1WA{ohc) zuZUx%zE^7fPS>to*Xa9NEuZRpz22_4ora`rg|vG^|BP zpho%nlG1-mOQrI^QWuaPXuVc9ht?|p*XjRWJ$v@-qwcgm`o4pf5!%<3ha#=Nrt)CQ z2%iiHh~XvL{r(INVb>TFNNZGxx+E`E!T4E>;|$aFRjPmRNw`V0@FKSf7GJVhKYEkc&+D$h1lbxw5 z3x{j@oHcJfHYENBYO={^Jr0r38VPh-K~`2)_FT1U)w|k%kQP2E2&jVjM3u_}60&)! zxL(lzn^Np%Wz(WXi-zc`{#d1VqLxusjAFzpfkxqaPDbzT)2GkFqeqWkV>N*m#?0%c zSFT)nsM0)6n-5c&=+WY5zP2DBMt{}=ZwIv4#8*!VbSiARI{Yu4EDw7cf39Jzl7SoZ z^Yec(cI?{bbCTF)O3Sp^MS}^5J}yhYPjlrHU;wM0s_o zT5YpiYzpV=BbVJV(&4cH;XsHcl@3Kt_u2aDMEO8VK{W0;mukIElH1hPbVZO|P1!~* zu{%PoIrFyI;n~{YxQq!@s7#!#iu2`+j|}*L#fujYudS`UUgz(T0Vfq3^UAB&lvi}; z$0os;cTr`FOGNuEYFwIS$u- zQ+Ze?zOz(G-l^|74Gal7R$ZVTEMI@EWv8Iiii!P^lP6F9M@)Rh%`6CX_I#VUIi2{A z`si;TGGxfUu8W$sVdv)T0Tg8<^=#iTwl}U8pWy{f9blYnecV*@5vrL zdW@2+1>nZbo({@*{!YO=7=qB7;vz(Cvzx;!kpyE-l2*&bJgRVr46e0iG=7GXT))LHw=(oN zrLZ+liaa4hTfXf6u0&vhPJS~Lk{2IUVw+ScpQH60F9HfN2*XavooMc@g_vyMNvS-T z8B)wc%%26Gn41Zh-YGtw5=bd*YO3#-#Qu0yV&=KE={o7neMav-5^M92_gwD+3osy^ z2eTw<_XU_lWTsWl7fIYq1z#VT6A>k>eBD{yk-JBfJjn)3Af>P=&HVyS*G2Q6=_EhI zr{TkW$!m zHREfBPaQk$@TRcgsL0sgUu!qO#vgQI*Kfc5_Qz;#-b}!!9RlL>2MOF|?fmT3 zW?lIFR_FiEy$UM5V3K$-pB|Z*@6|@+8i)Vy74x_gD&?9z61UrBCoNpiblu&2;__x)!QSx?+D*37S_2B>p48zp%KtcwN##h{M@pV4hg_{=gsfgft0tV9sSdW(Hb`oP78GDn^C)0lfp}lbGdGDDJ8&Dv2WZ z@!-LOe;*3qm?feMpO@wG(wMoOvAeqP^}gQA7)s0!XcjhA_~wOe!($##r|#={wt1cI zl+Yd2HMh)k(IqK-#rtqkQPIXE#hgj3y4Xp=`GT-zQYd1uZ?mv9KAG?P+elaGdA1i~ zkS~$BsER%b6PPq$5z#aYTM|Y`nyYgyo5=R| z3Fr#_!S;Xk>lc-U)oP_a?^jfIqZu=1%t~2YY}cxD*0yh)K-W3Pa40(h&BB(18>ou$ zg^n;4k6omx|Ctw{iIG~j%T@Wm-}JxFYn6=!iZu~K-E+*x7jit_`NO++?@rgG^SPA1 zgDpjFX!?i6b5GrCD~qS+p?m#e=qW~!phPVZapsCvoV-78G_T|?xpLxocL+2Kn+k7V zcigh?iQ;=h&+Po$zGeR`CZQrTxt5eTb1k82&6LZA*DYIh$7@DMKE4oW7B+Ru_@1$^ z_>yTs$Dy*|Ju8XYCe2EdsL`O=mYc>$W!}m5_?R5$d;J%aY_Q{Iv#`mW*BPtIy3!6Z z|E;LY)_Ybe5C39Tn)J)EE(DgRzjrM6bh^i?ddGh~%vgZz%2l(-sStZDa*EIUiaWa^ z(Do<|CRr_BUQfZL`2N{8a<+6p!0YoT0lilpWUYTcH4B?U^IF(caDDGqv0XZAY#VgR zo*sMoz$JfT;LF=F@G%z`y{`Xq0Tat(3rnj?5~FUqTf8QgxfGq#wb3OVe9CIJF%?N> zn0-HgP`Av=gVTGr6gH;5#ioryk7<;QK|Q?-%*Ds|%;?wG=t8CzO=P)jORN zI2S4biFl~#d61az=a1L*p9keHqY#>fO`|P7%jn3M?W`wIw~Lv}k-DpHs4kH@5Pagk z$7hwG>IdJ?A9{DJmY8UbH4B^SF|WHCG@p*w-L3%?qvo;^fNd8{`W~Nc#=dveA#Aow zOoaBDPi|e2d7ZI}&-WA4YB3V8ZdMICW=vhvUdLw}x5|U>7lvNff40km>-L(3O^$k< zv1+ju=9C%NPC4>?uf_tTPeZNw&!xY2{Pt9(-9LU_N9VE1LvH6%bgrkBvf}f)E=&u8 zM>{1(`SJVMyir43l1{NV~0Ti03Og0Of?^i6U z$hH;6+Sv*}~Y%FF93776#B zHo^I9D+#O=<8})dE~M3#MnRUS30Idr(%3b&yU=2bZPul9yrr=De#J7zbg`wRz{XYt z8X6iVwA$e5KdQ_odK#M5u;$O7|0Ri=*Y{i{-0{7zKRN$SJ)!B*yZ}~<@7As-Wpa&O z({5SQN!okk#*M{pdF7@zDhrd{^vteTDieu_GgoTrvh$vk@AY458Q?Lh+xq8AYPIb;TerV^7GJyJs1M?2?f#hY z54W7X<`~z<0;Cs|S}xO7q3xgE-rnwY2G0fjCvR0A3RE60_co_n2ex+n`0?+y-o$@# zC(ugd#*G{Ix|---51VYtFrByusUq|KPI*(j?XAsxWNNwG)ZXt&*{<@?Tg!DxiMOLT zb+hdUVv&@G|H@V8HFU&--{ME0m9RCsKR48VkNYiNym+|cy2!`a+KH*Go$YLnF@aRV_F|0V$;fq8WV=;WRb83U zK_2a_E~gRdo=r-ZQ(8GE9=Dr0$I{x_vz>H4bg8Ya{U3#uq>H`8)OVg0*AByJBW${< znzSpJi`6B0K!=n({LzenQy1iY3ayWa;bk3?D)-$#{`litvo;Xp19cu;toRdiE~pD~ z{lI|({~F^gOT+b>k2*<@@+SEm0c}K1H&tH~xix9f^I{is#j53QJ*m2r7XhUiL`_Z2 zY{i|FS&`GE(!ATrWo2cFddgn{H&*50C(Q(s@nzA-kt1u95o)rcY$I&CqS>TnL6R`& zgx;yHuI|3ZnPI&TU6t6;3NjJTF6EG!x9gd|Q8^qRn?qlE>7_wB2TV&oDYIlZeY8^osx+!B|)M#MKRv(OFRL_(MOz~s;HKT5>4k<*E7n~jcP3;9l334$j5xC7QdZ&#yyvzh19Wm9tr2oJMwS}^Cu|;8SB#Hn zG4Cwl(>Z~`YRUge-IAa0eAoExQCV5pQ}LPdkcgIP%N&xZ)vBIb)N&i&{UMN2*z|1M z%L=jDpD@#pL?h(RRu|Ol^pA+go<`IZ+cT=f%&fP3(kD=)O7KsS-h-XH;sT9!2y85X zc{sbey81ztjVbA4@oLZKG`3*9R}m3RGl7&Mr<1xt%LC1OCG3k%_KS7JewWr>+3lv^WqGbr8W?GxU7fhTu@qW9O?OBt!?I$1qTLQMHeBofJuZVP%{AQYB$#Ft~BRfB{!&HiNZoc8F+$T5QwJ zO#aF%COr;04^$>z(2(-8Crp^&%mtxFcMj3umuplWjtv=y)5$5X?$Sl-sZKkIb2$^} zRM^ylyHqWJpXHpAX9jeFm{$PZtmRgnC?7=?o-RBNQrefO0^2_-A4qo#0W+%j_j(87 z91SU78Wj^WgTE#_zCh`psxna!l^?FAs|%0=)xv((RsZnI5`n_fs*+CCO=F&SmAbv7 zGo`Z|be7zTof*?~yHjV)ojPllh2g!fIQpt4JxcjL|}y z2oyW`uTJ~Kl9Ok)-P(kNb9#$9#(3-DVkJJ%}ITN}#9mdv7^!mXsgLLrN?e zZPdjh?9a2KXd|K-$7)cu3gh zB!mlLLLeptzVhPdb@wj3c>!XAC54-+zczR8-u;>sKe5SU0vU;%o=$y0EZ+5)2cba# z0v-`ix9($lch~D4g+wT65XeZ_boEm&o7bmdmt7zL0SH7+K=;|qH~~HhBao4>88$CCxHaA z61hfB=c@3SDe?J000IzjiNH!tb9S{$4&h6<1hN)3J?~~-WX8jg;pP{qK>z}s5KwpI zg_^t5Ol`&|p#-uPHp9!jyiBdOeiRHjgOrNicz&gw4E>Qw526 z*%DlU2ps|r5vW&vbhbnO#NU+{UOBZS=3@bJ5;>EDx>CAV1#5o%bCU=l0D(9YP(5^O zSnp7bGp8i@p2LE2W`1nLX?@-iL zX4D$@x1iI)emDeHtXR>js;cToO6_6^S&w#7HQmtH4;eD#3iI4`t9=Sft4ge?o3X5y zyZu(4e5+L|`~v|9Kp;Q@s^Mm7*!E2UCV}Y?36z(Y@2EF1KdvOlq?zoK%Ksx&4$ORz zTRu78XlpWL)*3c>rdE|LxA7eU5QvPxn_qu;T+GJ;q|Z(j+v5ma`n+7efCQ@Y^YgzQpnXh-NI7n+WATGNhJ#{V}NYq?gJ0uX>ejs%|5#q&>c zw87yK6R51L>{(r1{cCB&@s?cKy~$1>EjD9ZU6QNSRdA5L(pAtzJFE5PCrbt=W-LHf zgg7X%1peN)Z{MSI>tj=533w3r!i5V5NZ_8eC~$eQHJ}MiU?OJ{kkGxMnM)5XU;;j~=}yo8vjg4FVFi5%u-;izGyog7PR(VKYu^{+mTAj7RHh z^Rov*1%q7(K)_o9H4?Vzs!y1mJ;qtAdutOUYUWkwML~uUxUd=Lb;I|M>Y_X?$Uv|S z0SI_Y;4_KZAriGWy^Sydfl1VkRhWO#vP00}h9Ybx2#MQV70ye84hZ`YfPhy7>eb`( zO${6|5AgDFionY6&-r)eV*&JF^$(;4_bQa0VT2Q!$eCbNP-iQ+R!@$H5hQ6q00QwN zpt@qSmhY(5_Eh}5$74fa$&w{KG#%rw^z7Qzy1!<1n#Ya^hbnBw5f#$&R9NSApJgpn9&*e9S7kw@y@+6%Hg$iDUTEk-JG#!a>2Zj;KNi_oQ? zY3vCBPYHC_RsT&Ic<_{YxYyGdy$wsFAZMu_e@OLt@2GdOSe zJRT6rkkC|qunhtbaE`!6Rgyo~J0Y*uE3;~y^A3la38?<=X5N{m^;yjuBl@Bq!7Z8= znXsAn>!`_kzhHbdA_gQ20SGuwK;rhYx+jm(^RaI`?rI|4Q{$vhO-;>x3jPom05l0( zUSVlfNhJM|QnsU{Y~~dKD4PpK0v{mYC;?MPn7YE$8IHP`Shv(v+gZw1CIC(-Tg!|H zUD$Mo@jMmO->blWuB9V<&x%0b!QXh$&9MMkg~LG*=$L@1H%$Fu>XDB3mvh&vphngwnh6~Cg#ZNHAkbK6T;EuSxZzYny-*&QcbLuB zGQ?E`p$VHQkSd&)xC#QlAOHdP379$raf>dW)D`)C<-rqL`bOtP=P8FGY^DnVQR_T2 z*aHF(=$wG5OX!yDoRiHx#Jr1`U!(5F+hw<#P1{YjG;(NJ)AwB0feV|t0W62F%hgei zhX4d1&_ux0DGV-Yq7m#`4;dDyrKTJEc^77o((lSHoSoHJ0OjqU3knJ*WRO;ey9O$9 zDuiad|F4bmcjyH_LI45~$bf*UQ%v1r>X-};W7iA`i0_ViqW*dD{zis}roFpF?N^$L zW=3&w@yBT&)X9#437dH`TLsTN#Kx$|PBMX?Apn8Q37ERY)G?;6$^2-J=!`%`Ma5o? zlSA&?*}mEQEo#`$`0=J?7}&?U z$f-FyQBcf-eS9DQ0SJUbz|=XW?g=F^4-=`Ztn8`h27jl}N`eYcqBdWmHZF__Lahs% z3fK>W0)t%$KmY>m5uomAk4(qg)ulV2y1M#V@jJfbJ#+f?cY3A6G_}-L=VT?#gRKgi zM$~-8TsftgHoHLp0uZo9z|=ja4zgx20fx+dN_9O}h~1POvAn;>3B)OK(6gQb7e^;oBO6P+SayWEn=w9Qx(Hq%Ed zK*yw=GCPJtV6PQ_RwfV2n=x(5%y3d96$m&%z|=>kUUI@2hn>*9NmFnCMavEWxw%Fn zH(etle-n`X4$WEz{}uuEVl)0Auls%b`cUB7;PdBDncttN#0 zX1dDuht(7Hn(lDM0$33_4Z9h;6)E2!009U@OMp7*Km65fE7n;5MH0A?0p&=8hDDyC zVUZW9U((Ee?8L`P-=qTCQ{bEk2qz!_0SKs0(yU?0{%EZKk*b%?R3p8EAR)$|%I?t` zHS%;2_H(gmrNt%(5?_dN$pnst00gWP*webj7#UPcZI*=RAqiU`q9znovOQ5O;Uje3(lW8l$CYU_X zmQyxxFa%;ppl0vg#)UN&ASXCUte^Cj);=2Rf1kh|k`ug+5B}r8fdh}#JX&iz-Ywc+ zt%#gL=o@7iYJNYZrv*5dL6ZPl~4s>OD$)(t_WVau+S`)vv|(n5r&*(wg$fk5sA%mt=7Cv&%yy@jaj zr0hM<{74NL*+<=w8de{SsEOq!**;(Q*8X1{M9mPiB5b-c%QwcN`p{B~iahB;AT@!g z&&jCkq|{XGZ&lahK@ytwJj$ZkR;DCs ze=aB}m|0w0{Bf%vV)PHf7Ng9gQ6f&`;|sPeqZbQpwbA# zF8ABQpiCMNfB*z?B=FHkA6+XGfry%fY_qx^FViT<@5Wu!3}#wvITkh!hX4d15HtbJ z;{QcWa(re$>1>pkovfDH{Q=p}!t7yp*8kMbSO7#W3;Y}c0SNd_K+lX>pZQ&*4zqqE zs0NLETg1BsK>hz@^GFF?c>uN}Gl{T8hMt5W009W3O~870q*`om>20Ei=$&iJ)Ak}J zJ957*CK-jB5P(3U3G8AsdWqV6iP|_HMa^)c#b&d#U<(2efIt8QY(AVVQM-50ph2e= z6%}m^z*RR)7M50(pl)vD1zteFD*~5&cb{ABj0Nxti)+DLrD2hmyXKT_e-Js_M6m|} z2tdFw0&2F^X*o@!Mt zB!I9vm?^jf0SG_<0@)Kl*s^EGkr03Y1R&rdfx^fB*!1BY?2^mZQW20SG`K z!2~w%vVLmIu>go%f(rwoLjVF0@R0z*=3}lB69gatfdmsk*bk2%A^gNiYzA00ba_uu%pe009U< zz%K%YrBx;Es@vdGYjLeU6D%~2;zkR1RwwbKL{Xfe&i!jKmY;| zfIuSwgpHyA0SG_<0$ve7*u2V4f`Nel1g8JjcaLB!fdBbyD?&uh7D?|{cq;hsC6 zU@Sl;#Ml=C5Xg!EB9|354uSv#AOHbZ2_S5)<_vy800IzzKvo10wydym5Ck9q0SLHC z0AX`AXYdOG5P$##vLcX!u$2t`a3W&?vZBsG5P$##AP@?H97HY@|40M^5P$##AdnFO zge@an> zT2+G5g#?>qAOHafKp-3f2wOOuNd*EBfB*zSB7m@k1e#|}7wL!uL2tWV= z5QsAYge}gwhwl)800bb=h5*9W1_>M7C$QZ&ra#130Qd6=4zhEGTx~Sqly#Y!)D50s;_#Knw^Bl)ybFahnnYUvqL1Vao|0 z2SWe?5D1 z{Q2`w%Gr{m1`sw!GX}S^CQ!1^m@|AI3y?J&4vaqmwch?@Ig0MGH&;S;j%B+}m_y{8 z$OfE%00bb=A%S1%*M<)F$nZyXQFhUClf>7B5~rFbMl$*hJXE zpiCMNfB*z65|F5Enlx$B=`wkZMYAnUeXX{(wrt_Tg@r9Q#^pQ07MGmDPY6H&0^1N! zzv;yixl6a%Y~^3I-1e@ouU{Z>8)3y@h(-{$5Mh%P1RxM&0@EKEc%tKD0o00{Eus6K zY0(8hdRRk4!vc*s85Mx-z)T`?fuY4P1Rwx`a0p1;?vSvVdvJBOQ&cN%CoM0i6*u0t z?V#)-Y(bI5E(9O|fe;C3aLEHo?r@3Qx&V^xruGXK<%)m-JP=hL3Vpf+#c7n0YN->kfm3t z53?d{3OLdSAoQlaJEA_3QsZSS1d>O!c`S*Wi+J3H$z9KCtbFxc1O8 zudJ->G~2dq+Ozfawh^|-o_`SN85*X#Qm}2Z!Ip;vjwyTaOOB5P@QS+5OBdpa^ujx8 z0BXg(sxHKdYHj^lb>*%${gFM>IJ!fvxPIyi4eBw3oLsijdec>c^(JsmQE@N?AdqMR z)Jb`HUGaQ7UIocwtZwsW;j_ zgSF|g7Mrbo74M@pYx83gx8Bx_=3vN*uyya=eNhfRWP0cc!*)>q49lA_ZOY6{k7a)d zKpwx<4&ly0l*q_A{|*MdZv4OC`E8lZ4q9 z0uX>eKm=Ac)=2@GkFQyYTD@9wCu@Ck5K&0nCahh%_60o(vQrTD)3s?u*cuaiF5N`g z4+0Q?K!60Oi#mWSQQNGR+qqr4b}j8-x2%7XxQ)`|9}CLM%dI|gkcmS!h3$z<5@ufr zKmY;M4>1V~`bjyvuc)kXIFv#xw4wqpU*iZk7lr)a6Soj+>D6>656`5H-CY}=Wyk>-65Znez;GUDXO$n7)CIAY(ByJCB3X^XI zV7rY;tHNfit8o3aO)6}F00bZqFaheG+ySfQ_SYUgdYJjS-p}1y8w+N3{@+O4&S~?D z^p2Y1+iQ7#^=z_2xh_IO{0R+U!_Z|cR5t|TzKy(C5UBfga_W6$;JNAPwUg9xd$6*yvZqbxfeG8lkt1t0+U6Jm`NXEf*n$8AAYcfX zy2aEnrmlfVa0H5ri`Nwt6dW$z4+NCT5!KbzPpS3R*OvXjgv~gp(Kc_Z;GHTULCoip zlELchHy+JcfRt$12mvn%nEJ)kGp4@rGC;?IlF-#@pw4mP9>_DyYQ;^_Vr??eKt;~v zjSAjFa`*zr@(Fh!0D%}2Fm;NlTVfnS>|B?qZPFAb-_v?d5Y8)4t?q0Rx*5fIzYcn7YK&Danf3ooFR)mnaV|b;qN&o`fQ7CRxF_6me^t0c?Q)1kxv9 z>JU?xq<;i^20=i1Fk5+HT5p?zu%D~V(1gu6+E^gZ7mU#EzvT*u;~@Zn=m|8|8Ry4Y z)C#X%GRoJn0Lqs;lt<bSLNr@HYj6QIxIog8v`@ffNKxU191B zx*}7+iFlI+mzWWhW+dghh+S!weCWbvQa3k%RZzbo7(D;hDm(ZG0uX3Pz|;|@u3*qe zODb-CSIg~b4FWk(UODp;&q##LWQz*w+j`(~ybA7*^)J(M87O=p0D&d~=0%V{Hg$xl zE1EX4c9Vcw)8)#q{k44Hf`@_3-<4@#3l}aN(a_Lvi&X!hOpj%M2tdFu0;(LJHgiHU zeOCPP)zszn_4Uun^I=hVFM-{nX-)`R697GtK2hTKLj50LE2R~j^RK!j9*kxho4x33LrEZUEnbP^*cJ^peH>ZVd z+fW-jbjRv4Z%_TUhn5k7W}0<b)>#ykWd0D;s5)Pk?q2%%H7zB%0fdB*`0D;a3NZhWJxEX;9bYfwIt+Slq zcL+cL0uZo9K;mY)Bu~*&Z_Vg7h7h)GfbcH_AOL~T37kE?;*SX(3m~EUt)`)wDdro3 z;Eu=zK^2=2fB*y_&>;a$7W$}W!ai7Cl;)8U8=smcBM4g)3DyvR00bZqDglk0d|tvf zRf#r>QVtHh)pRVv)GYis z1Rwwb2tWV=Ng}Xz$ezbD79dGEPOK1s00bZa0SG_<0uYD|fx^-?KmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P(4E1eh0~b4Kg|0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Iz*69L8o#3{G%6#@`|00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_&^dwsj0M_l>SQiGL7)00bZafs6=j_u^rPjV?cOt~qGN0f$d}cv literal 0 HcmV?d00001 From b3cc33c875c62d78652da8c4bb21d2b8f2c85942 Mon Sep 17 00:00:00 2001 From: Josh Tomlinson Date: Mon, 11 Dec 2017 17:32:56 -0500 Subject: [PATCH 2/2] Oops, code in wrong method. Fixed --- hooks/tk-multi-publish2/basic/collector.py | 32 ++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/hooks/tk-multi-publish2/basic/collector.py b/hooks/tk-multi-publish2/basic/collector.py index 19c8dd8..8748c72 100644 --- a/hooks/tk-multi-publish2/basic/collector.py +++ b/hooks/tk-multi-publish2/basic/collector.py @@ -227,6 +227,30 @@ def _collect_session_geometry(self, parent_item): :param parent_item: Parent Item instance """ + geo_item = parent_item.create_item( + "maya.session.geometry", + "Geometry", + "All Session Geometry" + ) + + # get the icon path to display for this item + icon_path = os.path.join( + self.disk_location, + os.pardir, + "icons", + "geometry.png" + ) + + geo_item.set_icon_from_path(icon_path) + + def _collect_session_cameras(self, parent_item): + """ + Creates items for each camera to be exported. + + :param parent_item: + :return: + """ + # get the icon path to display for camera items icon_path = os.path.join( self.disk_location, @@ -257,14 +281,6 @@ def _collect_session_geometry(self, parent_item): cam_item.properties["camera_name"] = camera_name cam_item.properties["camera_shape"] = camera_shape - def _collect_session_cameras(self, parent_item): - """ - Creates items for each camera to be exported. - - :param parent_item: - :return: - """ - def collect_playblasts(self, parent_item, project_root): """ Creates items for quicktime playblasts.