using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System; using Godot; using System.Threading.Tasks; using System.Text; namespace Rokojori.Reallusion { [Tool] [GlobalClass] public partial class CCImporter:Node { [Export] public Node3D characterRoot; [Export] public string path; [Export] public CCImportConfiguration configuration; [Export] public bool addCCMaterialsNode = true; [Export] public CCImportSettings importSettings; [Export] public CCMaterialGenerator materialGenerator; [ExportToolButton( "Import")] public Callable ImportButton => Callable.From( () => { Import(); } ); [ExportToolButton( "Set Materials")] public Callable SetMaterialsButton => Callable.From( () => { SetMaterials(); } ); CCImportFile importFile; public void Import() { this.LogInfo( "Loading:", path ); importFile = new CCImportTool().Read( path ); var sb = new StringBuilder(); importFile.messages.ForEach( ( m )=> { sb.Append( m.type == MessageType.Error ? "Error: " : "Info: " ); sb.Append( m.content ); sb.Append( "\n" ); } ); this.LogInfo( sb ); importSettings = new CCImportSettings(); importSettings.configuration = configuration; var meshIndex = 0; importFile.ccObject.meshes.ForEach( ( m )=> { var meshSettings = new CCMeshSettings(); meshSettings.meshName = m.name; for ( int i = 0; i < m.materials.Count; i++ ) { var materialSetting = new CCMaterialSettings(); materialSetting.meshName = m.name; materialSetting.materialName = m.materials[ i ].name; materialSetting.materialIndex = i; materialSetting.materialType = m.materials[ i ].GetMaterialType(); meshSettings.materials = Arrays.AddEntry( meshSettings.materials, materialSetting ); } importSettings.meshes = Arrays.AddEntry( importSettings.meshes, meshSettings ); meshIndex ++; } ); } public void SetMaterials() { var meshIndex = -1; var ccmaterials = addCCMaterialsNode ? characterRoot.GetOrCreateChild( "CC Materials" ) : null; if ( ccmaterials != null ) { ccmaterials.Clear(); ccmaterials.root = characterRoot; } for ( int i = 0; i < importSettings.meshes.Length; i++ ) { var ms = importSettings.meshes[ i ]; for ( int j = 0; j < ms.materials.Length; j++ ) { ms.materials[ j ].configuration = importSettings.configuration; } } if ( importSettings.configuration.setRenderPrioritiesForHair ) { var renderIndex = 0; for ( int i = 0; i < importSettings.configuration.preRenderPriorityTargets.Length; i++ ) { var target = importSettings.configuration.preRenderPriorityTargets[ i ]; var targetName = target.meshName; var targetIndex = target.materialSurfaceIndex; var mesh = importSettings.meshes.Find( m => m.meshName == targetName ); if ( mesh == null || targetIndex < 0 || targetIndex > mesh.materials.Length ) { this.LogInfo( "Mesh not found:", targetName, ":", targetIndex ); continue; } var material = mesh.materials[ targetIndex ]; material.assignRenderPriority = true; material.materialRenderPriority = renderIndex; renderIndex++; } for ( int i = 0; i < importSettings.meshes.Length; i++ ) { var ms = importSettings.meshes[ i ]; for ( int j = 0; j < ms.materials.Length; j++ ) { if ( ms.materials[ j ].materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) { ms.materials[ j ].materialRenderPriorityIndexBack = renderIndex; renderIndex ++; } } } for ( int i = 0; i < importSettings.meshes.Length; i++ ) { var ms = importSettings.meshes[ i ]; for ( int j = 0; j < ms.materials.Length; j++ ) { if ( ms.materials[ j ].materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) { ms.materials[ j ].materialRenderPriorityIndexFront = renderIndex; renderIndex ++; } } } } importFile.ccObject.meshes.ForEach( ( m )=> { meshIndex ++; var meshSettings = importSettings.meshes[ meshIndex ]; var mesh = characterRoot.FindChild( m.name ) as MeshInstance3D; if ( mesh == null ) { return; } for ( int i = 0; i < m.materials.Count; i++ ) { var settings = meshSettings.materials[ i ]; var material = materialGenerator == null ? m.materials[ i ].CreateMaterial( settings ) : materialGenerator.CreateMaterial( m.materials[ i ], settings ); if ( settings.assignRenderPriority ) { material.RenderPriority = settings.materialRenderPriority; } var overwriteMaterial = settings.configuration.GetOverwriteMaterial( m.name, i ); if ( overwriteMaterial != null ) { material = overwriteMaterial; } mesh.SetSurfaceOverrideMaterial( i, material ); if ( ccmaterials == null ) { continue; } if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) { var hairMaterial = (CustomMaterial) material; var materials = Materials.ResolveNextPasses( material ); materials.ForEach( m => { ccmaterials.hairMaterials = Arrays.AddEntry( ccmaterials.hairMaterials, m ); } ); ccmaterials.hairSpecular.ReadFrom( hairMaterial ); ccmaterials.hairMetallic.ReadFrom( hairMaterial ); ccmaterials.hairRoughness.ReadFrom( hairMaterial ); } else if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHead || settings.materialType.shaderType == CCMaterialType.CCShaderType.RLSkin ) { var skinMaterial = (CustomMaterial) material; var materials = Materials.ResolveNextPasses( material ); materials.ForEach( m => { ccmaterials.skinMaterials = Arrays.AddEntry( ccmaterials.skinMaterials, m ); } ); ccmaterials.skinAlbedoNoise.ReadFrom( skinMaterial ); ccmaterials.skinAlbedoNoiseOffset.ReadFrom( skinMaterial ); } } } ); } } }