Maya から Alembic をパブリッシュする

Maya から Alembic をパブリッシュする

このチュートリアルでは、Maya からジオメトリのグループをパブリッシュする場合に Alembic ファイルを書き出せるように Multi Publish を設定する方法について説明します。

作業を開始する前に

Maya から Alembic キャッシュ ファイルをパブリッシュする場合は、AbcExportプラグインがプラグイン マネージャにロードされていることを確認してください。また、グループ化されたメッシュを持つショット シーンをパブリッシュ可能な状態にする必要があります。

 

ae_prerequisites.ja.png

手順 1 - 環境を準備する

まず、Shot_Step 環境用の tk-multi-publish アプリをインストールします。

アプリを環境に追加するだけでなく、アプリ ストアからダウンロードして最新のバージョンを実行していることも確認してください。

インストールしたら、通常 <pipeline_configuration_root>/config/env/Shot_Step.yml にある Shot_Step 環境ファイルを開き、変更したい tk-maya エンジンにある tk-multi-publish アプリのエントリを見つけます。

engines:
  tk-maya:
    apps:
      tk-multi-publish:
        ...

ヒント: アプリの新しい設定を試してみる場合は、環境内でエントリを複製し、別の名前を付けます。多くのアプリで、メイン メニューで区別できるように個別の表示名もサポートしています。

この例では、アプリ名と表示名をそれぞれ tk-multi-publish-alembic-examplePublish Alembic Example に変更します。初期設定は次のようになります。

tk-multi-publish-alembic-example:
  allow_taskless_publishes: true
  display_name: Publish Alembic Example
  expand_single_items: false
  hook_copy_file: default
  hook_post_publish: default
  hook_primary_pre_publish: default
  hook_primary_publish: default
  hook_scan_scene: default
  hook_secondary_pre_publish: default
  hook_secondary_publish: default
  hook_thumbnail: default
  location: {name: tk-multi-publish, type: app_store, version: v0.2.7}
  primary_description: Publish and version up the current work file
  primary_display_name: Current Work File
  primary_icon: ''
  primary_publish_template: maya_shot_publish
  primary_scene_item_type: work_file
  primary_tank_type: Maya Scene
  secondary_outputs: []
  template_work: maya_shot_work

これらの設定の一部を変更しますが、完全なリファレンスとしては Multi Publish のマニュアルを参照してください。

設定を保存し、エンジンとアプリを Maya に再ロードします。メイン メニューに新しい Publish Alembic Example エントリが追加されました。

手順 2 - シーンをスキャンする

アプリが最初に行うことは、パブリッシュする対象のシーンをスキャンすることです。これを行うために、hook_scan_scene 設定で指定されたフックを使用します。既定の実装ではシーン自体を検索するだけなので、これを開始点として、シーンからグループ化されたジオメトリを検索するように拡張します。

簡単にまとめると、この実装の開始点として既定のフックを使用するには、以下を実行する必要があります。

  • 既定の実装を見つけます。これは <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/scan_scene_tk-maya.py にあります。
  • このフックを、現在のパイプライン設定の hooks ディレクトリ(<pc_root>/config/hooks など)にコピーします。
  • 一意の名前(alembic_example_scan_scene.py など)に変更します。
  • このフック hook_scan_scene: alembic_example_scan_scene を使用するように hook_scan_scene 設定を更新します。

アプリは作成されたバージョンの scan scene フックを使用するので、先に進んで開きます。

フックはシーンで見つかった項目のリストを返します。既定の実装ではシーン自体を検索するだけなので、1 つまたは複数のメッシュを含むすべての最上位グループを検索するように拡張します。これを行うには、実行メソッドの最後に次のコードを追加します。

...

# look for root level groups that have meshes as children:
for grp in cmds.ls(assemblies=True, long=True):
    if cmds.ls(grp, dag=True, type="mesh"):
        # include this group as a 'mesh_group' type
        items.append({"type":"mesh_group", "name":grp})

...

項目をリストに追加するときに、タイプ mesh_group が指定されることに注意してください。

items.append({"type":"mesh_group", "name":grp})

この type がアプリによってどのように使用され、出力が各項目に関連付けられるのかは、すぐにわかるでしょう。これは重要なので忘れないようにしてください。

ここをクリックすると、alembic_example_scan_scene.py の完全な内容が表示されます。

import os
import maya.cmds as cmds

import tank
from tank import Hook
from tank import TankError

class ScanSceneHook(Hook):
    """
    Hook to scan scene for items to publish
    """

    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item

                            name:   String
                                    Name to use for the item in the UI

                            description:    String
                                            Description of the item to use in the UI

                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.

                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.

                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """   

        items = []

        # get the main scene:
        scene_name = cmds.file(query=True, sn=True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")

        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':            
        items.append({"type": "work_file", "name": name})

        # look for root level groups that have meshes as children:
        for grp in cmds.ls(assemblies=True, long=True):
            if cmds.ls(grp, dag=True, type="mesh"):
                # include this group as a 'mesh_group' type
                items.append({"type":"mesh_group", "name":grp})

        return items

シーンのメッシュグ ループの検索方法を指定したら、次に、それらのグループでどの出力を使用できるかを指定します。

手順 3 - 出力を定義する

Multi Publish アプリには 2 種類の出力があります:

  • Primary - 通常、シーン ファイルを表現するためにプライマリ出力が使用されます。プライマリ出力は 1 つのみ存在します。
  • Secondary - 追加でパブリッシュされるものはセカンダリ出力として表示されます。これらは必要なだけ定義することができます。

これらはメイン インタフェースのさまざまな領域に表示されます。

 

ae_outputs.ja.png

この例では、シーン内のすべての最上位メッシュ グループに対する新しいAlembic キャッシュのセカンダリ出力を定義しています。これを行うには、tk-multi-publish-alembic 構成の secondary_outputs 設定を編集します。

いくつかの詳細を記入し、重要事項について確認しましょう。

...
secondary_outputs:
- description: 'Publish Alembic Cache data for the model'
  display_group: Caches
  display_name: Alembic Cache
  icon: 'icons/alembic_output.png'
  name: alembic_cache
  publish_template: maya_shot_mesh_alembic_cache
  required: false
  scene_item_type: mesh_group
  selected: false
  tank_type: 'Alembic Cache'
...

これらのほとんどの内容は明確ですが、さらなる詳細については Multi Publish のリファレンス ドキュメントを参照してください。

この例で注意すべき設定は次のとおりです。

name: alembic_cache

名前はすべての出力で一意でなければならず、プライマリ出力用に予約されている primary は使用できません。この名前は後で実際にパブリッシュを実行するときに使用します。

scene_item_type: mesh_group

前の手順 2 のスキャン シーンのフックで各項目について返されたタイプを覚えていますか? 出力の scene_item_type を同じタイプに設定すると、アプリは mesh_group タイプのすべての項目に対して Alembic Cache 出力をパブリッシュするようになります。

ヒント: このメカニズムを使用すると、複数の異なる出力を 1 つの項目タイプに関連付けることができるので、たとえば、後で OBJ 書き出しなど別の出力を追加する場合は、スキャン フックを再度変更する必要がなくなります。

publish_template: maya_shot_mesh_alembic_cache

この設定では、パブリッシュされた Alembic キャッシュ ファイルに使用するテンプレートを指定できます。これにはパブリッシュするときにアクセスできます。

この例では、次のテンプレートが使用されています。

# excerpt from templates.yml
keys:
    ...
    grp_name:
        type: str

paths:        
    ...
    maya_shot_mesh_alembic_cache: '@shot_root/publish/maya/{name}[_{grp_name}].v{version}.abc'

既定の設定を使用している場合、これを templates.yml ファイルに追加することができます。そうでない場合は、正しく動作するようにテンプレートまたはフックを微調整する必要があります。

tank_type: Alembic Cache

これは一意のパブリッシュ タイプで Alembic キャッシュ ファイルを Shotgun に登録する時に使用されます。繰り返しますが、これにはパブリッシュするときにアクセスできます。

icon: 'icons/alembic_output.png'

これは、この新しいタイプの出力を表すためにアプリが使用するアイコンです。このアイコンを保存します。

保存先は、設定の 'icons' ディレクトリ(<pc_root>/config/icons/alembic_output.png など)です。

これがどのように見えるか確認してみます。設定を保存し、Maya でアプリを再ロードし、テストのショット シーンを開き、メニューから Publish Alembic Example コマンドを実行します。すべて計画通りに実行すると、いくつかのセカンダリ パブリッシュが UI にリストされます。

 

ae_alembic_outputs.ja.png

Alembic キャッシュ ファイルを書き出して Shotgun に登録するためのコードを追加する必要があるので、まだ Publish をクリックしないでください。

手順 4 - パブリッシュ前の検証

パブリッシュは 3 つのステージに分けられます。

  • パブリッシュ前
  • パブリッシュ
  • パブリッシュ後

1 つ目は「パブリッシュ前」で、パブリッシュする項目の検証を行い、問題をユーザに報告することができます。

シーンをスキャンする場合と同様、「パブリッシュ前」は hook_secondary_pre_publish 設定によりアプリ設定で定義されるフックを介して実装されます。

Step 2 の指示に従って、既定のフック <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/secondary_pre_publish_tk-maya.py を設定のフック ディレクトリにコピーし、名前を alembic_example_secondary_pre_publish.py に変更します。

次に、構成の設定を次のように編集します。

hook_secondary_pre_publish: alembic_example_secondary_pre_publish

アプリは「パブリッシュ前」のバージョンのフックを使用するようになるので、先に進んで、それを開きます。

フックはメインの入力としてタスクのリストを取ります。

def execute(self, tasks, work_template, progress_cb, **kwargs):
    ...

このリストは UI からのユーザ選択に基づいているので、パブリッシュの対象として選択したもののみが含まれています。

各タスクは item および outputを含むディクショナリです。

  • この項目は、前の手順 2 でスキャン シーン フックから返された項目です。
  • 出力には、手順 3 でセカンダリ出力用に設定した name、publish_template および tank_type が含まれています。

このフックの既定の実装はユーザが選択したすべてのタスクを反復処理するための基礎を提供するだけなので、出力の処理方法が不明な場合はエラーが報告されます。

ユーザはスキャン シーン フックによって返されたグループを削除または変更している可能性があります。そのため、この実装を拡張して、そのような状況になっていないこと、またすべてがパブリッシュ可能な状態であることを確認する必要があります。

これを実行するには、最初に:

# pre-publish item here, e.g.
#if output["name"] == "foo":
#    ...
#else:
# don't know how to publish this output types!
errors.append("Don't know how to publish this item!")

を以下に置換します

# pre-publish alembic_cache output
if output["name"] == "alembic_cache":
    errors.extend(self._validate_item_for_alembic_cache_publish(item))
else:
    # don't know how to publish this output types!
    errors.append("Don't know how to publish this item!")

次に、新しい検証メソッドを PrePublishHook クラスに追加します。

def _validate_item_for_alembic_cache_publish(self, item):
    """
    Validate that the item is valid to be exported 
    to an alembic cache
    """
    errors = []
    # check that the group still exists:
    if not cmds.objExists(item["name"]):
        errors.append("This group couldn't be found in the scene!")

    # and that it still contains meshes:
    elif not cmds.ls(item["name"], dag=True, type="mesh"):
        errors.append("This group doesn't appear to contain any meshes!")

    # finally return any errors
    return errors

検出された問題が返され、ユーザはパブリッシュ前に修正することができます。もちろん、これを拡張して項目のより包括的な検証を行うこともできます。

ここをクリックすると、alembic_example_secondary_pre_publish.py の完全な内容が表示されます。

import os
import maya.cmds as cmds

import tank
from tank import Hook
from tank import TankError

class PrePublishHook(Hook):
    """
    Single hook that implements pre-publish functionality
    """
    def execute(self, tasks, work_template, progress_cb, **kwargs):
        """
        Main hook entry point
        :tasks:         List of tasks to be pre-published.  Each task is be a 
                        dictionary containing the following keys:
                        {   
                            item:   Dictionary
                                    This is the item returned by the scan hook 
                                    {   
                                        name:           String
                                        description:    String
                                        type:           String
                                        other_params:   Dictionary
                                    }

                            output: Dictionary
                                    This is the output as defined in the configuration - the 
                                    primary output will always be named 'primary' 
                                    {
                                        name:             String
                                        publish_template: template
                                        tank_type:        String
                                    }
                        }

        :work_template: template
                        This is the template defined in the config that
                        represents the current work file

        :progress_cb:   Function
                        A progress callback to log progress during pre-publish.  Call:

                            progress_cb(percentage, msg)

                        to report progress to the UI

        :returns:       A list of any tasks that were found which have problems that
                        need to be reported in the UI.  Each item in the list should
                        be a dictionary containing the following keys:
                        {
                            task:   Dictionary
                                    This is the task that was passed into the hook and
                                    should not be modified
                                    {
                                        item:...
                                        output:...
                                    }

                            errors: List
                                    A list of error messages (strings) to report    
                        }
        """       
        results = []

        # validate tasks:
        for task in tasks:
            item = task["item"]
            output = task["output"]
            errors = []

            # report progress:
            progress_cb(0, "Validating", task)

             # pre-publish alembic_cache output
            if output["name"] == "alembic_cache":
                errors.extend(self._validate_item_for_alembic_cache_publish(item))
            else:
                # don't know how to publish this output types!
                errors.append("Don't know how to publish this item!")       

            # if there is anything to report then add to result
            if len(errors) > 0:
                # add result:
                results.append({"task":task, "errors":errors})

            progress_cb(100)

        return results

    def _validate_item_for_alembic_cache_publish(self, item):
        """
        Validate that the item is valid to be exported 
        to an alembic cache
        """
        errors = []
        # check that the group still exists:
        if not cmds.objExists(item["name"]):
            errors.append("This group couldn't be found in the scene!")

        # and that it still contains meshes:
        elif not cmds.ls(item["name"], dag=True, type="mesh"):
            errors.append("This group doesn't appear to contain any meshes!")

        # finally return any errors
        return errors

手順 5 - パブリッシュ

パブリッシュ ステージでは、Alembic キャッシュ ファイルを各項目のパブリッシュ パスに書き出し、Shotgun に登録します。この例では、これも最後に行う必要があります。

このステージは hook_secondary_publish 設定によりアプリ設定で定義されるフックを介して実装されます。

ここでも、前の指示に従って既定のフック <code_root>/install/apps/app_store/tk-multi-publish/<version>/hooks/secondary_publish_tk-maya.py を設定のフック ディレクトリにコピーし、名前を alembic_example_secondary_publish.py に変更します。次に、構成の設定を次のように編集します。

hook_secondary_publish: alembic_example_secondary_publish

アプリは「パブリッシュ」のバージョンのフックを使用するようになるので、先に進んで、それを開きます。

「パブリッシュ」フックには、いくつかの入力とともにタスクのリストが提供されます。

def execute(self, tasks, work_template, comment, thumbnail_path, 
            sg_task, primary_publish_path, progress_cb, **kwargs):
    ...
  • commentthumbnail_path および sg_task は、UI を介してユーザによって提供される情報を表します。
  • primary_publish_path は、プライマリ パブリッシュのパスです。この場合はシーン ファイル自身です。

「パブリッシュ前」フックの場合と同様、既定の実装はタスクを反復処理するための基礎を提供するだけなので、まずいくつかのコードを追加し、新しい alembic_cache 出力を処理できるように拡張します。

これを行うには、以下を:

# publish item here, e.g.
#if output["name"] == "foo":
#    ...
#else:
# don't know how to publish this output types!
errors.append("Don't know how to publish this item!")

次のように置換します。

# publish alembic_cache output
if output["name"] == "alembic_cache":
    try:
       self._publish_alembic_cache_for_item(item, output, work_template, primary_publish_path, 
                                            sg_task, comment, thumbnail_path, progress_cb)
    except Exception, e:
       errors.append("Publish failed - %s" % e)
else:
    # don't know how to publish this output types!
    errors.append("Don't know how to publish this item!")

次に、新しいパブリッシュ メソッドを PublishHook クラスに追加します。

def _publish_alembic_cache_for_item(self, item, output, work_template, primary_publish_path, 
                                    sg_task, comment, thumbnail_path, progress_cb)
    ...

この新しいメソッドの動作を確認しましょう。

まず、このメソッドは work_template を使用して現在のシーン パスからフィールドのディクショナリを抽出します。

    scene_path = os.path.abspath(cmds.file(query=True, sn=True))
    fields = work_template.get_fields(scene_path)
    publish_version = fields["version"]

次に、グループ名をフィールドに追加し、Alembic キャッシュ ファイルに使用するパブリッシュ パスを作成します。

    fields["grp_name"] = group_name
    publish_path = publish_template.apply_fields(fields)

このパスを使用し、Alembic キャッシュ書き出しコマンド AbcExport を使用してグループをパブリッシュ パスに書き出します。

    frame_start = int(cmds.playbackOptions(q=True, min=True))
    frame_end = int(cmds.playbackOptions(q=True, max=True))
    abc_publish_path = publish_path.replace("\\", "/")
    abc_export_cmd = ("AbcExport -j \"-fr %d %d -root %s -file %s\"" 
                        % (frame_start, frame_end, item["name"], abc_publish_path))
    try:
        self.parent.log_debug("Executing command: %s" % abc_export_cmd)
        mel.eval(abc_export_cmd)
    except Exception, e:
        raise TankError("Failed to export Alembic Cache: %s" % e)

最後に、パブリッシュされた Alembic キャッシュ ファイルを Shotgun に登録します。

    self._register_publish(publish_path, ...

これで完了です。

ここをクリックすると、alembic_example_secondary_publish.py の完全な内容が表示されます。

import os
import shutil
import maya.cmds as cmds
import maya.mel as mel

import tank
from tank import Hook
from tank import TankError

class PublishHook(Hook):
    """
    Single hook that implements publish functionality for secondary tasks
    """    
    def execute(self, tasks, work_template, comment, thumbnail_path, sg_task, primary_publish_path, progress_cb, **kwargs):
        """
        Main hook entry point
        :tasks:         List of secondary tasks to be published.  Each task is a 
                        dictionary containing the following keys:
                        {
                            item:   Dictionary
                                    This is the item returned by the scan hook 
                                    {   
                                        name:           String
                                        description:    String
                                        type:           String
                                        other_params:   Dictionary
                                    }

                            output: Dictionary
                                    This is the output as defined in the configuration - the 
                                    primary output will always be named 'primary' 
                                    {
                                        name:             String
                                        publish_template: template
                                        tank_type:        String
                                    }
                        }

        :work_template: template
                        This is the template defined in the config that
                        represents the current work file

        :comment:       String
                        The comment provided for the publish

        :thumbnail:     Path string
                        The default thumbnail provided for the publish

        :sg_task:       Dictionary (shotgun entity description)
                        The shotgun task to use for the publish    

        :primary_publish_path: Path string
                        This is the path of the primary published file as returned
                        by the primary publish hook

        :progress_cb:   Function
                        A progress callback to log progress during pre-publish.  Call:

                            progress_cb(percentage, msg)

                        to report progress to the UI

        :returns:       A list of any tasks that had problems that need to be reported 
                        in the UI.  Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            task:   Dictionary
                                    This is the task that was passed into the hook and
                                    should not be modified
                                    {
                                        item:...
                                        output:...
                                    }

                            errors: List
                                    A list of error messages (strings) to report    
                        }
        """
        results = []

        # publish all tasks:
        for task in tasks:
            item = task["item"]
            output = task["output"]
            errors = []

            # report progress:
            progress_cb(0, "Publishing", task)

            # publish alembic_cache output
            if output["name"] == "alembic_cache":
                try:
                    self._publish_alembic_cache_for_item(item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb)
                except Exception, e:
                    errors.append("Publish failed - %s" % e)
            else:
                # don't know how to publish this output types!
                errors.append("Don't know how to publish this item!")

            # if there is anything to report then add to result
            if len(errors) > 0:
                # add result:
                results.append({"task":task, "errors":errors})

            progress_cb(100)

        return results

    def _publish_alembic_cache_for_item(self, item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Export an Alembic cache for the specified item and publish it
        to Shotgun.
        """
        group_name = item["name"].strip("|")
        tank_type = output["tank_type"]
        publish_template = output["publish_template"]        

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]

        # update fields with the group name:
        fields["grp_name"] = group_name

        # create the publish path by applying the fields 
        # with the publish template:
        publish_path = publish_template.apply_fields(fields)

        # build and execute the Alembic export command for this item:
        frame_start = int(cmds.playbackOptions(q=True, min=True))
        frame_end = int(cmds.playbackOptions(q=True, max=True))
        # The AbcExport command expects forward slashes!
        abc_publish_path = publish_path.replace("\\", "/")
        abc_export_cmd = "AbcExport -j \"-fr %d %d -root %s -file %s\"" % (frame_start, frame_end, item["name"], abc_publish_path)
        try:
            self.parent.log_debug("Executing command: %s" % abc_export_cmd)
            mel.eval(abc_export_cmd)
        except Exception, e:
            raise TankError("Failed to export Alembic Cache: %s" % e)

        # Finally, register this publish with Shotgun
        self._register_publish(publish_path, 
                               group_name, 
                               sg_task, 
                               publish_version, 
                               tank_type,
                               comment,
                               thumbnail_path, 
                               [primary_publish_path])

    def _register_publish(self, path, name, sg_task, publish_version, tank_type, comment, thumbnail_path, dependency_paths=None):
        """
        Helper method to register publish using the 
        specified publish info.
        """
        # construct args:
        args = {
            "tk": self.parent.tank,
            "context": self.parent.context,
            "comment": comment,
            "path": path,
            "name": name,
            "version_number": publish_version,
            "thumbnail_path": thumbnail_path,
            "task": sg_task,
            "dependency_paths": dependency_paths,
            "published_file_type":tank_type,
        }

        # register publish;
        sg_data = tank.util.register_publish(**args)

        return sg_data

ここをクリックすると、Shot_Step 環境における tk-multi-publish-alembic-example の完全な内容が表示されます。

tk-multi-publish-alembic-example:
  allow_taskless_publishes: true
  display_name: Publish Alembic Example
  expand_single_items: false
  hook_copy_file: default
  hook_post_publish: default
  hook_primary_pre_publish: default
  hook_primary_publish: default
  hook_scan_scene: alembic_example_scan_scene
  hook_secondary_pre_publish: alembic_example_secondary_pre_publish
  hook_secondary_publish: alembic_example_secondary_publish
  hook_thumbnail: default
  location: {name: tk-multi-publish, type: app_store, version: v0.2.7}
  primary_description: Publish and version up the current work file
  primary_display_name: Current Work File
  primary_icon: ''
  primary_publish_template: maya_shot_publish
  primary_scene_item_type: work_file
  primary_tank_type: Maya Scene
  secondary_outputs:
  - description: 'Publish Alembic Cache data for the model'
    display_group: Caches
    display_name: Alembic Cache
    icon: 'icons/alembic_output.png'
    name: alembic_cache
    publish_template: maya_shot_mesh_alembic_cache
    required: false
    scene_item_type: mesh_group
    selected: false
    tank_type: 'Alembic Cache'
  template_work: maya_shot_work

これで、ショットのシーンで参照されているアセットに対する Alembic キャッシュをパブリッシュするために必要な設定が完了しました。

設定を保存し、Maya でアプリを再ロードし、テストのショット シーンを開き、メニューから Publish Alembic Example コマンドを実行します。

カスタム スキャン フックで見つかった Alembic キャッシュ項目が UI で選択されていることを確認し、コメントを追加して Publish をヒットします。アプリはまず、新しい「パブリッシュ前」フックを使用して参照が有効であることを検証します。問題がなければ、Alembic キャッシュが書き出され、新しいパブリッシュ フックを使用して Shotgun のパブリッシュ ファイルとして登録されます。

 

ae_success_shotgun.ja.png
 
フォローする

0 コメント

ログインしてコメントを残してください。