2025-02-19 17:24:26 +09:00
using UnityEngine ;
using UnityEditor ;
using System.IO ;
using System.Collections.Generic ;
2025-02-21 11:57:09 +09:00
using XRLib ;
using XRLib.Util ;
2025-02-19 17:24:26 +09:00
using System.Threading.Tasks ;
#if UNITY_EDITOR
using UnityEditor.AddressableAssets.Settings ;
using UnityEditor.AddressableAssets ;
#endif
namespace XED
{
public class TwinObjectPreprocessingHelper
{
#if UNITY_EDITOR
static List < TwinContainer > twinContainerList = new ( ) ;
2025-03-24 20:03:17 +09:00
//[MenuItem("Tools/TwinObjectsSetting")]
//public static void TwinObjectsSetting()
//{
// AutomateTwinObjectSetup();
//}
2025-02-19 17:24:26 +09:00
//<2F> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ش<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ִ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static void CreateFolder ( string folderPath )
{
if ( Directory . Exists ( folderPath ) )
return ;
Directory . CreateDirectory ( folderPath ) ;
}
//TODO : <20> <> <EFBFBD> θ<EFBFBD> <20> ϵ<EFBFBD> <CFB5> ڵ<EFBFBD> <20> ϴ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ̿<EFBFBD> <CCBF> <EFBFBD> <20> ٸ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ȱ<> <C8B0> , Prefab <20> <> <20> ̸<EFBFBD> <20> Ľ<EFBFBD> <C4BD> <EFBFBD> <20> ̿<EFBFBD> <CCBF> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ȱ<> <C8B0> (PRF_Robot01_Robot)
static void AutomateTwinObjectSetup ( )
{
var mainPath = "Assets/Models/" ;
var beforePath = string . Concat ( mainPath , "TwinObject_BeforeProcessing" ) ;
var afterPath = string . Concat ( mainPath , "TwinObject_AfterProcessing/" ) ;
string etcPath = string . Concat ( mainPath , "$etc" ) ;
CreateFolder ( etcPath ) ;
CreateAddressableAssets ( beforePath , etcPath , afterPath ) ;
TwinContainerAddressableSetting ( twinContainerList ) ;
}
static void CreateAddressableAssets ( string beforePath , string etcPath , string afterPath )
{
//beforPath <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ÿ<> <C5B8> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Asset<65> <74> guid<69> <64> <20> <> <EFBFBD> <EFBFBD> ã<> <C3A3> <EFBFBD> ϴ<EFBFBD> .
string [ ] guids = AssetDatabase . FindAssets ( "t:Prefab" , new string [ ] { beforePath } ) ;
foreach ( var guid in guids )
{
//guid <20> <> <20> ش<EFBFBD> <D8B4> ϴ<EFBFBD> Asset <20> <> <20> <> <EFBFBD> θ<EFBFBD> ã<> <C3A3> <EFBFBD> ϴ<EFBFBD> .
string filePath = AssetDatabase . GUIDToAssetPath ( guid ) ;
if ( filePath . StartsWith ( etcPath ) )
{
continue ;
}
//<2F> <> <EFBFBD> ο <EFBFBD> <20> ش<EFBFBD> <D8B4> ϴ<EFBFBD> Asset <20> <> ã<> <C3A3> <EFBFBD> ϴ<EFBFBD> .
var loadAsset = AssetDatabase . LoadAssetAtPath < GameObject > ( filePath ) ;
var twinObject = loadAsset . GetComponent < TwinObject > ( ) ;
string fileName = Path . GetFileName ( filePath ) ;
string fileNameWithoutExtension = Path . GetFileNameWithoutExtension ( filePath ) ;
string folderPath = string . Concat ( afterPath , fileNameWithoutExtension ) ;
string fullPath = string . Concat ( folderPath , "/" , fileName ) ;
//<2F> <> ó<EFBFBD> <C3B3> <20> Ϸ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> մϴ<D5B4> .
CreateFolder ( folderPath ) ;
//TwinContainer <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> մϴ<D5B4> .
var twinContainer = CreateTwinContainer ( folderPath , twinObject ) ;
//TwinObject <20> ̸<EFBFBD> <CCB8> <EFBFBD> <EFBFBD> <EFBFBD> <20> ̹<EFBFBD> <CCB9> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> մϴ<D5B4> .
var texture = CreateTwinObjectPortrait ( folderPath , twinObject ) ;
//TwinObject <20> <> <20> <EFBFBD> <20> <> ġ, <20> ݶ<EFBFBD> <DDB6> ̴<EFBFBD> <CCB4> <EFBFBD> <20> ʱ<EFBFBD> ȭ <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> մϴ<D5B4> .
SetTwinObject ( loadAsset ) ;
var moveFilePath = MoveFiles ( fileName , filePath , fullPath , etcPath ) ;
AssetDatabase . Refresh ( ) ;
//TwinContainer <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ҵ<EFBFBD> <D2B4> մϴ<D5B4> .
TwinContainerSetData ( twinContainer , texture , moveFilePath ) ;
twinContainerList . Add ( twinContainer ) ;
}
}
static TwinContainer CreateTwinContainer ( string folderPath , TwinObject twinObject )
{
var twinContainer = ScriptableObject . CreateInstance < TwinContainer > ( ) ;
var path = string . Concat ( folderPath , "/" , twinObject . name , ".asset" ) ;
AssetDatabase . CreateAsset ( twinContainer , path ) ;
return twinContainer ;
}
static Texture2D CreateTwinObjectPortrait ( string folderPath , TwinObject twinObject )
{
Texture2D thumbnailTexture = null ;
//<2F> ̸<EFBFBD> <CCB8> <EFBFBD> <EFBFBD> <EFBFBD> <20> ؽ<EFBFBD> ó <20> <> <EFBFBD> <EFBFBD>
while ( thumbnailTexture = = null )
{
thumbnailTexture = AssetPreview . GetAssetPreview ( twinObject . gameObject ) ;
System . Threading . Thread . Sleep ( 5 ) ;
}
var transparentTexture = BackgroundTransparencyProcess ( thumbnailTexture ) ;
//<2F> ؽ<EFBFBD> ó <20> <> <EFBFBD> <EFBFBD>
transparentTexture . name = string . Concat ( "Texture_" , twinObject . name ) ;
byte [ ] bytes = transparentTexture . EncodeToPNG ( ) ;
string filePath = string . Concat ( folderPath , "/" , transparentTexture . name , ".png" ) ;
File . WriteAllBytes ( filePath , bytes ) ;
AssetDatabase . Refresh ( ) ;
//<2F> ؽ<EFBFBD> ó <20> ҷ<EFBFBD> <D2B7> <EFBFBD> <EFBFBD> <EFBFBD>
var texture = AssetDatabase . LoadAssetAtPath < Texture2D > ( filePath ) ;
return texture ;
}
static Texture2D BackgroundTransparencyProcess ( Texture2D texture )
{
var transparentTexture = new Texture2D ( texture . width , texture . height ) ;
transparentTexture . SetPixels ( texture . GetPixels ( ) ) ;
for ( int h = 0 ; h < texture . height ; h + + )
{
for ( int w = 0 ; w < texture . width ; w + + )
{
transparentTexture . SetPixel ( w , h , Color . clear ) ;
if ( texture . GetPixel ( w , h ) ! = texture . GetPixel ( w + 1 , h ) )
break ;
}
for ( int w = texture . width ; w > 0 ; w - - )
{
transparentTexture . SetPixel ( w , h , Color . clear ) ;
if ( texture . GetPixel ( w , h ) ! = texture . GetPixel ( w - 1 , h ) )
break ;
}
}
transparentTexture . Apply ( ) ;
return transparentTexture ;
}
//<2F> ۾<EFBFBD> <DBBE> <EFBFBD> <20> Ϸ<EFBFBD> <CFB7> <EFBFBD> <20> <EFBFBD> <F0B5A8B8> <EFBFBD> <20> <> ó<EFBFBD> <C3B3> <20> Ϸ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ̵<EFBFBD> <CCB5> <EFBFBD> Ű<EFBFBD> <C5B0> <20> <EFBFBD> <DEBC> <EFBFBD>
static string MoveFiles ( string fileName , string filePath , string fullPath , string etcPath )
{
if ( File . Exists ( fullPath ) & & ( filePath ! = fullPath ) )
{
int filenum = 0 ;
string EtcFileName = string . Concat ( etcPath , "/" , fileName ) ;
while ( File . Exists ( EtcFileName ) )
{
filenum + + ;
EtcFileName = string . Concat ( etcPath , "/" , filenum . ToString ( ) , "_" , fileName ) ;
}
fullPath = EtcFileName ;
}
File . Move ( filePath , fullPath ) ;
return fullPath ;
}
static void TwinContainerSetData ( TwinContainer twinContainer , Texture2D texture , string filePath )
{
var moveAsset = AssetDatabase . LoadAssetAtPath < GameObject > ( filePath ) ;
var moveTwinObject = moveAsset . GetComponent < TwinObject > ( ) ;
twinContainer . twinObject = moveTwinObject ;
twinContainer . twinObjectPortrait = texture ;
}
#region TwinObject Modeling <EFBFBD> <EFBFBD> Collider <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ϴ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
//TwinObject <20> <> Modeling <20> <> <20> <> ġ<EFBFBD> <C4A1> Collider <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static void SetTwinObject ( GameObject twinObject )
{
var bounds = CalculateBounds ( twinObject . transform ) ;
SetModelPosition ( twinObject . transform , bounds ) ;
SetBoxCollider ( twinObject . transform , bounds ) ;
}
//TwinObject <20> <> Bounds <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static Bounds CalculateBounds ( Transform twinObject )
{
var childRenderers = twinObject . GetComponentsInChildren < Renderer > ( ) ;
var combinedBounds = childRenderers [ 0 ] . bounds ;
foreach ( var childRenderer in childRenderers )
{
combinedBounds . Encapsulate ( childRenderer . bounds ) ;
}
return combinedBounds ;
}
//TwinObject <20> <> <20> ݶ<EFBFBD> <DDB6> ̴<EFBFBD> <CCB4> <EFBFBD> ũ<> <20> °<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static void SetBoxCollider ( Transform twinObject , Bounds bounds )
{
var boxCollider = twinObject . GetOrAddComponent < BoxCollider > ( ) ;
boxCollider . size = bounds . size ;
boxCollider . center = Vector3 . zero ;
}
//TwinObject <20> <> <20> <EFBFBD> <20> <> ü<EFBFBD> <C3BC> <20> <> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static void SetModelPosition ( Transform twinObject , Bounds bounds )
{
var twinObjectChild = twinObject . GetChild ( 0 ) ;
twinObjectChild . position - = bounds . center ;
}
#endregion
#region TwinContainer <EFBFBD> <EFBFBD> Addressable Asset <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ϴ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
private static void TwinContainerAddressableSetting ( List < TwinContainer > twinContainers )
{
foreach ( var twinContainer in twinContainers )
{
AddressableSetting ( twinContainer ) ;
}
}
//TwinContainer <20> <> Addressable(Group, Label)<29> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
private static void AddressableSetting ( TwinContainer twinContainer )
{
AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject . Settings ;
var path = AssetDatabase . GetAssetPath ( twinContainer ) ;
var guid = AssetDatabase . AssetPathToGUID ( path ) ;
var entry = settings . FindAssetEntry ( guid ) ;
var label = twinContainer . twinObject . assetLabel . ToString ( ) ;
var group = CreateOrFindGroup ( settings , label ) ;
if ( entry = = null )
{
entry = settings . CreateOrMoveEntry ( guid , group ) ;
}
else
{
entry . address = path ;
}
settings . MoveEntry ( entry , group ) ;
entry . SetLabel ( label , true ) ;
}
//Addressable Group <20> <> ã<> <C3A3> , ã<> <C3A3> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ش<EFBFBD> Group <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϰ<EFBFBD> <20> <> ȯ<EFBFBD> ϴ<EFBFBD> <20> <EFBFBD> <DEBC> <EFBFBD>
static AddressableAssetGroup CreateOrFindGroup ( AddressableAssetSettings settings , string groupName )
{
var group = settings . FindGroup ( groupName ) ;
if ( group = = null )
group = settings . CreateGroup ( groupName , false , false , true , null ) ;
return group ;
}
#endregion
#endif
}
}