[UE5]EUW作っていて困る事あるんですが、コンテンツブラウザでなくExplorerのファイルブラウザーとかディレクトリブラウザーパスをユーザーに選ばせたい場合ってどのように実装してますか?

Pythonを使うパターンであれば、tkinterモジュールを使います。

from tkinter import filedialog
"""
# ファイルーダイアログでファイルを選択する
typ = [('テキストファイル','*.txt')] 
dir = 'C:\\pg'
fle = filedialog.askopenfilename(filetypes = typ, initialdir = dir) 
print("WorkData="+fle)
"""
# フォルダーダイアログでフォルダーを選択する
dir = 'D:/Design/WorkData'
fld = filedialog.askdirectory(initialdir = dir) 
print("WorkData="+fld)

参考URL

https://pg-chain.com/python-filedialog-dir
https://pg-chain.com/python-filedialog

[UE5]Pythonからダイアログメッセージを表示 unreal.EditorDialog.show_message

import unreal
class hoge:
    def show_messageDialog(self):
        title="タイトル"
        message="メッセージ"
        message_type=unreal.AppMsgType.OK_CANCEL
        
        unreal.EditorDialog.show_message(title,message,message_type, default_value=unreal.AppReturnType.NO, message_category=unreal.AppMsgCategory.WARNING)

class_Ins=hoge()
hoge.show_messageDialog()

参考URL

https://docs.unrealengine.com/5.3/en-US/PythonAPI/class/EditorDialog.html#unreal.EditorDialog

PERFORCEやgitや共有フォルダに入れる独立した依存関係のないpython.exeのzipからのインストール方法

1. 作業用フォルダを作成する。

PC内のどこでもいいので、作業用フォルダPythonUSBを作成してください。その配下にpythonフォルダとcodeフォルダを作成します。このPythonUSBは最終的に共有フォルダにそのままコピーします。

├directory
│    └ PythonUSB/     <= 作業用フォルダー
│         ├ python/
│         └ code/
│             └ hello.py
│ 

2. pythonをダウンロードして配置する

pythonのページから、OSに合わせたダウンロードページに遷移してください。今回はWindowsで説明します。

Windowsのリンク先に行くと、バージョンがいくつかありますが、OSのbitに合わせたembeddableパッケージをダウンロードします。今回は、執筆時点で最新の3.12.0バージョン、64-bitを上述のpythonフォルダにダウンロードします。ダウンロードが完了したら、解凍しましょう。解凍後のフォルダ名がpython-3.12.0-embed-amd64と長いので、python-3.12.0に変更します。

3. pipを使えるようにする

先程のpython-3.12.0フォルダ内にpython312._pthがありますので、これをメモ帳で開きます。そして、#import site#を削除してimoprt siteに変更して保存します。

続いて、get-pip.pyのリンクを右クリックして「名前をつけてリンク先を保存」でpython-3.12.0フォルダにダウンロードします。
このファイルをコマンドプロンプトで実行するには、python-3.12.0フォルダをエクスプローラーで開き、アドレスに「cmd」と入力してEnterを押して、コマンドプロンプトを出現させます。そして、python.exe get-pip.pyを実行します。
これでpip installが使用することができるようになりました。

4. 使用するライブラリをインストールする

インストールするには、コマンドプロンプトでpython-3.12.0フォルダに移動して、python.exe -m pip install [ライブラリ]を実行します。例えば、p4vを操作するライブラリp4pythonをインストールするには以下のようにします。必要なライブラリを順次インストールしてください。

python.exe -m pip install p4python

5. 実行用バッチファイルを作成する

バッチファイルをクリックするだけでコードが実行できるようにします。execute.batを以下の位置に作成します。メモ帳のテキストファイルからファイル名を変更することで作成できます。今回はhello.pyというpythonファイルを実行する例を紹介します。

├directory
│    └ PythonUSB/     <= 作業用フォルダー
│         ├ python/
│         └ code/
│             └ hello.py
│         └ execute.bat

hello.pyの中身は以下の通りです。最後にinput関数を入れておくことで、コマンドプロンプトが自動で閉じるのを防いでいます。

print('Hello world!')

input('Close window to enter any key.')

execute.batの中身は以下の通りです。
@echo offがないと、set以下の内容がコマンドプロンプト上に表示されてしまいます。見栄えの問題ですね。
set xxx=yyyは変数を定義しています。この変数を利用する際には、%で挟んで上げる必要があります。
%~dp0は実行されるバッチファイルが置かれているカレントディレクトリを示します。今回の場合では、PythonUSBですね。
pyintpathpython.exeまでのパス、codepathcodeまでのパス、pyfileは実行したいpyファイル名の変数を設定します。
%pyintpath%python.exe %codepath%%pyfile%は、上述の変数を組み合わせてよく使うpython xxx.pyの形式になっています。

@echo off
set cwdirpath=%~dp0
set pyintpath=%cwdirpath%python\python-3.12.0\
set codepath=%cwdirpath%code\
set pyfile=hello.py

%pyintpath%python.exe %codepath%%pyfile%

実行結果は以下の通りです。意図通りの動きをしています。


6. 共有フォルダにコピーする

「PythonProj」フォルダを共有フォルダにコピーします。コピー先でもバッチファイルが実行できるか念のため確認しておきましょう。

pythonUSB.zip

https://drive.google.com/file/d/1OK-1uFEXMsj5JLxIMVtaLjgwIyIVfhvF/view?usp=sharing

または

https://github.com/nobolu-ootsuka-unrealengine/pythonUSB

参考サイト

https://qiita.com/r-shiomoto/items/ea8be09ffc21ea10a867

[ue5] python rename 依存関係のあるファイルをチェックアウトしてからリネームする下調べ

rename_asset(asset, newName) 色々あるが基本はこれでいい。むしろこれしか動かず。

editor_util = unreal.EditorUtilityLibrary()
# 新しい名前
newName = newName
                
# リネームしたいアセット
asset = unreal.load_asset(package_name)
                
# rename実行
editor_util.rename_asset(asset, newName)

複数ファイルに対応する。

    def rename_endZ_remove_loop(self):
        editorAssetLib = unreal.EditorAssetLibrary()
        editor_util = unreal.EditorUtilityLibrary()
        #editorStaticMeshLib = unreal.EditorStaticMeshLibrary()
        MaterialEditingLibrary = unreal.MaterialEditingLibrary()
        asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()

        #import unreal.AssetRegistry
        #AssetRegistry=unreal.AssetRegistry()
        
        EnvName=unreal.Name.cast("/Game/Effects")

        #EnvName=unreal.Name.cast(readDirPath)
        EnvArr=unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)
        
        #EnvArr = asset_registry.get_assets()
        #EnvArr =self.SelectedAssets
        
        unreal.log_warning("main_way_start2 040  unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)")
        unreal.log_warning("main_way_start2 041  get_assets_by_path() EnvArr len= "+str(len(EnvArr)))

        NGlist=[]       
        checkout_Arr=[] 
        checkout_Arr_Str=""
        rename_data_Arr=[]
        total_frames = len(EnvArr)
        text_label = "Rename Execution!"
        with unreal.ScopedSlowTask(total_frames, text_label) as slow_task:
            slow_task.make_dialog(True)               # まだダイアログが表示されていない場合は表示します
            for i in range(total_frames):
                if slow_task.should_cancel():# ユーザーが UI の [Cancel] を押した場合は True
                    break
                slow_task.enter_progress_frame(1)# 1 フレーム次に進めます。
                

                AssetData=EnvArr[i]
                print("AssetData= "+str(AssetData))
                package_name=str(AssetData.package_name)
                print("package_name= "+str(package_name))
                package_name_Arr=package_name.split("/")
                package_name_Arr_len=len(package_name_Arr)
                print("package_name_Arr_len= "+str(package_name_Arr_len))
                assetName=package_name_Arr[package_name_Arr_len-1]
                print("assetName= "+str(assetName))
                assetNameStr=str(assetName)+"."
                
                # 新しい名前
                newName=assetNameStr.replace("Z.","")
                
                # リネームしたいアセット
                asset = unreal.load_asset(package_name)
                
                # 新しいパッケージパス
                new_package_path = package_name+"."
                new_package_path=new_package_path.replace("Z.","")
                
                editor_util.rename_asset(asset, newName)
                
                # リネームデータを作成
                #rename_data = unreal.AssetRenameData(asset, new_package_path, new_name)
                #unreal.EditorUtilityLibrary.rename_asset(rename_data)
                #rename_data_Arr.append(rename_data)
        
        #rename_assets(rename_data_Arr)

依存関係のあるファイルをチェックアウトしてからリネーム

# -*- coding: utf-8 -*- 
import unreal
import sys
import os
import re
import codecs
import os
import datetime
unreal.log("--------------py--start000-----------------")
unreal.log("    ")

class RefferenceCounter():

    def mainWay(self):
        
        self.AssetRegistryLoaded=False
        #----------------------------------------------------------
        self.tickhandle = None
        self.tickhandle = unreal.register_slate_pre_tick_callback(self.testRegistry)
        print("tickhandle="+str(self.tickhandle))

        
    def testRegistry(self,deltaTime):
        unreal.log_warning("ticking...mainWay")
        asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()
        if asset_registry.is_loading_assets():
            unreal.log_warning("still loading...mainWay")
        else:
            unreal.log_warning("ready!.....mainWay")
            if(self.AssetRegistryLoaded==False):
                self.AssetRegistryLoaded=True
                self.textLoad2()
                #self.textLoad()
                
            unreal.unregister_slate_pre_tick_callback(self.tickhandle)
            unreal.unregister_slate_pre_tick_callback(self.tickhandle)

    def getProject_SavedDir(self):
        project_saved_dir=unreal.Paths.project_saved_dir()
        print("project_saved_dir= "+project_saved_dir)
        HD_project_saved_dir=os.path.abspath(project_saved_dir)
        print("HD_project_saved_dir= "+HD_project_saved_dir)
        HD_project_saved_dir_slash=HD_project_saved_dir.replace('\\', '/')
        print("HD_project_saved_dir_slash= "+HD_project_saved_dir_slash)
        return HD_project_saved_dir_slash

    def get_project_dir(self):
        project_dir=unreal.Paths.project_dir()
        print("project_dir= "+project_dir)
        HD_project_dir=os.path.abspath(project_dir)
        print("HD_project_dir= "+HD_project_dir)
        HD_project_dir_slash=HD_project_dir.replace('\\', '/')
        print("HD_project_dir_slash= "+HD_project_dir_slash)
        return HD_project_dir_slash

    def textLoad2(self):
        import codecs
        readPath=self.getProject_SavedDir()+'/RefferenceCounter/SelectedAsset.txt'
        print("readPath= "+readPath)
        fin = codecs.open(readPath, 'r', 'utf_8')
        
        SelectedAssetArr=[]
        for line in fin:
            line=line.replace(" ","")#Space
            line=line.replace(" ","")#TAB
            line=line.replace("\r","")
            line=line.replace("\n","")
            if(line==""):
                pass
            else:
                SelectedAssetArr.append(line)
        #txtData=fin.read()
        print("SelectedAssetArr= "+str(SelectedAssetArr))
        #rejectLines=txtData
        #print("SelectedAssets= "+SelectedAssets)
        self.SelectedAssets=SelectedAssetArr
        self.main_way_start2()

     
    def main_way_start2(self):

        editorAssetLib = unreal.EditorAssetLibrary()
        editor_util = unreal.EditorUtilityLibrary()
        #editorStaticMeshLib = unreal.EditorStaticMeshLibrary()
        MaterialEditingLibrary = unreal.MaterialEditingLibrary()
        asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()

        #import unreal.AssetRegistry
        #AssetRegistry=unreal.AssetRegistry()
        
        EnvName=unreal.Name.cast("/Game/Materials")
        EnvName_Str=editor_util.get_current_content_browser_path()
        EnvName=unreal.Name.cast(EnvName_Str)
        
        #EnvName=unreal.Name.cast(readDirPath)
        EnvArr=unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)
        

        
        unreal.log_warning("main_way_start2 040  unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)")
        unreal.log_warning("main_way_start2 041  get_assets_by_path() EnvArr len= "+str(len(EnvArr)))

        NGlist=[]       
        checkout_Arr=[] 
        checkout_Arr_Str=""
        total_frames = len(EnvArr)
        text_label = "reference And Dependency Checking!"
        with unreal.ScopedSlowTask(total_frames, text_label) as slow_task:
            slow_task.make_dialog(True)               # まだダイアログが表示されていない場合は表示します
            for i in range(total_frames):
                if slow_task.should_cancel():# ユーザーが UI の [Cancel] を押した場合は True
                    break
                slow_task.enter_progress_frame(1)# 1 フレーム次に進めます。
                

                #package_name=EnvArr[i]
                AssetData=EnvArr[i]
                print("AssetData= "+str(AssetData))
                package_name=str(AssetData.package_name)
                print("package_name= "+str(package_name))
                package_name_Arr=package_name.split("/")
                package_name_Arr_len=len(package_name_Arr)
                print("package_name_Arr_len= "+str(package_name_Arr_len))
                assetName=package_name_Arr[package_name_Arr_len-1]
                print("assetName= "+str(assetName))
                
                
                dependency_options=unreal.AssetRegistryDependencyOptions(include_soft_package_references=True, include_hard_package_references=True, include_searchable_names=False, include_soft_management_references=False, include_hard_management_references=False)
                #
                asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()
                dependencies=unreal.AssetRegistry.get_dependencies(asset_registry,package_name, dependency_options)
                referencers=unreal.AssetRegistry.get_referencers(asset_registry,package_name, dependency_options)
                
                dependencies_len=len(dependencies)
                referencers_len=len(referencers)
                print("----------------referencers_len= "+str(referencers_len)+"-------------------")

                dependencies_str=self.array_to_str(dependencies)
                referencers_str=self.array_to_str(referencers)
                all_ref_dependencys_str=dependencies_str+"|"+referencers_str
                all_ref_dependencys_len=referencers_len+dependencies_len
                #A=assetName+","+assetPath
                A=assetName+","+str(referencers_len)+","+referencers_str+","+str(dependencies_len)+","+dependencies_str+","
                A=A+str(all_ref_dependencys_len)+","+all_ref_dependencys_str
                
                checkout_Arr_Str=checkout_Arr_Str+all_ref_dependencys_str+"|"+package_name+"|"
                #A=A+","+str(package_name)
                #for dep in dependencies:
                #    A=A+","+str(dep)
                NGlist.append(A)
                unreal.log_warning(A)
        
        # チェックアウト
        checkout_Arr=checkout_Arr_Str.split("|")
        for checkout_file_path in checkout_Arr:
            if checkout_file_path=="":
                pass
            else:
                unreal.EditorAssetLibrary.checkout_asset(checkout_file_path)
    
        
        self.rename_endZ_remove_loop(EnvName_Str)     
        
    def rename_endZ_remove_loop(self,EnvName_Str):
        editorAssetLib = unreal.EditorAssetLibrary()
        editor_util = unreal.EditorUtilityLibrary()
        #editorStaticMeshLib = unreal.EditorStaticMeshLibrary()
        MaterialEditingLibrary = unreal.MaterialEditingLibrary()
        asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()

        #import unreal.AssetRegistry
        #AssetRegistry=unreal.AssetRegistry()

        EnvName=unreal.Name.cast(EnvName_Str)
        
        #EnvName=unreal.Name.cast(readDirPath)
        EnvArr=unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)
        
        #EnvArr = asset_registry.get_assets()
        #EnvArr =self.SelectedAssets
        
        unreal.log_warning("main_way_start2 040  unreal.AssetRegistry.get_assets_by_path(asset_registry,EnvName,True,False)")
        unreal.log_warning("main_way_start2 041  get_assets_by_path() EnvArr len= "+str(len(EnvArr)))

        NGlist=[]       
        checkout_Arr=[] 
        checkout_Arr_Str=""
        rename_data_Arr=[]
        total_frames = len(EnvArr)
        text_label = "Rename Execution!"
        with unreal.ScopedSlowTask(total_frames, text_label) as slow_task:
            slow_task.make_dialog(True)               # まだダイアログが表示されていない場合は表示します
            for i in range(total_frames):
                if slow_task.should_cancel():# ユーザーが UI の [Cancel] を押した場合は True
                    break
                slow_task.enter_progress_frame(1)# 1 フレーム次に進めます。
                

                AssetData=EnvArr[i]
                print("AssetData= "+str(AssetData))
                package_name=str(AssetData.package_name)
                print("package_name= "+str(package_name))
                package_name_Arr=package_name.split("/")
                package_name_Arr_len=len(package_name_Arr)
                print("package_name_Arr_len= "+str(package_name_Arr_len))
                assetName=package_name_Arr[package_name_Arr_len-1]
                print("assetName= "+str(assetName))
                assetNameStr=str(assetName)+"."
                
                # 新しい名前
                newName=assetNameStr.replace("Z.","")
                
                
                # リネームしたいアセット
                asset = unreal.load_asset(package_name)
                
                # 新しいパッケージパス
                new_package_path = package_name+"."
                new_package_path=new_package_path.replace("Z.","")
                
                editor_util.rename_asset(asset, newName)
                
                # リネームデータを作成
                #rename_data = unreal.AssetRenameData(asset, new_package_path, new_name)
                #unreal.EditorUtilityLibrary.rename_asset(rename_data)
                #rename_data_Arr.append(rename_data)
        
        #rename_assets(rename_data_Arr)

Class_Ins=RefferenceCounter()
Class_Ins.mainWay()

CGWORLD.JPさんから引用、「リネームとリダイレクタはある意味密接な関係にある…

KAEditorUtilityBlueprintLibrary.h

#pragma once
 
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "KAEditorUtilityBlueprintLibrary.generated.h"
 
UCLASS()
class KAEDITORUTILITYTEST_API UKAEditorUtilityBlueprintLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
	//RedirectorをFixUpする
	UFUNCTION(BlueprintCallable, Category = "KAEditorUtility")
	static void FixupRedirectors(const TArray<FAssetData>& Assets, bool bCheckoutDialogPrompt);
};

KAEditorUtilityBlueprintLibrary.cpp

#include "KAEditorUtilityBlueprintLibrary.h"
#include "AssetToolsModule.h"
 
void UKAEditorUtilityBlueprintLibrary::FixupRedirectors(const TArray<FAssetData>& Assets, bool bCheckoutDialogPrompt)
{
	FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
	//Redirectorの取得
	TArray<UObjectRedirector*> Redirectors;
	for (FAssetData Object : Assets)
	{
		if (UObjectRedirector* Redirector = Cast<UObjectRedirector>(Object.GetAsset()))
		{
			Redirectors.Emplace(Redirector);
		}
	}
 
	if (Redirectors.Num() > 0)
	{
		AssetToolsModule.Get().FixupReferencers(Redirectors, bCheckoutDialogPrompt);
		return true;
	}
	return false;
}

参考URL

https://cgworld.jp/regular/202312-ue5tool-01.html

https://docs.unrealengine.com/5.0/en-US/PythonAPI/class/EditorAssetLibrary.html

PERFORCEで、mark for delete したあとに workspaceで消したファイルを復帰してもが見えなくなる現象

PERFORCEで、mark for delete したあとに workspaceで消したファイルを復帰してもが見えなくなる現象

In Perforce, a file deleted in workspace is no longer visible after being marked for delete.

「The folder is not located within the filtered view of the tree.」

はp4vのエラーでPerforceのエラーではないそう。

p4vを再起動したら治った。

参考

https://stackoverflow.com/questions/57364883/what-does-not-located-within-the-filtered-view-of-the-tree-mean

より抜粋

「ツリーのフィルターされたビュー」は P4V のものであり、一般的な Perforce のものではありません (つまり、Viewクライアント仕様のビューと同じではありません)。タスクバー上の小さな漏斗アイコンを探すと、そこにワークスペース ペインのフィルターが設定されています。おそらく、このファイルを除外する何かがそこに設定されているのではないでしょうか? 「隠し」ファイルを除外する設定のようなものですか?

P4Python を使用した Perforce でのファイルの移動の下調べ

Rename/Moving files in Perforce using P4Python

P4Python を使用した Perforce でのファイルの移動

P4Python は Perforce C++ API の Python ラッパーであり、プログラムで Perforce サーバーと対話できるようにします。 P4Python を使用して Perforce でファイルを移動または名前変更するには、 メソッドを使用できますp4.run_move()

ファイルをデポ内の新しい場所に移動する方法の例を次に示します。

from P4 import P4

# Connect to the Perforce server
p4 = P4()
p4.connect()
p4.login(user, password)

# Open the file for edit
p4.run_edit("//depot/path/to/file.txt")

# Move the file to a new location
p4.run_move("//depot/path/to/file.txt", "//depot/new/path/renamed_file.txt")

# Submit the changes
p4.run_submit(["-d", "Moved and renamed file"])

この例では、まず を使用して Perforce サーバーに接続しp4.connect()、 を使用して資格情報でログインしますp4.login(user, password)。次に、 を使用して編集用にファイルを開きますp4.run_edit()

次に、 を使用してファイルを新しい場所に移動しますp4.run_move()。このメソッドは、ソース ファイル パスと宛先ファイル パス (必要に応じて新しい名前を含む) という 2 つの引数を取ります。

最後に、 を使用して変更を送信しp4.run_submit()、変更リストの説明を提供します。

ファイルを移動または名前変更するには、Perforce で適切な権限が必要であることに注意してください。さらに、プロセス中に発生する可能性のある例外やエラーを必ず処理してください。

情報源

[ 1 ]Helix Core P4Python 開発者ガイド (2023.2)

[ 2 ]p4 移動

[ 3 ]スクリプト – Python で perforce からファイルをチェックアウトするにはどうすればよいですか? – スタック…

[ 4 ]PERFORCE P4Wエラー:ファイルがクライアントビューにありません – コードログ

[ 5 ]ファイルの名前変更と移動

TexturePath Replace Python Script for Maya

Select HyperShade Textures And Do Script
import maya.cmds as cmds
import pymel.core as pm
import os

def remap_selected_texture(z_path):
    
    # figure out what's selected
    selected = pm.ls(sl=True)
    workspace_path = cmds.workspace(query=True, rootDirectory=True)
    print("workspace_path= "+workspace_path)
    for item in selected:
        test_path = pm.getAttr(item+".ftn")
        fileName = test_path.split('/')[-1]
        fileName = fileName.replace('//', '')
        fileName = fileName.replace('/', '')
        print("fileName2= "+fileName)
        #if ':' not in test_path:
        if(fileName=="GraceYong_ArmsColorD1001.jpg"):
            fileName="GraceYong_ArmsColorD_1001.jpg"
        if (1==1):   
            
            #print("fileName1= "+fileName)
            
            
            #new_path = os.path.join(z_path, 'cartoon_room', second)
            new_path = os.path.join(workspace_path,z_path, fileName)
            new_path = new_path.replace('\\', '/')
            new_path = new_path.replace('//', '/')
            relative_path = os.path.join(z_path, fileName)
            relative_path = relative_path.replace('\\', '/')
            new_path = new_path.replace('//', '/')
            if os.path.exists(new_path):
                if(fileName==""):
                    print("item= "+str(item)+" is No fileName= "+ fileName)
                    cmds.select( str(item), r=True )
                    cmds.delete( str(item) )
                else:
                    print("new_path= "+new_path+' is exists! OK')
                    pm.setAttr(item+'.ftn', new_path)
                #pm.setAttr(item+'.ftn', relative_path)
            else:
                print("new_path= "+new_path+ ' not exists NG' )
        if os.path.exists(test_path):
            pass
        else:
            PersonalIndex=test_path.find("Personal")
            if(PersonalIndex==-1):
                pass
            else:
                print("test_path= "+test_path+ ' not exists NG' )
                pm.setAttr(item+'.ftn', "")
                cmds.select( str(item), r=True )
                cmds.delete( str(item) )
         
    cmds.select(selected)
    print("--------------remap_selected_texture----------END")
    
remap_selected_texture("GraceYong.images")

モデルフォルダの自動認識と出力フォルダ引数のパターン

#remap_selected_filenode_texture_path
import maya.cmds as cmds
import pymel.core as pm
import os

def remap_selected_texture(z_path):
    
    # figure out what's selected
    selected = pm.ls(sl=True)
    # workspace_project_path
    workspace_path = cmds.workspace(query=True, rootDirectory=True)
    print("workspace_path= "+workspace_path)
    # ma_file_path
    ma_file_path=cmds.file(q=True, sn=True)
    print("ma_file_path= "+ma_file_path)
    ma_file_path_arr = ma_file_path.split('/')
    ma_Folder=ma_file_path_arr[-2]
    
    print("ma_Folder= "+ma_Folder)
    for item in selected:
        item_path = pm.getAttr(item+".ftn")
        print("item_path= "+item_path)
        item_path_arr = item_path.split('/')
        texFolderName = item_path_arr[-2]
        print("texFolderName= "+texFolderName)
        fileName = item_path_arr[-1]
        print("fileName= "+fileName)
        fileName = fileName.replace('//', '')
        fileName = fileName.replace('/', '')
        print("fileName2= "+fileName)
        
        
        
        #if ':' not in test_path:

        if (1==1):   
            
            #print("fileName1= "+fileName)
            
            
            #new_path = os.path.join(z_path, 'cartoon_room', second)
            new_path = os.path.join(workspace_path,z_path, fileName)
            new_path = new_path.replace('\\', '/')
            new_path = new_path.replace('//', '/')
            #relative_path = os.path.join(z_path, fileName)
            #====================================================
            relative_path = ma_Folder+"/"+z_path+"/"+fileName
            #====================================================
            print("relative_path= "+relative_path)
            #relative_path = relative_path.replace('\\', '/')
            abs_path = os.path.abspath(workspace_path+"/"+relative_path)
            abs_path = abs_path.replace('//', '/')
            print(" abs_path= "+abs_path)
            new_path= abs_path
            print(" new_path= "+new_path)
            print("----------------------------end--------------------------")
            
            if os.path.exists(new_path):
                if(fileName==""):
                    print("item= "+str(item)+" is No fileName= "+ fileName)
                    cmds.select( str(item), r=True )
                    cmds.delete( str(item) )
                else:
                    print("new_path= "+new_path+' is exists! OK')
                    pm.setAttr(item+'.ftn', new_path)
                
            else:
                print("new_path= "+new_path+ ' not exists NG' )

    cmds.select(selected)
    print("--------------remap_selected_texture----------END")
    
remap_selected_texture("texture")

Scene押してシーンディレクトリ取得、押してWalkでテクスチャファイルをwalkで自動検索

#remap_selected_filenode_texture_path
import maya.cmds as cmds
import pymel.core as pm
import os
   
def dir_walk(walkDir,TextureFileName):
    resultPath=""
    for curDir, dirs, files in os.walk(walkDir):
        print('===================')
        print("現在のディレクトリ: " + curDir)
        curDir=curDir.replace("\\","/")
        curDir_arr=curDir.split("/")
        
        curDir_endDirName = curDir_arr[-1]
        print("curDir_endDirName= "+curDir_endDirName)
        if(curDir_endDirName==".mayaSwatches"):
            print("処理をスキップします。。。")
            pass
        else:
            
            print("内包するディレクトリ:" + str(dirs))
            print("内包するファイル: " + str(files))
            for fileName in files: 
                if(fileName==TextureFileName):
                    print("Hit : fileName= "+fileName+ "== TextureFileName= "+TextureFileName)
                    resultPath=curDir+"/"+fileName
        print('===================')
    return resultPath
     
def remap_selected_texture2(sceme_path):
    
    # figure out what's selected
    selected = cmds.ls(sl=True)
    # workspace_project_path
    workspace_path = cmds.workspace(query=True, rootDirectory=True)
    print("workspace_path= "+workspace_path)
    # ma_file_path
    ma_file_path=cmds.file(q=True, sn=True)
    print("ma_file_path= "+ma_file_path)
    ma_file_path_arr = ma_file_path.split('/')
    ma_Folder=ma_file_path_arr[-2]
    
    print("ma_Folder= "+ma_Folder)
    for item in selected:
        item_path = cmds.getAttr(item+".ftn")
        print("item_path= "+item_path)
        item_path_arr = item_path.split('/')
        texFolderName = item_path_arr[-2]
        print("texFolderName= "+texFolderName)
        fileName = item_path_arr[-1]
        print("fileName= "+fileName)
        fileName = fileName.replace('//', '')
        fileName = fileName.replace('/', '')
        print("fileName2= "+fileName)
        
        fixTexturePath=dir_walk(sceme_path,fileName)
        print("fixTexturePath= "+fixTexturePath)
        #if ':' not in test_path:

        if (1==1):   
            
            #print("fileName1= "+fileName)
            
            
            #new_path = os.path.join(z_path, 'cartoon_room', second)
            #new_path = os.path.join(workspace_path,z_path, fileName)
            new_path = fixTexturePath
            new_path = new_path.replace('\\', '/')
            new_path = new_path.replace('//', '/')
            #relative_path = os.path.join(z_path, fileName)
            #====================================================
            #relative_path = ma_Folder+"/"+z_path+"/"+fileName
            #====================================================
            #print("relative_path= "+relative_path)
            #relative_path = relative_path.replace('\\', '/')
            #abs_path = os.path.abspath(workspace_path+"/"+relative_path)
            #abs_path = abs_path.replace('//', '/')
            #print(" abs_path= "+abs_path)
            #new_path= abs_path
            print(" new_path= "+new_path)
            print("----------------------------end--------------------------")
            
            if os.path.exists(new_path):
                if(fileName==""):
                    print("item= "+str(item)+" is No fileName= "+ fileName)
                    cmds.select( str(item), r=True )
                    cmds.delete( str(item) )
                else:
                    print("new_path= "+new_path+' is exists! OK')
                    #cmds.setAttr(item+'.ftn', new_path)
                    cmds.setAttr(item+'.fileTextureName', new_path,type='string')
            else:
                print("new_path= "+new_path+ ' not exists NG' )

    cmds.select(selected)
    print("--------------remap_selected_texture----------END")
    

def remap_fileNode_texture(self):
    text_Field_id="remap_selected_filenode_texture_path_Window|USD_layout|pathTxtFld"
    textField_outputFolder = cmds.textField(text_Field_id, q=True, text=True)
    remap_selected_texture2(textField_outputFolder)

def get_scenePath():
    scenefilePath = cmds.file(q=1, sceneName=1)
    mayaPath,mayaFile = os.path.split(scenefilePath)
    #mayaPath = mayaPath + "/Usd/"
    #mayaPath = mayaPath + "/"
    mayaPath=os.path.abspath(mayaPath)
    mayaPath=mayaPath.replace('\\', '/')
    print("mayaPath= "+mayaPath)
    mayaPath_len=len(mayaPath)
    last_str=mayaPath[mayaPath_len-1:]
    print("mayaPath= "+mayaPath+ " last_str= "+last_str)
    if(last_str=="/"):
        pass
    else:
        mayaPath=mayaPath+"/"
    
    return mayaPath

def btn_scene(self):
    scenePath = get_scenePath()
    
    #textureFolder= cmds.textField('textField_outputFolder', q=True, text=True)
    
    
    
    #lastExportDirPath=scenePath+textureFolder+"/"
    
    
    
    set_lastExportDirPath(scenePath)


def set_lastExportDirPath(lastExportDirPath):
    
    selectList=cmds.ls(sl=True)
    if(str(selectList)== "[]"):
        print("なにも選択されていません。0 set_lastExportDirPath")

            
    text_Field_id="remap_selected_filenode_texture_path_Window|USD_layout|pathTxtFld"
    cmds.textField(text_Field_id, edit=True, text=lastExportDirPath)
    cmds.select(selectList)



def createWindow():
    scenefilePath = cmds.file(q=1, sceneName=1)

    USD_window = cmds.window("remap_selected_filenode_texture_path_Window", widthHeight=(400, 200))
    USD_layout = cmds.columnLayout("USD_layout",adjustableColumn=True, parent=USD_window)
    cmds.text (label="選択したハイパーシェードのテクスチャのパスを置換するツールです。", align='left', parent=USD_layout)
    cmds.text (label="シーンのパス以下のフォルダーから検索して自動的に置換します。", align='left', parent=USD_layout)
    cmds.separator(parent=USD_layout)
    cmds.text (label="", align='left', parent=USD_layout)
    
    cmds.text (label="1、Sceneを押してください。", align='left', parent=USD_layout)
    cmds.button(label="Scene", command=btn_scene, parent=USD_layout)
    text_field = cmds.textField("pathTxtFld", parent="USD_layout",text="")
    #cmds.text (label="2、テクスチャフォルダ名を指定してください。", align='left', parent=USD_layout)
    #text_field = cmds.textField("textField_outputFolder", parent="USD_layout",text="texture")
    cmds.separator(parent=USD_layout)
    cmds.text (label="", align='left', parent=USD_layout)

    
    
    
    cmds.text (label="2、HyperShadeのテクスチャTabで(例:file1,file2,複数可)を選択して、ボタンを押してください。", align='left', parent=USD_layout)
    #CheckBox_Absolute_Path_Bool = cmds.checkBox('CheckBox_Absolute_Path', q=True, value=True)
    cmds.button(label="Remap FileNode Texture ", command=remap_fileNode_texture, parent=USD_layout)
    
    #cmds.separator(parent=USD_layout)

    #cmds.button(label="Add USD Referernce/Payload... ", command=add_prim_xform_for_stage_layer, parent=USD_layout)

    cmds.showWindow(USD_window)
    return None

    
def remap_selected_filenode_texture_path():
    if cmds.window("remap_selected_filenode_texture_path_Window",exists=True):
        cmds.deleteUI("remap_selected_filenode_texture_path_Window")
    createWindow()



remap_selected_filenode_texture_path()

[UE5.3]第21回UE5ぷちコン テーマ「おす」題名「下痢ゲー2」で使った技術とexeダウンロード

Technology used in the 21st UE5 Petit Con theme “Osu” title “Diarrea Game 2”

windowsBuildをアップしました。ぜひプレイしてみてください。
▼furcraeaTokyo_GeliGa2_Windows2.zip

https://drive.google.com/file/d/18n38Hj44_s3AVEObuP43kYCyn5T4Gb_k/view?usp=sharing

MetaHumanでサードパーソンテンプレートBPを乗っ取り。

【UE5】サードパーソンテンプレートのBPを乗っ取るまで【備忘録】

テーマ「おす」のために腕をIKで構えさせる

【第6.5回】武器を持たせる・IKで構えさせる

Idle時にお腹が痛いアイドル、Run時に上半身:お腹が痛い+下半身:走り

Blend Poses by boolを使用してIdle時とRun時で分岐させる

押すBoxを見つける

[UE4] プレイヤーを検知する敵キャラクターを作る

https://historia.co.jp/archives/25062/

選択したMeshグループAからBへスキンウェイトを全部コピーMEL

Meshグループに無数にMeshがはいっててスキンウェイトをコピーするのがめんどくさくなったから書いたよ

Aのメッシュグループから
Bのメッシュグループにコピーしていく

動作はちょっと逆で
Bのグループのメッシュ名をループして
Aのグループのメッシュ名にあるか探す
あったらスキンウェイトコピー
なかったらrejectedリストに入れてます。
最後にrejectedListを表示するのでスキンウェイトしなかったメッシュのリストが出ます。

// SkinWeightCopy First Select MeshGroup to Second Select MeshGroup 
string $selectedArrFUllPath[] = `ls -long -sl`;
print($selectedArrFUllPath);

string $FirstSelect=$selectedArrFUllPath[0];

string $SecondSelect=$selectedArrFUllPath[1];

string $rejectArr[];

string $inputNodes[] = `ls -type transform -long -dag $FirstSelect`;
string $destNodes[] = `ls -type transform -long -dag $SecondSelect`;

$inputNodeslong=size($inputNodes);
$destNodeslong=size($destNodes);

string $buffer[];
string $buffer_i[];
$finded = 0;
for($d = 0; $d <$destNodeslong;$d++){
    string $destNode_name=$destNodes[$d];
    
    if($destNode_name==$SecondSelect){
            
    }else{
        print("$destNode_name= "+$destNode_name+"\n");
        
        $numTokens = `tokenize $destNode_name "|" $buffer`;
        $bufferlong=size($buffer);
        string $destNode_name_Short = $buffer[$bufferlong-1]+"";
        print("$destNode_name_Short= "+$destNode_name_Short+"\n");
        $finded = 0;
        for($i = 0; $i <$inputNodeslong;$i++){
            string $inputNode_name=$inputNodes[$i];
            $numTokens_i = `tokenize $inputNode_name "|" $buffer_i`;
            $bufferlong_i=size($buffer_i);
            string $inputNode_name_Short = $buffer_i[$bufferlong_i-1]+"";
            print("$inputNode_name_Short= "+$inputNode_name_Short+"\n");
                
            //$index=`gmatch $inputNode_name $destNode_name_Short`;
            //if($index > 0){
            if($inputNode_name_Short==$destNode_name_Short){
                //$blendShapeName = $blendshapeRet_name;
                print("$destNode_name= "+$destNode_name+" isHit!! "+"\n");
                select -r $inputNode_name;
                select -add $destNode_name;
                copySkinWeights  -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
                //copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint -sourceSkin $inputNode_name -destinationSkin $destNode_name;
                $finded = 1;
            }
        }
        if($finded==0){
            $rejectArr[size($rejectArr)] = $destNode_name;
        }
    }
}
print("----rejected_list---start"+"\n");
print($rejectArr);
print("----rejected_list---end"+"\n");
select -r $FirstSelect ;
select -add $SecondSelect ;

メッシュグループ内のグループを無視できるように、MeshのTransformだけをフィルターした。

// SkinWeightCopy First Select MeshGroup to Second Select MeshGroup 
string $selectedArrFUllPath[] = `ls -long -sl`;
print($selectedArrFUllPath);

string $FirstSelect=$selectedArrFUllPath[0];

string $SecondSelect=$selectedArrFUllPath[1];

string $rejectArr[];

//string $inputNodes[] = `ls -type transform -long -dag $FirstSelect`;
//string $destNodes[] = `ls -type transform -long -dag $SecondSelect`;

string $inputNodes_mesh[] = `ls -type mesh -long -dag $FirstSelect`;
string $destNodes_mesh[] = `ls -type mesh -long -dag $SecondSelect`;

$inputNodes_meshlong=size($inputNodes_mesh);
$destNodes_meshlong=size($destNodes_mesh);

string $inputNodes[];
string $destNodes[];
clear $inputNodes;
clear $destNodes;
string $mesh;
string $parent;
for($d0 = 0; $d0 <$inputNodes_meshlong;$d0++){
    $mesh=$inputNodes_mesh[$d0];
    string $parentS[] = `listRelatives -parent -path -type transform $mesh`;
    $parent=$parentS[0];
    $inputNodes[size($inputNodes)] = $parent;
}
for($d0 = 0; $d0 <$destNodes_meshlong;$d0++){
    $mesh=$destNodes_mesh[$d0];
    string $parentS[] = `listRelatives -parent -path -type transform $mesh`;
    $parent=$parentS[0];
    $destNodes[size($destNodes)] = $parent;
}

print("$inputNodes= ------------------------------------------------ \n");
print($inputNodes);

print("$destNodes= ------------------------------------------------ \n");
print($destNodes);



$inputNodeslong=size($inputNodes);
$destNodeslong=size($destNodes);

string $buffer[];
string $buffer_i[];
$finded = 0;
for($d = 0; $d <$destNodeslong;$d++){
    string $destNode_name=$destNodes[$d];
    
    if($destNode_name==$SecondSelect){
            
    }else{
        print("$destNode_name= "+$destNode_name+"\n");
        
        $numTokens = `tokenize $destNode_name "|" $buffer`;
        $bufferlong=size($buffer);
        string $destNode_name_Short = $buffer[$bufferlong-1]+"";
        print("$destNode_name_Short= "+$destNode_name_Short+"\n");
        $finded = 0;
        for($i = 0; $i <$inputNodeslong;$i++){
            string $inputNode_name=$inputNodes[$i];
            $numTokens_i = `tokenize $inputNode_name "|" $buffer_i`;
            $bufferlong_i=size($buffer_i);
            string $inputNode_name_Short = $buffer_i[$bufferlong_i-1]+"";
            print("$inputNode_name_Short= "+$inputNode_name_Short+"\n");
                
            //$index=`gmatch $inputNode_name $destNode_name_Short`;
            //if($index > 0){
            if($inputNode_name_Short==$destNode_name_Short){
                //$blendShapeName = $blendshapeRet_name;
                print("$destNode_name= "+$destNode_name+" isHit!! "+"\n");
                select -r $inputNode_name;
                select -add $destNode_name;
                copySkinWeights  -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
                //copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint -sourceSkin $inputNode_name -destinationSkin $destNode_name;
                $finded = 1;
            }//if
        }//for
        if($finded==0){
            $rejectArr[size($rejectArr)] = $destNode_name;
        }//if
    }//if
}//for
print("----rejected_list---start"+"\n");
print($rejectArr);
print("----rejected_list---end"+"\n");
select -r $FirstSelect ;
select -add $SecondSelect ;