From cf103baf579c497bfcdab88cb8f64d5fd40ca27b Mon Sep 17 00:00:00 2001 From: dal4segno Date: Mon, 6 Apr 2026 14:04:09 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20=EC=99=B8=EB=B6=80=20=EC=97=90?= =?UTF-8?q?=EC=85=8B=20=EA=B6=8C=ED=95=9C=20=EB=B0=8F=20=EC=A4=84=EB=B0=94?= =?UTF-8?q?=EA=BF=88=20=EC=9E=AC=EA=B8=B0=EB=A1=9D=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Assets/External 하위 샘플 및 서드파티 에셋 파일의 실행 비트 변경을 별도 커밋으로 분리 - PolygonGeneric, SidekickCharacters, Synty 도구 자산 전반의 줄바꿈 및 재직렬화 차이를 그대로 보존 - 프로젝트 고유 로직 변경과 분리해 이후 히스토리에서 외부 에셋 노이즈 범위를 식별하기 쉽게 정리 --- .../Samples/Scripts/InputSystem/Controls.cs | 4 +- .../Scripts/InputSystem/GBL_Controls.cs | 4 +- .../Samples/Materials/Dummy_Mat.mat | 190 +- .../Samples/Materials/Ground_Mat.mat | 197 +- .../Samples/Materials/M_Dummy.mat | 62 +- .../Samples/Materials/M_Dummy.mat.meta | 2 +- .../Samples/Materials/M_Ground.mat | 64 +- .../Samples/Materials/M_Ground.mat.meta | 2 +- .../Samples/Materials/M_Sky.mat | 50 +- .../Samples/Materials/M_Sky.mat.meta | 2 +- .../Samples/Textures/T_Polygon_Dummy_01.png | Bin .../Textures/T_Polygon_Dummy_01.png.meta | 2 +- .../Materials/Brick/Brick_Large_01.mat | 14 +- .../Materials/Alts/Generic_01_A.mat.meta | 0 .../Materials/Alts/Generic_01_B.mat.meta | 0 .../Materials/Alts/Generic_01_C.mat.meta | 0 .../Materials/Alts/Generic_02_A.mat.meta | 0 .../Materials/Alts/Generic_02_B.mat.meta | 0 .../Materials/Alts/Generic_02_C.mat.meta | 0 .../Materials/Alts/Generic_03_A.mat.meta | 0 .../Materials/Alts/Generic_03_B.mat.meta | 0 .../Materials/Alts/Generic_03_C.mat.meta | 0 .../Materials/Alts/Generic_04_A.mat.meta | 0 .../Materials/Alts/Generic_04_B.mat.meta | 0 .../Materials/Alts/Generic_04_C.mat.meta | 0 .../Materials/FX/Generic_Blank.mat.meta | 0 .../FX/Generic_Candle_Glow_01.mat.meta | 0 .../FX/Generic_Circle_Additive_01.mat.meta | 0 .../FX/Generic_Circle_Multiply_01.mat.meta | 0 .../FX/Generic_Circle_Soft_01.mat.meta | 0 .../Materials/FX/Generic_Leaf.mat.meta | 0 .../Materials/FX/Generic_Lightray_01.mat.meta | 0 .../Materials/FX/Generic_Sun_Beam_01.mat.meta | 0 .../Materials/FX/Generic_Wind_Streak.mat.meta | 0 .../Materials/Generic_Brick.mat.meta | 0 .../Materials/Generic_Carpet.mat.meta | 0 .../Materials/Generic_Cloud.mat.meta | 0 .../Materials/Generic_Concrete.mat.meta | 0 .../Materials/Generic_Dirt.mat.meta | 0 .../Materials/Generic_Glass.mat.meta | 0 .../Materials/Generic_Glass_Opaque.mat.meta | 0 .../Materials/Generic_Grass.mat.meta | 0 .../Materials/Generic_Ivy.mat.meta | 0 .../Materials/Generic_Mountains.mat.meta | 0 .../Generic_Overview_Map_Ground.mat.meta | 0 .../Materials/Generic_Plaster.mat.meta | 0 .../Materials/Generic_Road.mat.meta | 0 .../Materials/Generic_Rock.mat.meta | 0 .../Materials/Generic_SimpleSky.mat.meta | 0 .../Materials/Generic_Skyline.mat.meta | 0 .../Generic_Triplanar_Grass_01.mat.meta | 0 .../Materials/Generic_Water.mat.meta | 0 .../Materials/Generic_Water_Fade.mat.meta | 0 .../Materials/Generic_Wood.mat.meta | 0 .../Materials/Glass_Opaque_01.mat.meta | 0 .../Materials/Skybox_01.mat.meta | 0 .../Materials/Waterflow_01.mat.meta | 0 .../Scripts/Generic_SimpleRotate.cs | 70 +- .../Scripts/Generic_SimpleRotate.cs.meta | 0 .../Scripts/Generic_SimpleTranslate.cs | 62 +- .../Scripts/Generic_SimpleTranslate.cs.meta | 0 .../Scripts/Generic_WaterBob.cs | 88 +- .../Scripts/Generic_WaterBob.cs.meta | 0 .../Editor/PolygonShaderGUI.cs | 408 +- .../Editor/PolygonShaderGUI.cs.meta | 0 .../Editor/PolygonTransparencyShaderGUI.cs | 290 +- .../PolygonTransparencyShaderGUI.cs.meta | 0 .../Editor/polygonShaderTransparent_UI.cs | 1130 +- .../polygonShaderTransparent_UI.cs.meta | 0 .../Editor/polygonShader_UI.cs | 1372 +-- .../Editor/polygonShader_UI.cs.meta | 0 .../Materials/FantasyKnights_01.mat | 15 +- .../Materials/FantasyKnights_02.mat | 15 +- .../Materials/FantasyKnights_03.mat | 15 +- .../Materials/FantasyKnights_04.mat | 15 +- .../Materials/FantasyKnights_05.mat | 15 +- .../Materials/FantasyKnights_06.mat | 15 +- .../Materials/HumanSpecies_01.mat | 15 +- .../Materials/HumanSpecies_02.mat | 16 +- .../Materials/HumanSpecies_03.mat | 15 +- .../Materials/HumanSpecies_04.mat | 15 +- .../Database/Side_Kick_Data.db.meta | 0 .../Runtime/sqlite-net/AssemblyInfo.cs | 58 +- .../Runtime/sqlite-net/AssemblyInfo.cs.meta | 0 .../Materials/M_BaseMaterial.mat.meta | 0 .../Materials/M_PresetColor.mat.meta | 0 .../Scripts/Editor/ModularCharacterWindow.cs | 10023 ++++++++-------- .../Editor/ModularCharacterWindow.cs.meta | 0 .../Editor/UI/DatabaseUpdateController.cs | 30 +- .../UI/DatabaseUpdateController.cs.meta | 0 .../Scripts/Editor/Utility/ToolDownloader.cs | 750 +- .../Editor/Utility/ToolDownloader.cs.meta | 0 .../Scripts/Editor/version.txt | 2 +- .../Scripts/Runtime/API/SidekickRuntime.cs | 40 +- .../Runtime/API/SidekickRuntime.cs.meta | 0 .../Runtime/Blendshapes/FacialController.cs | 6498 +++++----- .../Blendshapes/FacialController.cs.meta | 22 +- .../Runtime/Database/DTO/SidekickColorRow.cs | 694 +- .../Database/DTO/SidekickColorRow.cs.meta | 0 .../Runtime/Database/DTO/SidekickColorSet.cs | 12 - .../Database/DTO/SidekickColorSet.cs.meta | 0 .../Runtime/Database/DTO/SidekickPart.cs | 2 - .../Runtime/Database/DTO/SidekickPart.cs.meta | 0 .../Database/DTO/SidekickPartPreset.cs | 570 +- .../Database/DTO/SidekickPartPreset.cs.meta | 0 .../Runtime/Database/DatabaseManager.cs | 242 +- .../Runtime/Database/DatabaseManager.cs.meta | 0 .../Scripts/Runtime/Filters/FilterGroup.cs | 408 +- .../Runtime/Filters/FilterGroup.cs.meta | 0 .../Scripts/Runtime/Filters/FilterItem.cs | 118 +- .../Runtime/Filters/FilterItem.cs.meta | 0 .../Scripts/Runtime/Filters/ParsedPart.cs | 72 +- .../Runtime/Filters/ParsedPart.cs.meta | 4 +- .../Runtime/Filters/PresetFilterItem.cs | 90 +- .../Runtime/Filters/PresetFilterItem.cs.meta | 4 +- .../Runtime/Utils/SampleAutoInputModule.cs | 140 +- .../Utils/SampleAutoInputModule.cs.meta | 0 .../_Demos/Materials/M_SampleFace.mat.meta | 0 .../Materials/SK_FacialDemoCharacter.mat.meta | 0 .../Apocalypse_Bat/pasted__SK2.mat.meta | 0 .../Weapons/Goblin_Axe/lambert2.mat.meta | 0 .../Weapons/Pirate_Sword/blinn1.mat.meta | 0 .../Weapons/Pirate_Sword/lambert2.mat.meta | 0 .../Weapons/Pirate_Sword/lambert4.mat.meta | 0 .../SavedCharacters/SK_FacialDemoCharacter.sk | 1522 +-- .../SK_FacialDemoCharacter.sk.meta | 0 .../_Demos/Scripts/RandomisedLayerWeight.cs | 280 +- .../Scripts/RandomisedLayerWeight.cs.meta | 0 .../_Demos/Scripts/RuntimeColorDemo.cs | 446 +- .../_Demos/Scripts/RuntimeColorDemo.cs.meta | 0 .../_Demos/Scripts/RuntimePartsDemo.cs | 760 +- .../_Demos/Scripts/RuntimePartsDemo.cs.meta | 0 .../_Demos/Scripts/RuntimePresetDemo.cs | 650 +- .../_Demos/Scripts/RuntimePresetDemo.cs.meta | 0 .../Editor/SyntyPackageHelper.cs | 422 +- .../Editor/SyntyPackageHelper.cs.meta | 0 .../Editor/Utils/PropBoneToolEditorUtil.cs | 930 +- .../Utils/PropBoneToolEditorUtil.cs.meta | 0 .../Runtime/PropBoneBinder.cs | 966 +- .../Runtime/PropBoneBinder.cs.meta | 0 140 files changed, 15090 insertions(+), 14829 deletions(-) mode change 100644 => 100755 Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_A.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_B.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_C.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_A.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_B.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_C.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_A.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_B.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_C.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_A.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_B.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_C.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Blank.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Candle_Glow_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Additive_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Multiply_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Soft_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Leaf.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Lightray_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Sun_Beam_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Wind_Streak.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Brick.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Carpet.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Cloud.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Concrete.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Dirt.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Glass.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Glass_Opaque.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Grass.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Ivy.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Mountains.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Overview_Map_Ground.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Plaster.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Road.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Rock.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_SimpleSky.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Skyline.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Triplanar_Grass_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Water.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Water_Fade.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Generic_Wood.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Glass_Opaque_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Skybox_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Materials/Waterflow_01.mat.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs.meta mode change 100644 => 100755 Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Database/Side_Kick_Data.db.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Resources/Materials/M_BaseMaterial.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Resources/Materials/M_PresetColor.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Materials/M_SampleFace.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Materials/SK_FacialDemoCharacter.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Apocalypse_Bat/pasted__SK2.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Goblin_Axe/lambert2.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/blinn1.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert2.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert4.mat.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs.meta mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs mode change 100644 => 100755 Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs.meta mode change 100644 => 100755 Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs mode change 100644 => 100755 Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs.meta mode change 100644 => 100755 Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs mode change 100644 => 100755 Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs.meta mode change 100644 => 100755 Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs mode change 100644 => 100755 Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs.meta diff --git a/Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.cs b/Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.cs index 30bb94b8..efe32a0c 100644 --- a/Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.cs +++ b/Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.cs @@ -2,7 +2,7 @@ // // This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator // version 1.18.0 -// from Assets/Synty/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.inputactions +// from Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.inputactions // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -16,7 +16,7 @@ using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; /// -/// Provides programmatic access to , , and instances defined in asset "Assets/Synty/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.inputactions". +/// Provides programmatic access to , , and instances defined in asset "Assets/External/Animations/AnimationBaseLocomotion/Samples/Scripts/InputSystem/Controls.inputactions". /// /// /// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. diff --git a/Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.cs b/Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.cs index 0083a386..fc2c3faa 100644 --- a/Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.cs +++ b/Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.cs @@ -2,7 +2,7 @@ // // This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator // version 1.18.0 -// from Assets/Synty/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.inputactions +// from Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.inputactions // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -16,7 +16,7 @@ using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; /// -/// Provides programmatic access to , , and instances defined in asset "Assets/Synty/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.inputactions". +/// Provides programmatic access to , , and instances defined in asset "Assets/External/Animations/AnimationGoblinLocomotion/Samples/Scripts/InputSystem/GBL_Controls.inputactions". /// /// /// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. diff --git a/Assets/External/Animations/AnimationIdles/Samples/Materials/Dummy_Mat.mat b/Assets/External/Animations/AnimationIdles/Samples/Materials/Dummy_Mat.mat index bafe18d8..9bfb9771 100644 --- a/Assets/External/Animations/AnimationIdles/Samples/Materials/Dummy_Mat.mat +++ b/Assets/External/Animations/AnimationIdles/Samples/Materials/Dummy_Mat.mat @@ -8,21 +8,32 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Dummy_Mat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Shader: {fileID: -6465566751694194690, guid: 19e269a311c45cd4482cf0ac0e694503, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 - m_ValidKeywords: [] + m_ValidKeywords: + - _ALPHATEST_ON + - _OVERLAY_UV_CHANNEL_UV0 m_InvalidKeywords: [] m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _AO_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Base_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -43,6 +54,10 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Emission_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _MainTex: m_Texture: {fileID: 2800000, guid: 52475fb4afae07b4384becbad96a4bee, type: 3} m_Scale: {x: 1, y: 1} @@ -51,33 +66,202 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Metallic_Smoothness_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _OcclusionMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Overlay_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ParallaxMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Triplanar_Emission_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Bottom: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Side: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Top: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Bottom: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Side: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Top: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} m_Ints: [] m_Floats: + - _AO_Intensity: 1 + - _AlphaClip: 1 + - _AlphaToMask: 1 + - _BUILTIN_AlphaClip: 1 + - _BUILTIN_Blend: 0 + - _BUILTIN_CullMode: 2 + - _BUILTIN_DstBlend: 0 + - _BUILTIN_QueueControl: -1 + - _BUILTIN_QueueOffset: 0 + - _BUILTIN_SrcBlend: 1 + - _BUILTIN_Surface: 0 + - _BUILTIN_ZTest: 4 + - _BUILTIN_ZWrite: 1 + - _BUILTIN_ZWriteControl: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 0 + - _Bottom_Metallic: 0 + - _Bottom_Smoothness: 0 - _BumpScale: 1 + - _CastShadows: 1 + - _Cull: 2 - _Cutoff: 0.5 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _Enable_Ambient_Occlusion: 0 + - _Enable_Base_Texture: 0 + - _Enable_Emission_Texture: 0 + - _Enable_Normal_Texture: 0 + - _Enable_Overlay_Texture: 0 + - _Enable_Snow: 0 + - _Enable_Triplanar_Emission: 0 + - _Enable_Triplanar_Normals: 0 + - _Enable_Triplanar_Texture: 0 + - _Generate_From_Base_Normals: 0 - _GlossMapScale: 1 - _Glossiness: 0.5 - _GlossyReflections: 1 - _Metallic: 0 - _Mode: 0 + - _Normal_Intensity: 1 + - _OVERLAY_UV_CHANNEL: 0 - _OcclusionStrength: 1 + - _Overlay_Intensity: 1 - _Parallax: 0.02 + - _QueueControl: -1 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Side_Metallic: 0 + - _Side_Smoothness: 0 + - _Smoothness: 0 - _SmoothnessTextureChannel: 0 + - _Snow_Level: 0 + - _Snow_Metallic: 0.1 + - _Snow_Smoothness: 0.5 + - _Snow_Transition: 1 + - _Snow_Use_World_Up: 1 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _Top_Metallic: 0 + - _Top_Smoothness: 0 + - _Triplanar_Emission_Blend: 1 + - _Triplanar_Emission_Intensity: 1 + - _Triplanar_Emission_Tiling: 0.25 + - _Triplanar_Fade: 1 + - _Triplanar_Intensity: 1 + - _Triplanar_Normal_Fade: 0 + - _Triplanar_Normal_Intensity_Bottom: 1 + - _Triplanar_Normal_Intensity_Side: 1 + - _Triplanar_Normal_Intensity_Top: 1 + - _Triplanar_Normal_Top_To_Side_Difference: 0.2 + - _Triplanar_Top_To_Side_Difference: 0.2 - _UVSec: 0 + - _WorkflowMode: 1 + - _ZTest: 4 - _ZWrite: 1 + - _ZWriteControl: 0 m_Colors: + - _AO_Offset: {r: 0, g: 0, b: 0, a: 0} + - _AO_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Base_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Base_Tiling: {r: 1, g: 1, b: 0, a: 0} - _Color: {r: 1, g: 1, b: 1, a: 1} + - _Color_Tint: {r: 0, g: 0, b: 0, a: 0} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _Emission_Color_Tint: {r: 0, g: 0, b: 0, a: 0} + - _Emission_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Emission_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Normal_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Normal_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Overlay_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Overlay_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Snow_Color: {r: 0.85, g: 0.85, b: 0.85, a: 0} + - _Triplanar_Emission_Color_Tint: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Bottom: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Side: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Top: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Bottom: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Side: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Top: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Offset_Bottom: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Offset_Side: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Offset_Top: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Tiling_Bottom: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Tiling_Side: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Tiling_Top: {r: 1, g: 1, b: 0, a: 0} + - _UVPan: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &1478222285771911038 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.ShaderGraph.Editor::UnityEditor.Rendering.BuiltIn.AssetVersion + version: 0 +--- !u!114 &3036035668096195608 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/External/Animations/AnimationIdles/Samples/Materials/Ground_Mat.mat b/Assets/External/Animations/AnimationIdles/Samples/Materials/Ground_Mat.mat index 6757b3a5..a1032476 100644 --- a/Assets/External/Animations/AnimationIdles/Samples/Materials/Ground_Mat.mat +++ b/Assets/External/Animations/AnimationIdles/Samples/Materials/Ground_Mat.mat @@ -1,24 +1,52 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!114 &-300816632722559782 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 --- !u!21 &2100000 Material: - serializedVersion: 6 + serializedVersion: 8 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Ground_Mat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: + m_Shader: {fileID: -6465566751694194690, guid: 19e269a311c45cd4482cf0ac0e694503, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHATEST_ON + - _OVERLAY_UV_CHANNEL_UV0 + m_InvalidKeywords: [] m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _AO_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Base_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -39,6 +67,10 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Emission_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _MainTex: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -47,32 +79,189 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Metallic_Smoothness_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _OcclusionMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Overlay_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ParallaxMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Triplanar_Emission_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Bottom: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Side: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Normal_Texture_Top: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Bottom: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Side: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Triplanar_Texture_Top: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] m_Floats: + - _AO_Intensity: 1 + - _AlphaClip: 1 + - _AlphaToMask: 1 + - _BUILTIN_AlphaClip: 1 + - _BUILTIN_Blend: 0 + - _BUILTIN_CullMode: 2 + - _BUILTIN_DstBlend: 0 + - _BUILTIN_QueueControl: -1 + - _BUILTIN_QueueOffset: 0 + - _BUILTIN_SrcBlend: 1 + - _BUILTIN_Surface: 0 + - _BUILTIN_ZTest: 4 + - _BUILTIN_ZWrite: 1 + - _BUILTIN_ZWriteControl: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 0 + - _Bottom_Metallic: 0 + - _Bottom_Smoothness: 0 - _BumpScale: 1 + - _CastShadows: 1 + - _Cull: 2 - _Cutoff: 0.5 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _Enable_Ambient_Occlusion: 0 + - _Enable_Base_Texture: 0 + - _Enable_Emission_Texture: 0 + - _Enable_Normal_Texture: 0 + - _Enable_Overlay_Texture: 0 + - _Enable_Snow: 0 + - _Enable_Triplanar_Emission: 0 + - _Enable_Triplanar_Normals: 0 + - _Enable_Triplanar_Texture: 0 + - _Generate_From_Base_Normals: 0 - _GlossMapScale: 1 - _Glossiness: 0.2 - _GlossyReflections: 1 - _Metallic: 0 - _Mode: 0 + - _Normal_Intensity: 1 + - _OVERLAY_UV_CHANNEL: 0 - _OcclusionStrength: 1 + - _Overlay_Intensity: 1 - _Parallax: 0.02 + - _QueueControl: -1 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Side_Metallic: 0 + - _Side_Smoothness: 0 + - _Smoothness: 0 - _SmoothnessTextureChannel: 0 + - _Snow_Level: 0 + - _Snow_Metallic: 0.1 + - _Snow_Smoothness: 0.5 + - _Snow_Transition: 1 + - _Snow_Use_World_Up: 1 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _Top_Metallic: 0 + - _Top_Smoothness: 0 + - _Triplanar_Emission_Blend: 1 + - _Triplanar_Emission_Intensity: 1 + - _Triplanar_Emission_Tiling: 0.25 + - _Triplanar_Fade: 1 + - _Triplanar_Intensity: 1 + - _Triplanar_Normal_Fade: 0 + - _Triplanar_Normal_Intensity_Bottom: 1 + - _Triplanar_Normal_Intensity_Side: 1 + - _Triplanar_Normal_Intensity_Top: 1 + - _Triplanar_Normal_Top_To_Side_Difference: 0.2 + - _Triplanar_Top_To_Side_Difference: 0.2 - _UVSec: 0 + - _WorkflowMode: 1 + - _ZTest: 4 - _ZWrite: 1 + - _ZWriteControl: 0 m_Colors: + - _AO_Offset: {r: 0, g: 0, b: 0, a: 0} + - _AO_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Base_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Base_Tiling: {r: 1, g: 1, b: 0, a: 0} - _Color: {r: 0.5553578, g: 0.5795657, b: 0.6037736, a: 1} + - _Color_Tint: {r: 1, g: 1, b: 1, a: 0} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _Emission_Color_Tint: {r: 0, g: 0, b: 0, a: 0} + - _Emission_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Emission_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Normal_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Normal_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Overlay_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Overlay_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Snow_Color: {r: 0.85, g: 0.85, b: 0.85, a: 0} + - _Triplanar_Emission_Color_Tint: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Bottom: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Side: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Offset_Top: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Bottom: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Side: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Normal_Tiling_Top: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Offset_Bottom: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Offset_Side: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Offset_Top: {r: 0, g: 0, b: 0, a: 0} + - _Triplanar_Tiling_Bottom: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Tiling_Side: {r: 1, g: 1, b: 0, a: 0} + - _Triplanar_Tiling_Top: {r: 1, g: 1, b: 0, a: 0} + - _UVPan: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &1519216836111423043 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.ShaderGraph.Editor::UnityEditor.Rendering.BuiltIn.AssetVersion + version: 0 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat index fc64dbc7..d08b7245 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat @@ -8,7 +8,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: M_Dummy - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] @@ -17,12 +17,18 @@ Material: m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 2800000, guid: 52475fb4afae07b4384becbad96a4bee, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -59,12 +65,39 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} m_Ints: [] m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 - _GlossMapScale: 1 - _Glossiness: 0.5 - _GlossyReflections: 1 @@ -72,12 +105,35 @@ Material: - _Mode: 0 - _OcclusionStrength: 1 - _Parallax: 0.02 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 - _SmoothnessTextureChannel: 0 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 - _UVSec: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 - _ZWrite: 1 m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &8796169509839380165 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat.meta b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat.meta index 51a5e214..ad2bb767 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat.meta +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Dummy.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ba9ac54bb93ffaf4f9d335d994ebfabd +guid: 7181c4f41342f22d8bfa7ed36730f373 NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat index e3179bc4..01a519f4 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat @@ -8,7 +8,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: M_Ground - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] @@ -17,12 +17,18 @@ Material: m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -59,12 +65,39 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} m_Ints: [] m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 - _GlossMapScale: 1 - _Glossiness: 0.2 - _GlossyReflections: 1 @@ -72,12 +105,35 @@ Material: - _Mode: 0 - _OcclusionStrength: 1 - _Parallax: 0.02 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.2 - _SmoothnessTextureChannel: 0 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 - _UVSec: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 - _ZWrite: 1 m_Colors: - - _Color: {r: 0.5553578, g: 0.5795657, b: 0.6037736, a: 1} + - _BaseColor: {r: 0.55535775, g: 0.5795657, b: 0.6037736, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &686116854676397900 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat.meta b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat.meta index 5fab8d89..4e1d9a55 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat.meta +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Ground.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a8382f46b72a5d64283c4060b7311644 +guid: 6292c9818a88933b89f67a3b92eec4c7 NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat index f1195c53..67e48c81 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat @@ -2,23 +2,33 @@ %TAG !u! tag:unity3d.com,2011: --- !u!21 &2100000 Material: - serializedVersion: 6 + serializedVersion: 8 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: M_Sky - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: + m_Shader: {fileID: 4800000, guid: 650dd9526735d5b46b79224bc6e94025, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -55,11 +65,19 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + m_Ints: [] m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendOp: 0 - _BumpScale: 1 + - _Cull: 2 - _Cutoff: 0.5 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 - _GlossMapScale: 1 - _Glossiness: 0 - _GlossyReflections: 1 @@ -67,12 +85,32 @@ Material: - _Mode: 0 - _OcclusionStrength: 1 - _Parallax: 0.02 + - _QueueOffset: 0 + - _SampleGI: 0 - _SmoothnessTextureChannel: 0 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 - _UVSec: 0 + - _XRMotionVectorsPass: 1 - _ZWrite: 1 m_Colors: - - _Color: {r: 0.53333336, g: 0.5764706, b: 0.6, a: 1} + - _BaseColor: {r: 0.5333333, g: 0.57647055, b: 0.6, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &7601943180835571591 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat.meta b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat.meta index be5622b7..78b57835 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat.meta +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Materials/M_Sky.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e91303e74a336ee4eaf3299ee34d991d +guid: f9d20658359836af8a2e03271e776196 NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png b/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png old mode 100644 new mode 100755 diff --git a/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png.meta b/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png.meta index ef77c7aa..2ce0aed0 100644 --- a/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png.meta +++ b/Assets/External/Animations/AnimationSwordCombat/Samples/Textures/T_Polygon_Dummy_01.png.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 887c2720749571e41b36e668ec74a639 +guid: 983ae9de876815b0894058ef6ddc6f42 TextureImporter: internalIDToNameTable: [] externalObjects: {} diff --git a/Assets/External/Models/PolygonDarkFortress/Materials/Brick/Brick_Large_01.mat b/Assets/External/Models/PolygonDarkFortress/Materials/Brick/Brick_Large_01.mat index 6c6fcaeb..8187ec22 100644 --- a/Assets/External/Models/PolygonDarkFortress/Materials/Brick/Brick_Large_01.mat +++ b/Assets/External/Models/PolygonDarkFortress/Materials/Brick/Brick_Large_01.mat @@ -45,7 +45,7 @@ Material: m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 + m_CustomRenderQueue: 2450 stringTagMap: {} disabledShaderPasses: - MOTIONVECTORS @@ -57,6 +57,10 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _Alpha_Texture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _Base_Texture: m_Texture: {fileID: 2800000, guid: 9614e1c2eb9ea3240a97d2245414317b, type: 3} m_Scale: {x: 1, y: 1} @@ -158,6 +162,8 @@ Material: - _AO_Intensity: 1 - _AlphaClip: 1 - _AlphaToMask: 1 + - _Alpha_Clip_Threshold: 0.5 + - _Alpha_Transparency: 1 - _BUILTIN_AlphaClip: 0 - _BUILTIN_Blend: 0 - _BUILTIN_CullMode: 2 @@ -179,12 +185,14 @@ Material: - _Cutoff: 0.5 - _DetailNormalMapScale: 1 - _DstBlend: 0 + - _DstBlendAlpha: 0 - _Enable_Ambient_Occlusion: 0 - _Enable_Base_Texture: 1 - _Enable_Emission_Texture: 0 - _Enable_Normal_Texture: 1 - _Enable_Overlay_Texture: 0 - _Enable_Snow: 0 + - _Enable_Transparency: 0 - _Enable_Triplanar_Emission: 0 - _Enable_Triplanar_Normals: 0 - _Enable_Triplanar_Texture: 1 @@ -213,6 +221,7 @@ Material: - _Snow_Use_World_Up: 1 - _SpecularHighlights: 1 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 - _Surface: 0 - _Top_Metallic: 0 - _Top_Smoothness: 0 @@ -228,6 +237,7 @@ Material: - _Triplanar_Normal_Top_To_Side_Difference: 0.2 - _Triplanar_Top_To_Side_Difference: 0.2 - _UVSec: 0 + - _Use_Separate_Alpha_Map: 0 - _WorkflowMode: 1 - _ZTest: 4 - _ZWrite: 1 @@ -235,6 +245,8 @@ Material: m_Colors: - _AO_Offset: {r: 0, g: 0, b: 0, a: 0} - _AO_Tiling: {r: 1, g: 1, b: 0, a: 0} + - _Alpha_Offset: {r: 0, g: 0, b: 0, a: 0} + - _Alpha_Tiling: {r: 1, g: 1, b: 0, a: 0} - _Base_Offset: {r: 0, g: 0, b: 0, a: 0} - _Base_Tiling: {r: 1, g: 1, b: 0, a: 0} - _Color: {r: 1, g: 1, b: 1, a: 1} diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_A.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_A.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_B.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_B.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_C.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_01_C.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_A.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_A.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_B.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_B.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_C.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_02_C.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_A.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_A.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_B.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_B.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_C.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_03_C.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_A.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_A.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_B.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_B.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_C.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Alts/Generic_04_C.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Blank.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Blank.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Candle_Glow_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Candle_Glow_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Additive_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Additive_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Multiply_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Multiply_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Soft_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Circle_Soft_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Leaf.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Leaf.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Lightray_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Lightray_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Sun_Beam_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Sun_Beam_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Wind_Streak.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/FX/Generic_Wind_Streak.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Brick.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Brick.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Carpet.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Carpet.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Cloud.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Cloud.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Concrete.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Concrete.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Dirt.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Dirt.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Glass.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Glass.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Glass_Opaque.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Glass_Opaque.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Grass.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Grass.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Ivy.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Ivy.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Mountains.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Mountains.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Overview_Map_Ground.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Overview_Map_Ground.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Plaster.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Plaster.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Road.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Road.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Rock.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Rock.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_SimpleSky.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_SimpleSky.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Skyline.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Skyline.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Triplanar_Grass_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Triplanar_Grass_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Water.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Water.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Water_Fade.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Water_Fade.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Generic_Wood.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Generic_Wood.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Glass_Opaque_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Glass_Opaque_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Skybox_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Skybox_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Materials/Waterflow_01.mat.meta b/Assets/External/Models/PolygonGeneric/Materials/Waterflow_01.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs old mode 100644 new mode 100755 index 92b2cfba..6c0e387b --- a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs +++ b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs @@ -1,35 +1,35 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Generic_SimpleRotate : MonoBehaviour -{ - - public bool rotX; - public float rotXSpeed = 50f; - public bool rotY; - public float rotYSpeed = 50f; - public bool rotZ; - public float rotZSpeed = 50f; - - // Update is called once per frame - void Update() - { - if (rotX == true) - { - transform.Rotate(Vector3.left * Time.deltaTime * rotXSpeed); - } - if (rotY == true) - { - transform.Rotate(Vector3.up * Time.deltaTime * rotYSpeed); - } - - if (rotZ == true) - { - transform.Rotate(Vector3.back * Time.deltaTime * rotZSpeed); - } - - } - - -} +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Generic_SimpleRotate : MonoBehaviour +{ + + public bool rotX; + public float rotXSpeed = 50f; + public bool rotY; + public float rotYSpeed = 50f; + public bool rotZ; + public float rotZSpeed = 50f; + + // Update is called once per frame + void Update() + { + if (rotX == true) + { + transform.Rotate(Vector3.left * Time.deltaTime * rotXSpeed); + } + if (rotY == true) + { + transform.Rotate(Vector3.up * Time.deltaTime * rotYSpeed); + } + + if (rotZ == true) + { + transform.Rotate(Vector3.back * Time.deltaTime * rotZSpeed); + } + + } + + +} diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs.meta b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleRotate.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs old mode 100644 new mode 100755 index b1424113..e3270c83 --- a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs +++ b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs @@ -1,31 +1,31 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Generic_SimpleTranslate : MonoBehaviour -{ - public bool moveX; - public float moveXSpeed = 2f; - public bool moveY; - public float moveYSpeed = 2f; - public bool moveZ; - public float moveZSpeed = 2f; - - void Update() - { - if (moveX == true) - { - transform.Translate(Vector3.left * Time.deltaTime * moveXSpeed); - } - if (moveY == true) - { - transform.Translate(Vector3.up * Time.deltaTime * moveYSpeed); - } - - if (moveZ == true) - { - transform.Translate(Vector3.back * Time.deltaTime * moveZSpeed); - } - } -} - +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Generic_SimpleTranslate : MonoBehaviour +{ + public bool moveX; + public float moveXSpeed = 2f; + public bool moveY; + public float moveYSpeed = 2f; + public bool moveZ; + public float moveZSpeed = 2f; + + void Update() + { + if (moveX == true) + { + transform.Translate(Vector3.left * Time.deltaTime * moveXSpeed); + } + if (moveY == true) + { + transform.Translate(Vector3.up * Time.deltaTime * moveYSpeed); + } + + if (moveZ == true) + { + transform.Translate(Vector3.back * Time.deltaTime * moveZSpeed); + } + } +} + diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs.meta b/Assets/External/Models/PolygonGeneric/Scripts/Generic_SimpleTranslate.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs b/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs old mode 100644 new mode 100755 index 99ab02e7..04208fed --- a/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs +++ b/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs @@ -1,44 +1,44 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Generic_WaterBob : MonoBehaviour -{ - public float bobbingHeight = 0.08f; // The height the object will bob up and down - public float bobbingSpeed = 1.5f; // The speed of the bobbing motion - public float rotationAmount = 0.8f; // The amount of rotation applied to the object - public bool randomOffset = true; // Determines if random offsets are applied to speed and rotation - public Vector2 randomRange = new Vector2(0.1f, 1f); // The range for the random offset - private Vector3 startPos; - private Quaternion startRotation; - - void Start() - { - startPos = transform.position; - startRotation = transform.rotation; // Save the initial rotation - - if (randomOffset) - { - bobbingSpeed += UnityEngine.Random.Range(randomRange.x, randomRange.y); - rotationAmount += UnityEngine.Random.Range(randomRange.x, randomRange.y); - } - } - - void Update() - { - // Calculate the vertical bobbing motion - float newY = startPos.y + Mathf.Sin(Time.time * bobbingSpeed) * bobbingHeight; - Vector3 newPos = new Vector3(transform.position.x, newY, transform.position.z); - transform.position = newPos; - - // Calculate rotation offsets based on time - float rotationX = Mathf.Sin(Time.time * bobbingSpeed * 0.5f) * rotationAmount; - float rotationY = Mathf.Sin(Time.time * bobbingSpeed * 0.7f) * rotationAmount; - float rotationZ = Mathf.Sin(Time.time * bobbingSpeed * 0.9f) * rotationAmount; - - // Apply the incremental rotation as an offset to the existing rotation - Quaternion incrementalRotation = Quaternion.Euler(rotationX, rotationY, rotationZ); - transform.rotation = startRotation * incrementalRotation; - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Generic_WaterBob : MonoBehaviour +{ + public float bobbingHeight = 0.08f; // The height the object will bob up and down + public float bobbingSpeed = 1.5f; // The speed of the bobbing motion + public float rotationAmount = 0.8f; // The amount of rotation applied to the object + public bool randomOffset = true; // Determines if random offsets are applied to speed and rotation + public Vector2 randomRange = new Vector2(0.1f, 1f); // The range for the random offset + private Vector3 startPos; + private Quaternion startRotation; + + void Start() + { + startPos = transform.position; + startRotation = transform.rotation; // Save the initial rotation + + if (randomOffset) + { + bobbingSpeed += UnityEngine.Random.Range(randomRange.x, randomRange.y); + rotationAmount += UnityEngine.Random.Range(randomRange.x, randomRange.y); + } + } + + void Update() + { + // Calculate the vertical bobbing motion + float newY = startPos.y + Mathf.Sin(Time.time * bobbingSpeed) * bobbingHeight; + Vector3 newPos = new Vector3(transform.position.x, newY, transform.position.z); + transform.position = newPos; + + // Calculate rotation offsets based on time + float rotationX = Mathf.Sin(Time.time * bobbingSpeed * 0.5f) * rotationAmount; + float rotationY = Mathf.Sin(Time.time * bobbingSpeed * 0.7f) * rotationAmount; + float rotationZ = Mathf.Sin(Time.time * bobbingSpeed * 0.9f) * rotationAmount; + + // Apply the incremental rotation as an offset to the existing rotation + Quaternion incrementalRotation = Quaternion.Euler(rotationX, rotationY, rotationZ); + transform.rotation = startRotation * incrementalRotation; + } +} diff --git a/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs.meta b/Assets/External/Models/PolygonGeneric/Scripts/Generic_WaterBob.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs old mode 100644 new mode 100755 index cfc17e74..f07b426f --- a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs +++ b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs @@ -1,204 +1,204 @@ -using UnityEditor; - -public class PolygonShaderGUI : ShaderGUI -{ - private bool _showBaseTexture = false; - private bool _showOverlayTexture = false; - private bool _showAlphaTexture = false; - private bool _showNormalTexture = false; - private bool _showTriplanar = false; - private bool _showNormalTriplanar = false; - private bool _showEmissionTexture = false; - private bool _showSnow = false; - private bool _showWave = false; - - private bool CreatePropertyGroup(string title, string[] groupProperties, bool foldout, MaterialEditor materialEditor, MaterialProperty[] allProperties) - { - foldout = EditorGUILayout.BeginFoldoutHeaderGroup(foldout, title); - if (foldout) - { - foreach (string property in groupProperties) - { - MaterialProperty propertyReference = FindProperty(property, allProperties); - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 1); - } - } - EditorGUILayout.EndFoldoutHeaderGroup(); - return foldout; - } - - override public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) - { - EditorGUILayout.LabelField("Basic Parameters", EditorStyles.boldLabel); - - // Ungrouped Basic Parameters - string[] shaderProperties = - { - "_Color_Tint", - "_Metallic", - "_Smoothness", - "_Metallic_Smoothness_Texture", - "_Ambient_Occlusion", - "_Specular_Color", - "_Alpha_Transparency" - }; - - foreach (string property in shaderProperties) - { - MaterialProperty propertyReference = FindProperty(property, properties); - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 0); - } - - EditorGUILayout.Separator(); - - // Base Texture Parameters - shaderProperties = new[] - { - "_Enable_Base_Texture", - "_Base_Texture", - "_Base_Tiling", - "_Base_Offset" - }; - - _showBaseTexture = CreatePropertyGroup("Base Texture", shaderProperties, _showBaseTexture, materialEditor, properties); - - // Alpha Texture Parameters - shaderProperties = new[] - { - "_Enable_Alpha_Texture", - "_Alpha_Texture", - "_Alpha_Tiling", - "_Alpha_Offset" - }; - - _showAlphaTexture = CreatePropertyGroup("Alpha Texture", shaderProperties, _showAlphaTexture, materialEditor, properties); - - // Normal Texture Parameters - shaderProperties = new[] - { - "_Enable_Normal_Texture", - "_Normal_Texture", - "_Normal_Tiling", - "_Normal_Offset" - }; - - _showNormalTexture = CreatePropertyGroup("Normal Texture", shaderProperties, _showNormalTexture, materialEditor, properties); - - // Emission Texture Parameters - shaderProperties = new[] - { - "_Enable_Emission_Texture", - "_Emission_Texture", - "_Emission_Tiling", - "_Emission_Offset" - }; - - _showEmissionTexture = CreatePropertyGroup("Emission Texture", shaderProperties, _showEmissionTexture, materialEditor, properties); - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Advanced Parameters", EditorStyles.boldLabel); - - // Overlay Texture Parameters - shaderProperties = new[] - { - "_Enable_Overlay_Texture", - "_Overlay_Texture", - "_Overlay_Tiling", - "_Overlay_Offset", - "_OVERLAY_UV_CHANNEL", - "_Overlay_Intensity" - }; - - _showOverlayTexture = CreatePropertyGroup("Overlay Texture", shaderProperties, _showOverlayTexture, materialEditor, properties); - - // Triplanar Texture Parameters - shaderProperties = new[] - { - "_Enable_Triplanar_Texture", - "_Triplanar_Texture_Top", - "_Triplanar_Tiling_Top", - "_Triplanar_Offset_Top", - "_Triplanar_Texture_Bottom", - "_Triplanar_Tiling_Bottom", - "_Triplanar_Offset_Bottom", - "_Triplanar_Texture_Side", - "_Triplanar_Tiling_Side", - "_Triplanar_Offset_Side", - "_Triplanar_Top_To_Side_Difference", - "_Triplanar_Fade", "_Triplanar_Intensity" - }; - - _showTriplanar = CreatePropertyGroup("Triplanar Texture", shaderProperties, _showTriplanar, materialEditor, properties); - - // Triplanar Normal Texture Parameters - shaderProperties = new[] - { - "_Enable_Triplanar_Normals", - "_Triplanar_Normal_Texture_Top", - "_Triplanar_Normal_Intensity_Top", - "_Triplanar_Normal_Tiling_Top", - "_Triplanar_Normal_Offset_Top", - "_Triplanar_Normal_Texture_Bottom", - "_Triplanar_Normal_Intensity_Bottom", - "_Triplanar_Normal_Tiling_Bottom", - "_Triplanar_Normal_Offset_Bottom", - "_Triplanar_Normal_Texture_Side", - "_Triplanar_Normal_Intensity_Side", - "_Triplanar_Normal_Tiling_Side", - "_Triplanar_Normal_Offset_Side", - "_Triplanar_Normal_Top_To_Side_Difference", - "_Triplanar_Normal_Fade" - }; - - _showNormalTriplanar = CreatePropertyGroup("Triplanar Normal Texture", shaderProperties, _showNormalTriplanar, materialEditor, properties); - - // Snow Parameters - shaderProperties = new[] - { - "_Enable_Snow", - "_Snow_Metallic", - "_Snow_Smoothness", - "_Snow_Level", - "_Snow_Transition", - "_Snow_Transition_Threshold", - "_Snow_Transition_Threshold_Steps", - "_Snow_Transition_Threshold_Step_Count", - "_Snow_Angle_Threshold", - "_Snow_Color", - "_Sea_Level", - "_Snow_Edge_Noise", - "_Snow_Noise_Tiling", - "_Snow_Noise_Offset", - "_Snow_Noise_Fade", - "_Snow_Noise_Top_To_Side_Difference", - "_Snow_Normal_Texture", - "_Snow_Overrides_Normals", - "_Snow_Normal_Intensity", - "_Snow_Normal_Tiling", - "_Snow_Normal_Offset", - "_Snow_Normal_Fade", - "_Snow_Metallic_Smoothness_Texture", - "_Snow_Metallic_Smoothness_Tiling", - "_Snow_Metallic_Smoothness_Offset" - }; - - _showSnow = CreatePropertyGroup("Snow", shaderProperties, _showSnow, materialEditor, properties); - - // Wave Parameters - shaderProperties = new[] - { - "_Enable_Wave", - "_Wave_Direction_Vector", - "_Wave_Scale", - "_Wave_Noise_Tiling", - "_Wave_Speed", - "_Fade_Wave_To_Object_Origin", - "_Fade_Wave_Scale", - "_Fade_Wave_Vertical_Offset", - "_Wave_Object_Offset" - }; - - _showWave = CreatePropertyGroup("Wave", shaderProperties, _showWave, materialEditor, properties); - } -} +using UnityEditor; + +public class PolygonShaderGUI : ShaderGUI +{ + private bool _showBaseTexture = false; + private bool _showOverlayTexture = false; + private bool _showAlphaTexture = false; + private bool _showNormalTexture = false; + private bool _showTriplanar = false; + private bool _showNormalTriplanar = false; + private bool _showEmissionTexture = false; + private bool _showSnow = false; + private bool _showWave = false; + + private bool CreatePropertyGroup(string title, string[] groupProperties, bool foldout, MaterialEditor materialEditor, MaterialProperty[] allProperties) + { + foldout = EditorGUILayout.BeginFoldoutHeaderGroup(foldout, title); + if (foldout) + { + foreach (string property in groupProperties) + { + MaterialProperty propertyReference = FindProperty(property, allProperties); + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 1); + } + } + EditorGUILayout.EndFoldoutHeaderGroup(); + return foldout; + } + + override public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + EditorGUILayout.LabelField("Basic Parameters", EditorStyles.boldLabel); + + // Ungrouped Basic Parameters + string[] shaderProperties = + { + "_Color_Tint", + "_Metallic", + "_Smoothness", + "_Metallic_Smoothness_Texture", + "_Ambient_Occlusion", + "_Specular_Color", + "_Alpha_Transparency" + }; + + foreach (string property in shaderProperties) + { + MaterialProperty propertyReference = FindProperty(property, properties); + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 0); + } + + EditorGUILayout.Separator(); + + // Base Texture Parameters + shaderProperties = new[] + { + "_Enable_Base_Texture", + "_Base_Texture", + "_Base_Tiling", + "_Base_Offset" + }; + + _showBaseTexture = CreatePropertyGroup("Base Texture", shaderProperties, _showBaseTexture, materialEditor, properties); + + // Alpha Texture Parameters + shaderProperties = new[] + { + "_Enable_Alpha_Texture", + "_Alpha_Texture", + "_Alpha_Tiling", + "_Alpha_Offset" + }; + + _showAlphaTexture = CreatePropertyGroup("Alpha Texture", shaderProperties, _showAlphaTexture, materialEditor, properties); + + // Normal Texture Parameters + shaderProperties = new[] + { + "_Enable_Normal_Texture", + "_Normal_Texture", + "_Normal_Tiling", + "_Normal_Offset" + }; + + _showNormalTexture = CreatePropertyGroup("Normal Texture", shaderProperties, _showNormalTexture, materialEditor, properties); + + // Emission Texture Parameters + shaderProperties = new[] + { + "_Enable_Emission_Texture", + "_Emission_Texture", + "_Emission_Tiling", + "_Emission_Offset" + }; + + _showEmissionTexture = CreatePropertyGroup("Emission Texture", shaderProperties, _showEmissionTexture, materialEditor, properties); + + EditorGUILayout.Separator(); + + EditorGUILayout.LabelField("Advanced Parameters", EditorStyles.boldLabel); + + // Overlay Texture Parameters + shaderProperties = new[] + { + "_Enable_Overlay_Texture", + "_Overlay_Texture", + "_Overlay_Tiling", + "_Overlay_Offset", + "_OVERLAY_UV_CHANNEL", + "_Overlay_Intensity" + }; + + _showOverlayTexture = CreatePropertyGroup("Overlay Texture", shaderProperties, _showOverlayTexture, materialEditor, properties); + + // Triplanar Texture Parameters + shaderProperties = new[] + { + "_Enable_Triplanar_Texture", + "_Triplanar_Texture_Top", + "_Triplanar_Tiling_Top", + "_Triplanar_Offset_Top", + "_Triplanar_Texture_Bottom", + "_Triplanar_Tiling_Bottom", + "_Triplanar_Offset_Bottom", + "_Triplanar_Texture_Side", + "_Triplanar_Tiling_Side", + "_Triplanar_Offset_Side", + "_Triplanar_Top_To_Side_Difference", + "_Triplanar_Fade", "_Triplanar_Intensity" + }; + + _showTriplanar = CreatePropertyGroup("Triplanar Texture", shaderProperties, _showTriplanar, materialEditor, properties); + + // Triplanar Normal Texture Parameters + shaderProperties = new[] + { + "_Enable_Triplanar_Normals", + "_Triplanar_Normal_Texture_Top", + "_Triplanar_Normal_Intensity_Top", + "_Triplanar_Normal_Tiling_Top", + "_Triplanar_Normal_Offset_Top", + "_Triplanar_Normal_Texture_Bottom", + "_Triplanar_Normal_Intensity_Bottom", + "_Triplanar_Normal_Tiling_Bottom", + "_Triplanar_Normal_Offset_Bottom", + "_Triplanar_Normal_Texture_Side", + "_Triplanar_Normal_Intensity_Side", + "_Triplanar_Normal_Tiling_Side", + "_Triplanar_Normal_Offset_Side", + "_Triplanar_Normal_Top_To_Side_Difference", + "_Triplanar_Normal_Fade" + }; + + _showNormalTriplanar = CreatePropertyGroup("Triplanar Normal Texture", shaderProperties, _showNormalTriplanar, materialEditor, properties); + + // Snow Parameters + shaderProperties = new[] + { + "_Enable_Snow", + "_Snow_Metallic", + "_Snow_Smoothness", + "_Snow_Level", + "_Snow_Transition", + "_Snow_Transition_Threshold", + "_Snow_Transition_Threshold_Steps", + "_Snow_Transition_Threshold_Step_Count", + "_Snow_Angle_Threshold", + "_Snow_Color", + "_Sea_Level", + "_Snow_Edge_Noise", + "_Snow_Noise_Tiling", + "_Snow_Noise_Offset", + "_Snow_Noise_Fade", + "_Snow_Noise_Top_To_Side_Difference", + "_Snow_Normal_Texture", + "_Snow_Overrides_Normals", + "_Snow_Normal_Intensity", + "_Snow_Normal_Tiling", + "_Snow_Normal_Offset", + "_Snow_Normal_Fade", + "_Snow_Metallic_Smoothness_Texture", + "_Snow_Metallic_Smoothness_Tiling", + "_Snow_Metallic_Smoothness_Offset" + }; + + _showSnow = CreatePropertyGroup("Snow", shaderProperties, _showSnow, materialEditor, properties); + + // Wave Parameters + shaderProperties = new[] + { + "_Enable_Wave", + "_Wave_Direction_Vector", + "_Wave_Scale", + "_Wave_Noise_Tiling", + "_Wave_Speed", + "_Fade_Wave_To_Object_Origin", + "_Fade_Wave_Scale", + "_Fade_Wave_Vertical_Offset", + "_Wave_Object_Offset" + }; + + _showWave = CreatePropertyGroup("Wave", shaderProperties, _showWave, materialEditor, properties); + } +} diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs.meta b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonShaderGUI.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs old mode 100644 new mode 100755 index 180598a4..af758b3c --- a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs +++ b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs @@ -1,145 +1,145 @@ -using UnityEditor; - -public class PolygonTransparencyShaderGUI : ShaderGUI -{ - private bool _showBaseTexture = false; - private bool _showOverlayTexture = false; - private bool _showAlphaTexture = false; - private bool _showNormalTexture = false; - private bool _showEmissionTexture = false; - private bool _showSnow = false; - - private bool CreatePropertyGroup(string title, string[] groupProperties, bool foldout, MaterialEditor materialEditor, MaterialProperty[] allProperties) - { - foldout = EditorGUILayout.BeginFoldoutHeaderGroup(foldout, title); - if (foldout) - { - foreach (string property in groupProperties) - { - MaterialProperty propertyReference = FindProperty(property, allProperties); - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 1); - } - } - EditorGUILayout.EndFoldoutHeaderGroup(); - return foldout; - } - - override public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) - { - EditorGUILayout.LabelField("Basic Parameters", EditorStyles.boldLabel); - - // Ungrouped Basic Parameters - string[] shaderProperties = - { - "_Color_Tint", - "_Metallic", - "_Smoothness", - "_Metallic_Smoothness_Texture", - "_Ambient_Occlusion", - "_Alpha_Transparency", - "_Alpha_Clip_Threshold" - }; - - foreach (string property in shaderProperties) - { - MaterialProperty propertyReference = FindProperty(property, properties); - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 0); - } - - EditorGUILayout.Separator(); - - // Base Texture Parameters - shaderProperties = new[] - { - "_Enable_Base_Texture", - "_Base_Texture", - "_Base_Tiling", - "_Base_Offset" - }; - - _showBaseTexture = CreatePropertyGroup("Base Texture", shaderProperties, _showBaseTexture, materialEditor, properties); - - // Alpha Texture Parameters - shaderProperties = new[] - { - "_Enable_Alpha_Texture", - "_Alpha_Texture", - "_Alpha_Tiling", - "_Alpha_Offset" - }; - - _showAlphaTexture = CreatePropertyGroup("Alpha Texture", shaderProperties, _showAlphaTexture, materialEditor, properties); - - // Normal Texture Parameters - shaderProperties = new[] - { - "_Enable_Normal_Texture", - "_Normal_Texture", - "_Normal_Tiling", - "_Normal_Offset" - }; - - _showNormalTexture = CreatePropertyGroup("Normal Texture", shaderProperties, _showNormalTexture, materialEditor, properties); - - // Emission Texture Parameters - shaderProperties = new[] - { - "_Enable_Emission_Texture", - "_Emission_Texture", - "_Emission_Tiling", - "_Emission_Offset" - }; - - _showEmissionTexture = CreatePropertyGroup("Emission Texture", shaderProperties, _showEmissionTexture, materialEditor, properties); - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Advanced Parameters", EditorStyles.boldLabel); - - // Overlay Texture Parameters - shaderProperties = new[] - { - "_Enable_Overlay_Texture", - "_Overlay_Texture", - "_Overlay_Tiling", - "_Overlay_Offset", - "_OVERLAY_UV_CHANNEL", - "_Overlay_Intensity" - }; - - _showOverlayTexture = CreatePropertyGroup("Overlay Texture", shaderProperties, _showOverlayTexture, materialEditor, properties); - - // Snow Parameters - shaderProperties = new[] - { - "_Enable_Snow", - "_Snow_Metallic", - "_Snow_Smoothness", - "_Snow_Level", - "_Snow_Transition", - "_Snow_Transition_Threshold", - "_Snow_Transition_Threshold_Steps", - "_Snow_Transition_Threshold_Step_Count", - "_Snow_Angle_Threshold", - "_Snow_Color", - "_Sea_Level", - "_Snow_Edge_Noise", - "_Snow_Noise_Tiling", - "_Snow_Noise_Offset", - "_Snow_Noise_Fade", - "_Snow_Noise_Top_To_Side_Difference", - "_Snow_Normal_Texture", - "_Snow_Overrides_Normals", - "_Snow_Normal_Intensity", - "_Snow_Normal_Tiling", - "_Snow_Normal_Offset", - "_Snow_Normal_Fade", - "_Snow_Metallic_Smoothness_Texture", - "_Snow_Metallic_Smoothness_Tiling", - "_Snow_Metallic_Smoothness_Offset" - }; - - _showSnow = CreatePropertyGroup("Snow", shaderProperties, _showSnow, materialEditor, properties); - - } -} +using UnityEditor; + +public class PolygonTransparencyShaderGUI : ShaderGUI +{ + private bool _showBaseTexture = false; + private bool _showOverlayTexture = false; + private bool _showAlphaTexture = false; + private bool _showNormalTexture = false; + private bool _showEmissionTexture = false; + private bool _showSnow = false; + + private bool CreatePropertyGroup(string title, string[] groupProperties, bool foldout, MaterialEditor materialEditor, MaterialProperty[] allProperties) + { + foldout = EditorGUILayout.BeginFoldoutHeaderGroup(foldout, title); + if (foldout) + { + foreach (string property in groupProperties) + { + MaterialProperty propertyReference = FindProperty(property, allProperties); + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 1); + } + } + EditorGUILayout.EndFoldoutHeaderGroup(); + return foldout; + } + + override public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + EditorGUILayout.LabelField("Basic Parameters", EditorStyles.boldLabel); + + // Ungrouped Basic Parameters + string[] shaderProperties = + { + "_Color_Tint", + "_Metallic", + "_Smoothness", + "_Metallic_Smoothness_Texture", + "_Ambient_Occlusion", + "_Alpha_Transparency", + "_Alpha_Clip_Threshold" + }; + + foreach (string property in shaderProperties) + { + MaterialProperty propertyReference = FindProperty(property, properties); + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName, 0); + } + + EditorGUILayout.Separator(); + + // Base Texture Parameters + shaderProperties = new[] + { + "_Enable_Base_Texture", + "_Base_Texture", + "_Base_Tiling", + "_Base_Offset" + }; + + _showBaseTexture = CreatePropertyGroup("Base Texture", shaderProperties, _showBaseTexture, materialEditor, properties); + + // Alpha Texture Parameters + shaderProperties = new[] + { + "_Enable_Alpha_Texture", + "_Alpha_Texture", + "_Alpha_Tiling", + "_Alpha_Offset" + }; + + _showAlphaTexture = CreatePropertyGroup("Alpha Texture", shaderProperties, _showAlphaTexture, materialEditor, properties); + + // Normal Texture Parameters + shaderProperties = new[] + { + "_Enable_Normal_Texture", + "_Normal_Texture", + "_Normal_Tiling", + "_Normal_Offset" + }; + + _showNormalTexture = CreatePropertyGroup("Normal Texture", shaderProperties, _showNormalTexture, materialEditor, properties); + + // Emission Texture Parameters + shaderProperties = new[] + { + "_Enable_Emission_Texture", + "_Emission_Texture", + "_Emission_Tiling", + "_Emission_Offset" + }; + + _showEmissionTexture = CreatePropertyGroup("Emission Texture", shaderProperties, _showEmissionTexture, materialEditor, properties); + + EditorGUILayout.Separator(); + + EditorGUILayout.LabelField("Advanced Parameters", EditorStyles.boldLabel); + + // Overlay Texture Parameters + shaderProperties = new[] + { + "_Enable_Overlay_Texture", + "_Overlay_Texture", + "_Overlay_Tiling", + "_Overlay_Offset", + "_OVERLAY_UV_CHANNEL", + "_Overlay_Intensity" + }; + + _showOverlayTexture = CreatePropertyGroup("Overlay Texture", shaderProperties, _showOverlayTexture, materialEditor, properties); + + // Snow Parameters + shaderProperties = new[] + { + "_Enable_Snow", + "_Snow_Metallic", + "_Snow_Smoothness", + "_Snow_Level", + "_Snow_Transition", + "_Snow_Transition_Threshold", + "_Snow_Transition_Threshold_Steps", + "_Snow_Transition_Threshold_Step_Count", + "_Snow_Angle_Threshold", + "_Snow_Color", + "_Sea_Level", + "_Snow_Edge_Noise", + "_Snow_Noise_Tiling", + "_Snow_Noise_Offset", + "_Snow_Noise_Fade", + "_Snow_Noise_Top_To_Side_Difference", + "_Snow_Normal_Texture", + "_Snow_Overrides_Normals", + "_Snow_Normal_Intensity", + "_Snow_Normal_Tiling", + "_Snow_Normal_Offset", + "_Snow_Normal_Fade", + "_Snow_Metallic_Smoothness_Texture", + "_Snow_Metallic_Smoothness_Tiling", + "_Snow_Metallic_Smoothness_Offset" + }; + + _showSnow = CreatePropertyGroup("Snow", shaderProperties, _showSnow, materialEditor, properties); + + } +} diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs.meta b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/PolygonTransparencyShaderGUI.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs index 05aca487..e6068693 100644 --- a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs +++ b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs @@ -1,565 +1,565 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.Rendering; - -public class polygonShaderTransparent_UI : ShaderGUI -{ - #region TabProperties - private int selectedTab = 0; - private string[] tabNames = { "Base", "Overlay", "Snow"}; - - private bool showSurfaceType = false; - private bool checkedRenderPipe = false; - private int renderPipeType = 0; - - - void CheckRenderPipeline() - { - var pipelineAsset = GraphicsSettings.defaultRenderPipeline; - - if (pipelineAsset == null) - { - Debug.Log("Using Built-In Render Pipeline (BIRP)"); - renderPipeType = 0; - } - else if (pipelineAsset.GetType().Name.Contains("UniversalRenderPipelineAsset")) - { - Debug.Log("Using Universal Render Pipeline (URP)"); - renderPipeType = 1; - } - else if (pipelineAsset.GetType().Name.Contains("HDRenderPipelineAsset")) - { - Debug.Log("Using High Definition Render Pipeline (HDRP)"); - renderPipeType = 1; - } - else - { - Debug.Log("Using custom render pipeline, falling back to BIRP settings"); - renderPipeType = 0; - } - checkedRenderPipe = true; - } - //Build Surface Type options URP - public void SurfaceOptionsBIRP(MaterialEditor materialEditor) - { - GUIStyle backdropStyle = makeBackdrop(); - - Material material = materialEditor.target as Material; - if (material != null) - { - EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); - - EditorGUILayout.BeginVertical(backdropStyle); - - // Surface Type Dropdown - int surfaceType = (int)material.GetFloat("_BUILTIN_Surface"); - - surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); - material.SetFloat("_BUILTIN_Surface", surfaceType); - - // Transparent - if (surfaceType == 1) - { - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_BUILTIN_ZWrite", 0); - material.EnableKeyword("_ALPHABLEND_ON"); - material.EnableKeyword("_ZWRITE_ON"); - } - else // Opaque - { - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_BUILTIN_ZWrite", 1); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ZWRITE_ON"); - } - - // Render Face Type - int renderFace = (int)material.GetFloat("_BUILTIN_Cull"); - renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); - material.SetFloat("_BUILTIN_Cull", renderFace); - - // Alpha Clipping - bool alphaClip = material.GetFloat("_BUILTIN_AlphaClip") == 1; - alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); - material.SetFloat("_BUILTIN_AlphaClip", alphaClip ? 1 : 0); - - if (alphaClip) - { - material.EnableKeyword("_ALPHATEST_ON"); - } - else - { - material.DisableKeyword("_ALPHATEST_ON"); - } - - - EditorGUILayout.EndVertical(); - EditorGUILayout.Separator(); - - material.shader = Shader.Find(material.shader.name); - - } - } - - //Build Surface Type options URP - public void SurfaceOptionsURP(MaterialEditor materialEditor) - { - GUIStyle backdropStyle = makeBackdrop(); - - Material material = materialEditor.target as Material; - if (material != null) - { - EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); - - EditorGUILayout.BeginVertical(backdropStyle); - - // Surface Type Dropdown - int surfaceType = (int)material.GetFloat("_Surface"); - - surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); - material.SetFloat("_Surface", surfaceType); - - // Transparent - if (surfaceType == 1) - { - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_ZWrite", 0); - material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.EnableKeyword("_ZWRITE_ON"); - } - else // Opaque - { - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_ZWrite", 1); - material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.DisableKeyword("_ZWRITE_ON"); - } - - // Render Face Type - int renderFace = (int)material.GetFloat("_Cull"); - renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); - material.SetFloat("_Cull", renderFace); - - // Alpha Clipping - bool alphaClip = material.GetFloat("_AlphaClip") == 1; - alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); - material.SetFloat("_AlphaClip", alphaClip ? 1 : 0); - material.SetFloat("_AlphaToMask", alphaClip ? 1 : 0); - if (alphaClip) - { - material.EnableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - } - else - { - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - } - - - EditorGUILayout.EndVertical(); - - EditorGUILayout.Separator(); - - material.shader = Shader.Find(material.shader.name); - - } - } - - //used to setup the tabs and what settings to call - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) - { - #region Surface Type Properties - //Set Default RenderType's - if (!checkedRenderPipe) - { - Material material = materialEditor.target as Material; - CheckRenderPipeline(); - - //Set BIRP - if (renderPipeType == 0) - { - //Make transparent - material.SetFloat("_BUILTIN_Surface", 1); - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_BUILTIN_ZWrite", 0); - material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.EnableKeyword("_ZWRITE_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - //alpha clip off - material.SetFloat("_BUILTIN_AlphaClip", 0); - material.DisableKeyword("_ALPHATEST_ON"); - //Render both faces - material.SetFloat("_BUILTIN_CullMode", 2); - } - //Set URP - else if (renderPipeType == 1) - { - //Make transparent - material.SetFloat("_Surface", 1); - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_ZWrite", 0); - material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.EnableKeyword("_ZWRITE_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - //alpha clip off - material.SetFloat("_AlphaClip", 0); - material.SetFloat("_AlphaToMask", 0); - material.DisableKeyword("_ALPHATEST_ON"); - //Render both faces - material.SetFloat("_Cull", 2); - } - - } - - //Manual Options - showSurfaceType = EditorGUILayout.Foldout(showSurfaceType, "Material Override properties"); - if (showSurfaceType) - { - //Set BIRP - if (renderPipeType == 0) - { - SurfaceOptionsBIRP(materialEditor); - } - //Set URP - else if (renderPipeType == 1) - { - SurfaceOptionsURP(materialEditor); - } - - } - #endregion - - selectedTab = GUILayout.Toolbar(selectedTab, tabNames); - - GUILayout.Space(10); - - switch (selectedTab) - { - case 0: - DrawBaseSettings(materialEditor, properties); - break; - case 1: - DrawOverlaySettings(materialEditor, properties); - break; - case 2: - DrawSnowSettings(materialEditor, properties); - break; - } - } - #endregion - - #region Vector Gui Custom Properties - Dictionary vecGuiProperties = new Dictionary - { - { "_UVPan", "Vector2" }, - { "_Base_Tiling", "Vector2" }, - { "_Base_Offset", "Vector2" }, - { "_Overlay_Tiling", "Vector2"}, - { "_Overlay_Offset", "Vector2" }, - { "_Normal_Tiling", "Vector2" }, - { "_Normal_Offset", "Vector2" }, - { "_Emission_Tiling", "Vector2" }, - { "_Emission_Offset", "Vector2" }, - { "_Alpha_Tiling", "Vector2" }, - { "_Alpha_Offset", "Vector2" }, - { "_AO_Tiling", "Vector2" }, - { "_AO_Offset", "Vector2" } - - }; - - #endregion - - #region Gui Backdrops - private static GUIStyle makeBackdrop() - { - GUIStyle backdropStyle = new GUIStyle(GUI.skin.box); - backdropStyle.padding = new RectOffset(10, 10, 10, 10); - backdropStyle.margin = new RectOffset(5, 5, 5, 5); - return backdropStyle; - } - #endregion - - //Tab 1 - #region BaseProperties - bool showBaseTextures = true; - bool showBaseNormals = true; - bool showBaseEmissions = true; - bool showBaseAlpha = true; - bool showBaseAO = true; - bool isTriplanarBaseEnabled = false; - bool isTriplanarEmissionEnabled = false; - private void DrawBaseSettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyle = makeBackdrop(); - - if (isTriplanarBaseEnabled) - { - EditorGUILayout.LabelField(">>> Triplanar enabled, Some Base Parameters Ignored. <<<", EditorStyles.boldLabel); - EditorGUILayout.Separator(); - } - - GUILayout.Label("Base Properties", EditorStyles.boldLabel); - // Add properties here - EditorGUILayout.BeginVertical(backdropStyle); - - string[] shaderProperties = - { - "_Color_Tint", - "_Metallic", - "_Smoothness", - "_Metallic_Smoothness_Texture", - //"_Specular_Color", - "_UVPan" - }; - - EditorGUILayout.Separator(); - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - EditorGUILayout.EndVertical(); - - - #region BaseTextures - EditorGUILayout.Separator(); - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropBaseTex = FindProperty("_Enable_Base_Texture", properties); - materialEditor.ShaderProperty(materialPropBaseTex, "Enable Base Textures"); - if (materialPropBaseTex.floatValue == 1) - { - showBaseTextures = EditorGUILayout.Foldout(showBaseTextures, "Base Textures"); - if (showBaseTextures) - { - // Base Texture Parameters - shaderProperties = new[] - { - "_Base_Texture", - "_Base_Tiling", - "_Base_Offset" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - - #region NormalTextures - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropNormalTex = FindProperty("_Enable_Normal_Texture", properties); - materialEditor.ShaderProperty(materialPropNormalTex, "Enable Normal Texture"); - - if (materialPropNormalTex.floatValue == 1) - { - showBaseNormals = EditorGUILayout.Foldout(showBaseNormals, "Base Normal Textures"); - if (showBaseNormals) - { - - - - // Normal Texture Parameters - shaderProperties = new[] - { - "_Normal_Texture", - "_Normal_Intensity", - "_Normal_Tiling", - "_Normal_Offset" - - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - - #region EmissionTextures - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropEmissionTex = FindProperty("_Enable_Emission_Texture", properties); - materialEditor.ShaderProperty(materialPropEmissionTex, "Enable Emission Texture"); - if (materialPropEmissionTex.floatValue == 1) - { - showBaseEmissions = EditorGUILayout.Foldout(showBaseEmissions, "Base Emission Textures"); - if (isTriplanarEmissionEnabled) - { - EditorGUILayout.LabelField(">>> Emission Triplanar Enabled, Section Overriden <<<", EditorStyles.boldLabel); - EditorGUILayout.Separator(); - } - if (showBaseEmissions) - { - // Emission Texture Parameters - shaderProperties = new[] - { - "_Emission_Texture", - "_Emission_Tiling", - "_Emission_Offset", - "_Emission_Color_Tint" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - - #region Alpha - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialAlphaTex = FindProperty("_Enable_Transparency", properties); - materialEditor.ShaderProperty(materialAlphaTex, "Enable Transparency"); - if (materialAlphaTex.floatValue == 1) - { - showBaseAlpha = EditorGUILayout.Foldout(showBaseAlpha, "Base Transparency"); - if (showBaseAlpha) - { - // Emission Texture Parameters - shaderProperties = new[] - { - "_Alpha_Texture", - "_Alpha_Tiling", - "_Alpha_Offset", - "_Alpha_Transparency", - "_Alpha_Clip_Threshold" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - - #region Ambient Occlusion - EditorGUILayout.BeginVertical(backdropStyle); - - MaterialProperty materialPropBaseAO = FindProperty("_Enable_Ambient_Occlusion", properties); - materialEditor.ShaderProperty(materialPropBaseAO, "Enable Ambient Occlusion"); - if (materialPropBaseAO.floatValue == 1) - { - showBaseAO = EditorGUILayout.Foldout(showBaseAO, "Ambient Occlusion"); - if (showBaseAO) - { - // Base Texture Parameters - shaderProperties = new[] - { - "_AO_Intensity", - "_AO_Texture", - "_AO_Tiling", - "_AO_Offset", - "_Generate_From_Base_Normals" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - - } - - #endregion - - //Tab 2 - #region OverlayProperties - private void DrawOverlaySettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyleOverlay = makeBackdrop(); - GUILayout.Label("Overlay Texture Properties", EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(backdropStyleOverlay); - - MaterialProperty materialPropOverlayTex = FindProperty("_Enable_Overlay_Texture", properties); - materialEditor.ShaderProperty(materialPropOverlayTex, "Enable Overlay Texture"); - if (materialPropOverlayTex.floatValue == 1) - { - string[] shaderProperties = - { - "_Overlay_Texture", - "_Overlay_Tiling", - "_Overlay_Offset", - "_OVERLAY_UV_CHANNEL", - "_Overlay_Intensity" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - EditorGUILayout.EndVertical(); - } - #endregion - - //Tab 3 - #region SnowProperties - private void DrawSnowSettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyleSnow = makeBackdrop(); - GUILayout.Label("Snow Properties", EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(backdropStyleSnow); - MaterialProperty materialPropSnow = FindProperty("_Enable_Snow", properties); - materialEditor.ShaderProperty(materialPropSnow, "Enable Snow"); - - if (materialPropSnow.floatValue == 1) - { - string[] shaderProperties = - { - "_Snow_Use_World_Up", - "_Snow_Color", - "_Snow_Metallic", - "_Snow_Smoothness", - "_Snow_Level", - "_Snow_Transition" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - EditorGUILayout.EndVertical(); - } - #endregion - - - #region Create Properties - //Gathers list of properties to sort and display in inspector - private static void setProperties(MaterialEditor materialEditor, MaterialProperty[] properties, string[] shaderProperties, Dictionary vecGuiProperties) - { - foreach (string property in shaderProperties) - { - MaterialProperty propertyReference = FindProperty(property, properties); - - if (vecGuiProperties.ContainsKey(property)) - { - string type = vecGuiProperties[property]; - - if (type == "Vector2") - { - Vector2 vec2Value = new Vector2(propertyReference.vectorValue.x, propertyReference.vectorValue.y); - vec2Value = EditorGUILayout.Vector2Field(propertyReference.displayName, vec2Value); - propertyReference.vectorValue = new Vector4(vec2Value.x, vec2Value.y, 0, 0); - } - else if (type == "Vector3") - { - Vector3 vec3Value = new Vector3(propertyReference.vectorValue.x, propertyReference.vectorValue.y, propertyReference.vectorValue.z); - vec3Value = EditorGUILayout.Vector3Field(propertyReference.displayName, vec3Value); - propertyReference.vectorValue = new Vector4(vec3Value.x, vec3Value.y, vec3Value.z, 0); - } - - } - else - { - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName); - } - - - } - } - #endregion - -} +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +public class polygonShaderTransparent_UI : ShaderGUI +{ + #region TabProperties + private int selectedTab = 0; + private string[] tabNames = { "Base", "Overlay", "Snow"}; + + private bool showSurfaceType = false; + private bool checkedRenderPipe = false; + private int renderPipeType = 0; + + + void CheckRenderPipeline() + { + var pipelineAsset = GraphicsSettings.defaultRenderPipeline; + + if (pipelineAsset == null) + { + Debug.Log("Using Built-In Render Pipeline (BIRP)"); + renderPipeType = 0; + } + else if (pipelineAsset.GetType().Name.Contains("UniversalRenderPipelineAsset")) + { + Debug.Log("Using Universal Render Pipeline (URP)"); + renderPipeType = 1; + } + else if (pipelineAsset.GetType().Name.Contains("HDRenderPipelineAsset")) + { + Debug.Log("Using High Definition Render Pipeline (HDRP)"); + renderPipeType = 1; + } + else + { + Debug.Log("Using custom render pipeline, falling back to BIRP settings"); + renderPipeType = 0; + } + checkedRenderPipe = true; + } + //Build Surface Type options URP + public void SurfaceOptionsBIRP(MaterialEditor materialEditor) + { + GUIStyle backdropStyle = makeBackdrop(); + + Material material = materialEditor.target as Material; + if (material != null) + { + EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); + + EditorGUILayout.BeginVertical(backdropStyle); + + // Surface Type Dropdown + int surfaceType = (int)material.GetFloat("_BUILTIN_Surface"); + + surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); + material.SetFloat("_BUILTIN_Surface", surfaceType); + + // Transparent + if (surfaceType == 1) + { + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_BUILTIN_ZWrite", 0); + material.EnableKeyword("_ALPHABLEND_ON"); + material.EnableKeyword("_ZWRITE_ON"); + } + else // Opaque + { + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_BUILTIN_ZWrite", 1); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ZWRITE_ON"); + } + + // Render Face Type + int renderFace = (int)material.GetFloat("_BUILTIN_Cull"); + renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); + material.SetFloat("_BUILTIN_Cull", renderFace); + + // Alpha Clipping + bool alphaClip = material.GetFloat("_BUILTIN_AlphaClip") == 1; + alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); + material.SetFloat("_BUILTIN_AlphaClip", alphaClip ? 1 : 0); + + if (alphaClip) + { + material.EnableKeyword("_ALPHATEST_ON"); + } + else + { + material.DisableKeyword("_ALPHATEST_ON"); + } + + + EditorGUILayout.EndVertical(); + EditorGUILayout.Separator(); + + material.shader = Shader.Find(material.shader.name); + + } + } + + //Build Surface Type options URP + public void SurfaceOptionsURP(MaterialEditor materialEditor) + { + GUIStyle backdropStyle = makeBackdrop(); + + Material material = materialEditor.target as Material; + if (material != null) + { + EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); + + EditorGUILayout.BeginVertical(backdropStyle); + + // Surface Type Dropdown + int surfaceType = (int)material.GetFloat("_Surface"); + + surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); + material.SetFloat("_Surface", surfaceType); + + // Transparent + if (surfaceType == 1) + { + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_ZWrite", 0); + material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.EnableKeyword("_ZWRITE_ON"); + } + else // Opaque + { + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_ZWrite", 1); + material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.DisableKeyword("_ZWRITE_ON"); + } + + // Render Face Type + int renderFace = (int)material.GetFloat("_Cull"); + renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); + material.SetFloat("_Cull", renderFace); + + // Alpha Clipping + bool alphaClip = material.GetFloat("_AlphaClip") == 1; + alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); + material.SetFloat("_AlphaClip", alphaClip ? 1 : 0); + material.SetFloat("_AlphaToMask", alphaClip ? 1 : 0); + if (alphaClip) + { + material.EnableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + } + else + { + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + } + + + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + + material.shader = Shader.Find(material.shader.name); + + } + } + + //used to setup the tabs and what settings to call + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + #region Surface Type Properties + //Set Default RenderType's + if (!checkedRenderPipe) + { + Material material = materialEditor.target as Material; + CheckRenderPipeline(); + + //Set BIRP + if (renderPipeType == 0) + { + //Make transparent + material.SetFloat("_BUILTIN_Surface", 1); + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_BUILTIN_ZWrite", 0); + material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.EnableKeyword("_ZWRITE_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + //alpha clip off + material.SetFloat("_BUILTIN_AlphaClip", 0); + material.DisableKeyword("_ALPHATEST_ON"); + //Render both faces + material.SetFloat("_BUILTIN_CullMode", 2); + } + //Set URP + else if (renderPipeType == 1) + { + //Make transparent + material.SetFloat("_Surface", 1); + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_ZWrite", 0); + material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.EnableKeyword("_ZWRITE_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + //alpha clip off + material.SetFloat("_AlphaClip", 0); + material.SetFloat("_AlphaToMask", 0); + material.DisableKeyword("_ALPHATEST_ON"); + //Render both faces + material.SetFloat("_Cull", 2); + } + + } + + //Manual Options + showSurfaceType = EditorGUILayout.Foldout(showSurfaceType, "Material Override properties"); + if (showSurfaceType) + { + //Set BIRP + if (renderPipeType == 0) + { + SurfaceOptionsBIRP(materialEditor); + } + //Set URP + else if (renderPipeType == 1) + { + SurfaceOptionsURP(materialEditor); + } + + } + #endregion + + selectedTab = GUILayout.Toolbar(selectedTab, tabNames); + + GUILayout.Space(10); + + switch (selectedTab) + { + case 0: + DrawBaseSettings(materialEditor, properties); + break; + case 1: + DrawOverlaySettings(materialEditor, properties); + break; + case 2: + DrawSnowSettings(materialEditor, properties); + break; + } + } + #endregion + + #region Vector Gui Custom Properties + Dictionary vecGuiProperties = new Dictionary + { + { "_UVPan", "Vector2" }, + { "_Base_Tiling", "Vector2" }, + { "_Base_Offset", "Vector2" }, + { "_Overlay_Tiling", "Vector2"}, + { "_Overlay_Offset", "Vector2" }, + { "_Normal_Tiling", "Vector2" }, + { "_Normal_Offset", "Vector2" }, + { "_Emission_Tiling", "Vector2" }, + { "_Emission_Offset", "Vector2" }, + { "_Alpha_Tiling", "Vector2" }, + { "_Alpha_Offset", "Vector2" }, + { "_AO_Tiling", "Vector2" }, + { "_AO_Offset", "Vector2" } + + }; + + #endregion + + #region Gui Backdrops + private static GUIStyle makeBackdrop() + { + GUIStyle backdropStyle = new GUIStyle(GUI.skin.box); + backdropStyle.padding = new RectOffset(10, 10, 10, 10); + backdropStyle.margin = new RectOffset(5, 5, 5, 5); + return backdropStyle; + } + #endregion + + //Tab 1 + #region BaseProperties + bool showBaseTextures = true; + bool showBaseNormals = true; + bool showBaseEmissions = true; + bool showBaseAlpha = true; + bool showBaseAO = true; + bool isTriplanarBaseEnabled = false; + bool isTriplanarEmissionEnabled = false; + private void DrawBaseSettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyle = makeBackdrop(); + + if (isTriplanarBaseEnabled) + { + EditorGUILayout.LabelField(">>> Triplanar enabled, Some Base Parameters Ignored. <<<", EditorStyles.boldLabel); + EditorGUILayout.Separator(); + } + + GUILayout.Label("Base Properties", EditorStyles.boldLabel); + // Add properties here + EditorGUILayout.BeginVertical(backdropStyle); + + string[] shaderProperties = + { + "_Color_Tint", + "_Metallic", + "_Smoothness", + "_Metallic_Smoothness_Texture", + //"_Specular_Color", + "_UVPan" + }; + + EditorGUILayout.Separator(); + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + EditorGUILayout.EndVertical(); + + + #region BaseTextures + EditorGUILayout.Separator(); + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropBaseTex = FindProperty("_Enable_Base_Texture", properties); + materialEditor.ShaderProperty(materialPropBaseTex, "Enable Base Textures"); + if (materialPropBaseTex.floatValue == 1) + { + showBaseTextures = EditorGUILayout.Foldout(showBaseTextures, "Base Textures"); + if (showBaseTextures) + { + // Base Texture Parameters + shaderProperties = new[] + { + "_Base_Texture", + "_Base_Tiling", + "_Base_Offset" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + + #region NormalTextures + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropNormalTex = FindProperty("_Enable_Normal_Texture", properties); + materialEditor.ShaderProperty(materialPropNormalTex, "Enable Normal Texture"); + + if (materialPropNormalTex.floatValue == 1) + { + showBaseNormals = EditorGUILayout.Foldout(showBaseNormals, "Base Normal Textures"); + if (showBaseNormals) + { + + + + // Normal Texture Parameters + shaderProperties = new[] + { + "_Normal_Texture", + "_Normal_Intensity", + "_Normal_Tiling", + "_Normal_Offset" + + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + + #region EmissionTextures + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropEmissionTex = FindProperty("_Enable_Emission_Texture", properties); + materialEditor.ShaderProperty(materialPropEmissionTex, "Enable Emission Texture"); + if (materialPropEmissionTex.floatValue == 1) + { + showBaseEmissions = EditorGUILayout.Foldout(showBaseEmissions, "Base Emission Textures"); + if (isTriplanarEmissionEnabled) + { + EditorGUILayout.LabelField(">>> Emission Triplanar Enabled, Section Overriden <<<", EditorStyles.boldLabel); + EditorGUILayout.Separator(); + } + if (showBaseEmissions) + { + // Emission Texture Parameters + shaderProperties = new[] + { + "_Emission_Texture", + "_Emission_Tiling", + "_Emission_Offset", + "_Emission_Color_Tint" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + + #region Alpha + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialAlphaTex = FindProperty("_Enable_Transparency", properties); + materialEditor.ShaderProperty(materialAlphaTex, "Enable Transparency"); + if (materialAlphaTex.floatValue == 1) + { + showBaseAlpha = EditorGUILayout.Foldout(showBaseAlpha, "Base Transparency"); + if (showBaseAlpha) + { + // Emission Texture Parameters + shaderProperties = new[] + { + "_Alpha_Texture", + "_Alpha_Tiling", + "_Alpha_Offset", + "_Alpha_Transparency", + "_Alpha_Clip_Threshold" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + + #region Ambient Occlusion + EditorGUILayout.BeginVertical(backdropStyle); + + MaterialProperty materialPropBaseAO = FindProperty("_Enable_Ambient_Occlusion", properties); + materialEditor.ShaderProperty(materialPropBaseAO, "Enable Ambient Occlusion"); + if (materialPropBaseAO.floatValue == 1) + { + showBaseAO = EditorGUILayout.Foldout(showBaseAO, "Ambient Occlusion"); + if (showBaseAO) + { + // Base Texture Parameters + shaderProperties = new[] + { + "_AO_Intensity", + "_AO_Texture", + "_AO_Tiling", + "_AO_Offset", + "_Generate_From_Base_Normals" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + + } + + #endregion + + //Tab 2 + #region OverlayProperties + private void DrawOverlaySettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyleOverlay = makeBackdrop(); + GUILayout.Label("Overlay Texture Properties", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(backdropStyleOverlay); + + MaterialProperty materialPropOverlayTex = FindProperty("_Enable_Overlay_Texture", properties); + materialEditor.ShaderProperty(materialPropOverlayTex, "Enable Overlay Texture"); + if (materialPropOverlayTex.floatValue == 1) + { + string[] shaderProperties = + { + "_Overlay_Texture", + "_Overlay_Tiling", + "_Overlay_Offset", + "_OVERLAY_UV_CHANNEL", + "_Overlay_Intensity" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + EditorGUILayout.EndVertical(); + } + #endregion + + //Tab 3 + #region SnowProperties + private void DrawSnowSettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyleSnow = makeBackdrop(); + GUILayout.Label("Snow Properties", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(backdropStyleSnow); + MaterialProperty materialPropSnow = FindProperty("_Enable_Snow", properties); + materialEditor.ShaderProperty(materialPropSnow, "Enable Snow"); + + if (materialPropSnow.floatValue == 1) + { + string[] shaderProperties = + { + "_Snow_Use_World_Up", + "_Snow_Color", + "_Snow_Metallic", + "_Snow_Smoothness", + "_Snow_Level", + "_Snow_Transition" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + EditorGUILayout.EndVertical(); + } + #endregion + + + #region Create Properties + //Gathers list of properties to sort and display in inspector + private static void setProperties(MaterialEditor materialEditor, MaterialProperty[] properties, string[] shaderProperties, Dictionary vecGuiProperties) + { + foreach (string property in shaderProperties) + { + MaterialProperty propertyReference = FindProperty(property, properties); + + if (vecGuiProperties.ContainsKey(property)) + { + string type = vecGuiProperties[property]; + + if (type == "Vector2") + { + Vector2 vec2Value = new Vector2(propertyReference.vectorValue.x, propertyReference.vectorValue.y); + vec2Value = EditorGUILayout.Vector2Field(propertyReference.displayName, vec2Value); + propertyReference.vectorValue = new Vector4(vec2Value.x, vec2Value.y, 0, 0); + } + else if (type == "Vector3") + { + Vector3 vec3Value = new Vector3(propertyReference.vectorValue.x, propertyReference.vectorValue.y, propertyReference.vectorValue.z); + vec3Value = EditorGUILayout.Vector3Field(propertyReference.displayName, vec3Value); + propertyReference.vectorValue = new Vector4(vec3Value.x, vec3Value.y, vec3Value.z, 0); + } + + } + else + { + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName); + } + + + } + } + #endregion + +} diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs.meta b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShaderTransparent_UI.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs index 2f38a5d1..2f4dec34 100644 --- a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs +++ b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs @@ -1,686 +1,686 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.Rendering; - -public class polygonShader_UI : ShaderGUI -{ - #region TabProperties - private int selectedTab = 0; - private string[] tabNames = { "Base", "Overlay", "Triplanar", "Snow" }; - - private bool showSurfaceType = false; - private bool checkedRenderPipe = false; - private int renderPipeType = 0; - - void CheckRenderPipeline() - { - var pipelineAsset = GraphicsSettings.defaultRenderPipeline; - - if (pipelineAsset == null) - { - Debug.Log("Using Built-In Render Pipeline (BIRP)"); - renderPipeType = 0; - } - else if (pipelineAsset.GetType().Name.Contains("UniversalRenderPipelineAsset")) - { - Debug.Log("Using Universal Render Pipeline (URP)"); - renderPipeType = 1; - } - else if (pipelineAsset.GetType().Name.Contains("HDRenderPipelineAsset")) - { - Debug.Log("Using High Definition Render Pipeline (HDRP)"); - renderPipeType = 1; - } - else - { - Debug.Log("Using custom render pipeline, falling back to BIRP settings"); - renderPipeType = 0; - } - checkedRenderPipe = true; - } - //Build Surface Type options BIRP - public void SurfaceOptionsBIRP(MaterialEditor materialEditor) - { - GUIStyle backdropStyle = makeBackdrop(); - - Material material = materialEditor.target as Material; - if (material != null) - { - EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); - - EditorGUILayout.BeginVertical(backdropStyle); - - // Surface Type Dropdown - int surfaceType = (int)material.GetFloat("_BUILTIN_Surface"); - - surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); - material.SetFloat("_BUILTIN_Surface", surfaceType); - - // Transparent - if (surfaceType == 1) - { - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_BUILTIN_ZWrite", 0); - material.EnableKeyword("_ALPHABLEND_ON"); - material.EnableKeyword("_ZWRITE_ON"); - material.EnableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); - } - else // Opaque - { - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_BUILTIN_ZWrite", 1); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ZWRITE_ON"); - material.DisableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); - } - - // Render Face Type - int renderFace = (int)material.GetFloat("_BUILTIN_CullMode"); - renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); - material.SetFloat("_BUILTIN_CullMode", renderFace); - - // Alpha Clipping - bool alphaClip = material.GetFloat("_BUILTIN_AlphaClip") == 1; - alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); - material.SetFloat("_BUILTIN_AlphaClip", alphaClip ? 1 : 0); - - if (alphaClip) - { - material.EnableKeyword("_BUILTIN_ALPHATEST_ON"); - material.EnableKeyword("_BUILTIN_AlphaClip"); - } - else - { - material.DisableKeyword("_BUILTIN_ALPHATEST_ON"); - material.DisableKeyword("_BUILTIN_AlphaClip"); - } - - - EditorGUILayout.EndVertical(); - EditorGUILayout.Separator(); - - material.shader = Shader.Find(material.shader.name); - - } - } - - //Build Surface Type options URP - public void SurfaceOptionsURP(MaterialEditor materialEditor) - { - GUIStyle backdropStyle = makeBackdrop(); - - Material material = materialEditor.target as Material; - if (material != null) - { - EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); - - EditorGUILayout.BeginVertical(backdropStyle); - - // Surface Type Dropdown - int surfaceType = (int)material.GetFloat("_Surface"); - - surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); - material.SetFloat("_Surface", surfaceType); - - // Transparent - if (surfaceType == 1) - { - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetFloat("_ZWrite", 0); - material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.EnableKeyword("_ZWRITE_ON"); - } - else // Opaque - { - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_ZWrite", 1); - material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.DisableKeyword("_ZWRITE_ON"); - } - - // Render Face Type - int renderFace = (int)material.GetFloat("_Cull"); - renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); - material.SetFloat("_Cull", renderFace); - - // Alpha Clipping - bool alphaClip = material.GetFloat("_AlphaClip") == 1; - alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); - material.SetFloat("_AlphaClip", alphaClip ? 1 : 0); - material.SetFloat("_AlphaToMask", alphaClip ? 1 : 0); - if (alphaClip) - { - material.EnableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - } - else - { - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - } - - - EditorGUILayout.EndVertical(); - - EditorGUILayout.Separator(); - - material.shader = Shader.Find(material.shader.name); - - } - } - - //used to setup the tabs and what settings to call - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) - { - #region Surface Type Properties - //Set Default RenderType's - if (!checkedRenderPipe) - { - Material material = materialEditor.target as Material; - CheckRenderPipeline(); - - //Set BIRP - if (renderPipeType == 0) - { - //Make opaque - material.SetFloat("_BUILTIN_Surface", 0); - material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_BUILTIN_ZWrite", 1); - material.DisableKeyword("_ZWRITE_ON"); - material.DisableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); - //alpha clip on - material.SetFloat("_BUILTIN_AlphaClip", 0); - material.EnableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_BUILTIN_AlphaClip"); - //Render both faces - material.SetFloat("_BUILTIN_CullMode", 2); - } - //Set URP - else if (renderPipeType == 1) - { - //Make opaque - material.SetFloat("_Surface", 0); - material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); - material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); - material.SetFloat("_ZWrite", 1); - material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.DisableKeyword("_ZWRITE_ON"); - //alpha clip on - material.SetFloat("_AlphaClip", 1); - material.SetFloat("_AlphaToMask", 1); - material.EnableKeyword("_ALPHATEST_ON"); - //Render both faces - material.SetFloat("_Cull", 2); - } - - } - - //Manual Options - showSurfaceType = EditorGUILayout.Foldout(showSurfaceType, "Material Override properties"); - if (showSurfaceType) - { - //Set BIRP - if (renderPipeType == 0) - { - SurfaceOptionsBIRP(materialEditor); - } - //Set URP - else if (renderPipeType == 1) - { - SurfaceOptionsURP(materialEditor); - } - - } - #endregion - - selectedTab = GUILayout.Toolbar(selectedTab, tabNames); - - - GUILayout.Space(10); - - switch (selectedTab) - { - case 0: - DrawBaseSettings(materialEditor, properties); - break; - case 1: - DrawOverlaySettings(materialEditor, properties); - break; - case 2: - DrawTriplanarSettings(materialEditor, properties); - break; - case 3: - DrawSnowSettings(materialEditor, properties); - break; - - } - } - #endregion - - #region Vector Gui Custom Properties - Dictionary vecGuiProperties = new Dictionary - { - { "_UVPan", "Vector2" }, - { "_Base_Tiling", "Vector2" }, - { "_Base_Offset", "Vector2" }, - { "_Overlay_Tiling", "Vector2"}, - { "_Overlay_Offset", "Vector2" }, - { "_Normal_Tiling", "Vector2" }, - { "_Normal_Offset", "Vector2" }, - { "_Emission_Tiling", "Vector2" }, - { "_Emission_Offset", "Vector2" }, - { "_AO_Tiling", "Vector2" }, - { "_AO_Offset", "Vector2" }, - { "_Triplanar_Tiling_Top", "Vector2" }, - { "_Triplanar_Offset_Top", "Vector2" }, - { "_Triplanar_Tiling_Bottom", "Vector2" }, - { "_Triplanar_Offset_Bottom", "Vector2" }, - { "_Triplanar_Tiling_Side", "Vector2" }, - { "_Triplanar_Offset_Side", "Vector2" }, - { "_Triplanar_Normal_Tiling_Top", "Vector2" }, - { "_Triplanar_Normal_Offset_Top", "Vector2" }, - { "_Triplanar_Normal_Tiling_Bottom", "Vector2" }, - { "_Triplanar_Normal_Offset_Bottom", "Vector2" }, - { "_Triplanar_Normal_Tiling_Side", "Vector2" }, - { "_Triplanar_Normal_Offset_Side", "Vector2" } - - }; - - #endregion - - #region Gui Backdrops - private static GUIStyle makeBackdrop() - { - GUIStyle backdropStyle = new GUIStyle(GUI.skin.box); - backdropStyle.padding = new RectOffset(10, 10, 10, 10); - backdropStyle.margin = new RectOffset(5, 5, 5, 5); - return backdropStyle; - } - #endregion - - //Tab 1 - #region BaseProperties - bool showBaseTextures = true; - bool showBaseNormals = true; - bool showBaseEmissions = true; - bool showBaseAO = true; - bool isTriplanarBaseEnabled = false; - bool isTriplanarEmissionEnabled = false; - private void DrawBaseSettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyle = makeBackdrop(); - - if (isTriplanarBaseEnabled) - { - EditorGUILayout.LabelField(">>> Triplanar enabled, Some Base Parameters Ignored. <<<", EditorStyles.boldLabel); - EditorGUILayout.Separator(); - } - - GUILayout.Label("Base Properties", EditorStyles.boldLabel); - // Add properties here - EditorGUILayout.BeginVertical(backdropStyle); - - string[] shaderProperties = - { - "_Color_Tint", - "_Metallic", - "_Smoothness", - "_Metallic_Smoothness_Texture", - //"_Specular_Color", - "_UVPan" - }; - - EditorGUILayout.Separator(); - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - EditorGUILayout.EndVertical(); - - - #region BaseTextures - EditorGUILayout.Separator(); - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropBaseTex = FindProperty("_Enable_Base_Texture", properties); - materialEditor.ShaderProperty(materialPropBaseTex, "Enable Base Textures"); - if (materialPropBaseTex.floatValue == 1) - { - showBaseTextures = EditorGUILayout.Foldout(showBaseTextures, "Base Textures"); - if (showBaseTextures) - { - // Base Texture Parameters - shaderProperties = new[] - { - "_Base_Texture", - "_Base_Tiling", - "_Base_Offset" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - - EditorGUILayout.Separator(); - - #region NormalTextures - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropNormalTex = FindProperty("_Enable_Normal_Texture", properties); - materialEditor.ShaderProperty(materialPropNormalTex, "Enable Normal Texture"); - - if (materialPropNormalTex.floatValue == 1) - { - showBaseNormals = EditorGUILayout.Foldout(showBaseNormals, "Base Normal Textures"); - if (showBaseNormals) - { - - - - // Normal Texture Parameters - shaderProperties = new[] - { - "_Normal_Texture", - "_Normal_Intensity", - "_Normal_Tiling", - "_Normal_Offset" - - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - - EditorGUILayout.Separator(); - - #region EmissionTextures - - EditorGUILayout.BeginVertical(backdropStyle); - MaterialProperty materialPropEmissionTex = FindProperty("_Enable_Emission_Texture", properties); - materialEditor.ShaderProperty(materialPropEmissionTex, "Enable Emission Texture"); - if (materialPropEmissionTex.floatValue == 1) - { - showBaseEmissions = EditorGUILayout.Foldout(showBaseEmissions, "Base Emission Textures"); - if (isTriplanarEmissionEnabled) - { - EditorGUILayout.LabelField(">>> Emission Triplanar Enabled, Section Overriden <<<", EditorStyles.boldLabel); - EditorGUILayout.Separator(); - } - if (showBaseEmissions) - { - // Emission Texture Parameters - shaderProperties = new[] - { - "_Emission_Texture", - "_Emission_Tiling", - "_Emission_Offset", - "_Emission_Color_Tint" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - - EditorGUILayout.Separator(); - - #region Ambient Occlusion - EditorGUILayout.BeginVertical(backdropStyle); - - MaterialProperty materialPropBaseAO = FindProperty("_Enable_Ambient_Occlusion", properties); - materialEditor.ShaderProperty(materialPropBaseAO, "Enable Ambient Occlusion"); - if (materialPropBaseAO.floatValue == 1) - { - showBaseAO = EditorGUILayout.Foldout(showBaseAO, "Ambient Occlusion"); - if (showBaseAO) - { - // Base Texture Parameters - shaderProperties = new[] - { - "_AO_Intensity", - "_AO_Texture", - "_AO_Tiling", - "_AO_Offset", - "_Generate_From_Base_Normals" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - - } - - #endregion - - //Tab 2 - #region OverlayProperties - private void DrawOverlaySettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyleOverlay = makeBackdrop(); - GUILayout.Label("Overlay Texture Properties", EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(backdropStyleOverlay); - - MaterialProperty materialPropOverlayTex = FindProperty("_Enable_Overlay_Texture", properties); - materialEditor.ShaderProperty(materialPropOverlayTex, "Enable Overlay Texture"); - if (materialPropOverlayTex.floatValue == 1) - { - string[] shaderProperties = - { - "_Overlay_Texture", - "_Overlay_Tiling", - "_Overlay_Offset", - "_OVERLAY_UV_CHANNEL", - "_Overlay_Intensity" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - EditorGUILayout.EndVertical(); - } - #endregion - - //Tab 3 - #region TriplanarProperties - - bool enableTriplanarBase = true; - bool enableTriplanarNormals = true; - bool enableTriplanarEmission = true; - - private void DrawTriplanarSettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyleTriplanar = makeBackdrop(); - #region Base Triplanar Textures - - EditorGUILayout.BeginVertical(backdropStyleTriplanar); - MaterialProperty materialPropTriplanarBase = FindProperty("_Enable_Triplanar_Texture", properties); - materialEditor.ShaderProperty(materialPropTriplanarBase, "Enable Base Triplanar Textures"); - - if (materialPropTriplanarBase.floatValue == 1) - { - isTriplanarBaseEnabled = true; - enableTriplanarBase = EditorGUILayout.Foldout(enableTriplanarBase, "Triplanar Base Textures"); - if (enableTriplanarBase) - { - // Triplanar Base - string[] shaderProperties = - { - "_Triplanar_Texture_Top", - "_Triplanar_Tiling_Top", - "_Triplanar_Offset_Top", - "_Triplanar_Texture_Bottom", - "_Triplanar_Tiling_Bottom", - "_Triplanar_Offset_Bottom", - "_Triplanar_Texture_Side", - "_Triplanar_Tiling_Side", - "_Triplanar_Offset_Side", - "_Triplanar_Top_To_Side_Difference", - "_Triplanar_Fade", - "_Triplanar_Intensity", - "_Top_Metallic", - "_Side_Metallic", - "_Bottom_Metallic", - "_Top_Smoothness", - "_Side_Smoothness", - "_Bottom_Smoothness" - - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - - } - else - { - isTriplanarBaseEnabled = false; - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - #region Normal Triplanar Textures - EditorGUILayout.BeginVertical(backdropStyleTriplanar); - MaterialProperty materialPropTriplanarNormals = FindProperty("_Enable_Triplanar_Normals", properties); - materialEditor.ShaderProperty(materialPropTriplanarNormals, "Enable Triplanar Normals"); - - if (materialPropTriplanarNormals.floatValue == 1) - { - enableTriplanarNormals = EditorGUILayout.Foldout(enableTriplanarNormals, "Triplanar Normal Textures"); - if (enableTriplanarNormals) - { - // Triplanar Base - string[] shaderProperties = - { - "_Triplanar_Normal_Texture_Top", - "_Triplanar_Normal_Intensity_Top", - "_Triplanar_Normal_Tiling_Top", - "_Triplanar_Normal_Offset_Top", - "_Triplanar_Normal_Texture_Bottom", - "_Triplanar_Normal_Intensity_Bottom", - "_Triplanar_Normal_Tiling_Bottom", - "_Triplanar_Normal_Offset_Bottom", - "_Triplanar_Normal_Texture_Side", - "_Triplanar_Normal_Intensity_Side", - "_Triplanar_Normal_Tiling_Side", - "_Triplanar_Normal_Offset_Side", - "_Triplanar_Normal_Top_To_Side_Difference", - "_Triplanar_Normal_Fade" - - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - } - EditorGUILayout.EndVertical(); - #endregion - EditorGUILayout.Separator(); - #region Emission Triplanar Textures - EditorGUILayout.BeginVertical(backdropStyleTriplanar); - MaterialProperty materialPropTriplanarEmission = FindProperty("_Enable_Triplanar_Emission", properties); - materialEditor.ShaderProperty(materialPropTriplanarEmission, "Enable Triplanar Emission"); - - if (materialPropTriplanarEmission.floatValue == 1) - { - isTriplanarEmissionEnabled = true; - enableTriplanarEmission = EditorGUILayout.Foldout(enableTriplanarEmission, "Triplanar Emission Textures"); - if (enableTriplanarEmission) - { - // Triplanar Base - string[] shaderProperties = - { - "_Triplanar_Emission_Texture", - "_Triplanar_Emission_Tiling", - "_Triplanar_Emission_Blend", - "_Triplanar_Emission_Intensity", - "_Triplanar_Emission_Color_Tint" - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - - } - else - { - isTriplanarEmissionEnabled = false; - } - EditorGUILayout.EndVertical(); - #endregion - - } - #endregion - - //Tab 4 - #region SnowProperties - private void DrawSnowSettings(MaterialEditor materialEditor, MaterialProperty[] properties) - { - GUIStyle backdropStyleSnow = makeBackdrop(); - GUILayout.Label("Snow Properties", EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(backdropStyleSnow); - MaterialProperty materialPropSnow = FindProperty("_Enable_Snow", properties); - materialEditor.ShaderProperty(materialPropSnow, "Enable Snow"); - - if (materialPropSnow.floatValue == 1) - { - string[] shaderProperties = - { - "_Snow_Use_World_Up", - "_Snow_Color", - "_Snow_Metallic", - "_Snow_Smoothness", - "_Snow_Level", - "_Snow_Transition" - - }; - - setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); - } - EditorGUILayout.EndVertical(); - } - #endregion - - #region Create Properties - //Gathers list of properties to sort and display in inspector - private static void setProperties(MaterialEditor materialEditor, MaterialProperty[] properties, string[] shaderProperties, Dictionary vecGuiProperties) - { - foreach (string property in shaderProperties) - { - MaterialProperty propertyReference = FindProperty(property, properties); - - if (vecGuiProperties.ContainsKey(property)) - { - string type = vecGuiProperties[property]; - - if (type == "Vector2") - { - Vector2 vec2Value = new Vector2(propertyReference.vectorValue.x, propertyReference.vectorValue.y); - vec2Value = EditorGUILayout.Vector2Field(propertyReference.displayName, vec2Value); - propertyReference.vectorValue = new Vector4(vec2Value.x, vec2Value.y, 0, 0); - } - else if (type == "Vector3") - { - Vector3 vec3Value = new Vector3(propertyReference.vectorValue.x, propertyReference.vectorValue.y, propertyReference.vectorValue.z); - vec3Value = EditorGUILayout.Vector3Field(propertyReference.displayName, vec3Value); - propertyReference.vectorValue = new Vector4(vec3Value.x, vec3Value.y, vec3Value.z, 0); - } - - } - else - { - materialEditor.ShaderProperty(propertyReference, propertyReference.displayName); - } - - - } - } - #endregion - -} +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +public class polygonShader_UI : ShaderGUI +{ + #region TabProperties + private int selectedTab = 0; + private string[] tabNames = { "Base", "Overlay", "Triplanar", "Snow" }; + + private bool showSurfaceType = false; + private bool checkedRenderPipe = false; + private int renderPipeType = 0; + + void CheckRenderPipeline() + { + var pipelineAsset = GraphicsSettings.defaultRenderPipeline; + + if (pipelineAsset == null) + { + Debug.Log("Using Built-In Render Pipeline (BIRP)"); + renderPipeType = 0; + } + else if (pipelineAsset.GetType().Name.Contains("UniversalRenderPipelineAsset")) + { + Debug.Log("Using Universal Render Pipeline (URP)"); + renderPipeType = 1; + } + else if (pipelineAsset.GetType().Name.Contains("HDRenderPipelineAsset")) + { + Debug.Log("Using High Definition Render Pipeline (HDRP)"); + renderPipeType = 1; + } + else + { + Debug.Log("Using custom render pipeline, falling back to BIRP settings"); + renderPipeType = 0; + } + checkedRenderPipe = true; + } + //Build Surface Type options BIRP + public void SurfaceOptionsBIRP(MaterialEditor materialEditor) + { + GUIStyle backdropStyle = makeBackdrop(); + + Material material = materialEditor.target as Material; + if (material != null) + { + EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); + + EditorGUILayout.BeginVertical(backdropStyle); + + // Surface Type Dropdown + int surfaceType = (int)material.GetFloat("_BUILTIN_Surface"); + + surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); + material.SetFloat("_BUILTIN_Surface", surfaceType); + + // Transparent + if (surfaceType == 1) + { + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_BUILTIN_ZWrite", 0); + material.EnableKeyword("_ALPHABLEND_ON"); + material.EnableKeyword("_ZWRITE_ON"); + material.EnableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); + } + else // Opaque + { + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_BUILTIN_ZWrite", 1); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ZWRITE_ON"); + material.DisableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); + } + + // Render Face Type + int renderFace = (int)material.GetFloat("_BUILTIN_CullMode"); + renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); + material.SetFloat("_BUILTIN_CullMode", renderFace); + + // Alpha Clipping + bool alphaClip = material.GetFloat("_BUILTIN_AlphaClip") == 1; + alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); + material.SetFloat("_BUILTIN_AlphaClip", alphaClip ? 1 : 0); + + if (alphaClip) + { + material.EnableKeyword("_BUILTIN_ALPHATEST_ON"); + material.EnableKeyword("_BUILTIN_AlphaClip"); + } + else + { + material.DisableKeyword("_BUILTIN_ALPHATEST_ON"); + material.DisableKeyword("_BUILTIN_AlphaClip"); + } + + + EditorGUILayout.EndVertical(); + EditorGUILayout.Separator(); + + material.shader = Shader.Find(material.shader.name); + + } + } + + //Build Surface Type options URP + public void SurfaceOptionsURP(MaterialEditor materialEditor) + { + GUIStyle backdropStyle = makeBackdrop(); + + Material material = materialEditor.target as Material; + if (material != null) + { + EditorGUILayout.LabelField("Surface Options", EditorStyles.boldLabel); + + EditorGUILayout.BeginVertical(backdropStyle); + + // Surface Type Dropdown + int surfaceType = (int)material.GetFloat("_Surface"); + + surfaceType = EditorGUILayout.Popup("Surface Type", surfaceType, new string[] { "Opaque", "Transparent" }); + material.SetFloat("_Surface", surfaceType); + + // Transparent + if (surfaceType == 1) + { + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetFloat("_ZWrite", 0); + material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.EnableKeyword("_ZWRITE_ON"); + } + else // Opaque + { + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_ZWrite", 1); + material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.DisableKeyword("_ZWRITE_ON"); + } + + // Render Face Type + int renderFace = (int)material.GetFloat("_Cull"); + renderFace = EditorGUILayout.Popup("Render Face", renderFace, new string[] { "Both", "Back", "Front" }); + material.SetFloat("_Cull", renderFace); + + // Alpha Clipping + bool alphaClip = material.GetFloat("_AlphaClip") == 1; + alphaClip = EditorGUILayout.Toggle("Alpha Clipping", alphaClip); + material.SetFloat("_AlphaClip", alphaClip ? 1 : 0); + material.SetFloat("_AlphaToMask", alphaClip ? 1 : 0); + if (alphaClip) + { + material.EnableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + } + else + { + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + } + + + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + + material.shader = Shader.Find(material.shader.name); + + } + } + + //used to setup the tabs and what settings to call + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + #region Surface Type Properties + //Set Default RenderType's + if (!checkedRenderPipe) + { + Material material = materialEditor.target as Material; + CheckRenderPipeline(); + + //Set BIRP + if (renderPipeType == 0) + { + //Make opaque + material.SetFloat("_BUILTIN_Surface", 0); + material.SetFloat("_BUILTIN_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_BUILTIN_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_BUILTIN_ZWrite", 1); + material.DisableKeyword("_ZWRITE_ON"); + material.DisableKeyword("_BUILTIN_SURFACE_TYPE_TRANSPARENT"); + //alpha clip on + material.SetFloat("_BUILTIN_AlphaClip", 0); + material.EnableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_BUILTIN_AlphaClip"); + //Render both faces + material.SetFloat("_BUILTIN_CullMode", 2); + } + //Set URP + else if (renderPipeType == 1) + { + //Make opaque + material.SetFloat("_Surface", 0); + material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One); + material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero); + material.SetFloat("_ZWrite", 1); + material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.DisableKeyword("_ZWRITE_ON"); + //alpha clip on + material.SetFloat("_AlphaClip", 1); + material.SetFloat("_AlphaToMask", 1); + material.EnableKeyword("_ALPHATEST_ON"); + //Render both faces + material.SetFloat("_Cull", 2); + } + + } + + //Manual Options + showSurfaceType = EditorGUILayout.Foldout(showSurfaceType, "Material Override properties"); + if (showSurfaceType) + { + //Set BIRP + if (renderPipeType == 0) + { + SurfaceOptionsBIRP(materialEditor); + } + //Set URP + else if (renderPipeType == 1) + { + SurfaceOptionsURP(materialEditor); + } + + } + #endregion + + selectedTab = GUILayout.Toolbar(selectedTab, tabNames); + + + GUILayout.Space(10); + + switch (selectedTab) + { + case 0: + DrawBaseSettings(materialEditor, properties); + break; + case 1: + DrawOverlaySettings(materialEditor, properties); + break; + case 2: + DrawTriplanarSettings(materialEditor, properties); + break; + case 3: + DrawSnowSettings(materialEditor, properties); + break; + + } + } + #endregion + + #region Vector Gui Custom Properties + Dictionary vecGuiProperties = new Dictionary + { + { "_UVPan", "Vector2" }, + { "_Base_Tiling", "Vector2" }, + { "_Base_Offset", "Vector2" }, + { "_Overlay_Tiling", "Vector2"}, + { "_Overlay_Offset", "Vector2" }, + { "_Normal_Tiling", "Vector2" }, + { "_Normal_Offset", "Vector2" }, + { "_Emission_Tiling", "Vector2" }, + { "_Emission_Offset", "Vector2" }, + { "_AO_Tiling", "Vector2" }, + { "_AO_Offset", "Vector2" }, + { "_Triplanar_Tiling_Top", "Vector2" }, + { "_Triplanar_Offset_Top", "Vector2" }, + { "_Triplanar_Tiling_Bottom", "Vector2" }, + { "_Triplanar_Offset_Bottom", "Vector2" }, + { "_Triplanar_Tiling_Side", "Vector2" }, + { "_Triplanar_Offset_Side", "Vector2" }, + { "_Triplanar_Normal_Tiling_Top", "Vector2" }, + { "_Triplanar_Normal_Offset_Top", "Vector2" }, + { "_Triplanar_Normal_Tiling_Bottom", "Vector2" }, + { "_Triplanar_Normal_Offset_Bottom", "Vector2" }, + { "_Triplanar_Normal_Tiling_Side", "Vector2" }, + { "_Triplanar_Normal_Offset_Side", "Vector2" } + + }; + + #endregion + + #region Gui Backdrops + private static GUIStyle makeBackdrop() + { + GUIStyle backdropStyle = new GUIStyle(GUI.skin.box); + backdropStyle.padding = new RectOffset(10, 10, 10, 10); + backdropStyle.margin = new RectOffset(5, 5, 5, 5); + return backdropStyle; + } + #endregion + + //Tab 1 + #region BaseProperties + bool showBaseTextures = true; + bool showBaseNormals = true; + bool showBaseEmissions = true; + bool showBaseAO = true; + bool isTriplanarBaseEnabled = false; + bool isTriplanarEmissionEnabled = false; + private void DrawBaseSettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyle = makeBackdrop(); + + if (isTriplanarBaseEnabled) + { + EditorGUILayout.LabelField(">>> Triplanar enabled, Some Base Parameters Ignored. <<<", EditorStyles.boldLabel); + EditorGUILayout.Separator(); + } + + GUILayout.Label("Base Properties", EditorStyles.boldLabel); + // Add properties here + EditorGUILayout.BeginVertical(backdropStyle); + + string[] shaderProperties = + { + "_Color_Tint", + "_Metallic", + "_Smoothness", + "_Metallic_Smoothness_Texture", + //"_Specular_Color", + "_UVPan" + }; + + EditorGUILayout.Separator(); + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + EditorGUILayout.EndVertical(); + + + #region BaseTextures + EditorGUILayout.Separator(); + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropBaseTex = FindProperty("_Enable_Base_Texture", properties); + materialEditor.ShaderProperty(materialPropBaseTex, "Enable Base Textures"); + if (materialPropBaseTex.floatValue == 1) + { + showBaseTextures = EditorGUILayout.Foldout(showBaseTextures, "Base Textures"); + if (showBaseTextures) + { + // Base Texture Parameters + shaderProperties = new[] + { + "_Base_Texture", + "_Base_Tiling", + "_Base_Offset" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + + EditorGUILayout.Separator(); + + #region NormalTextures + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropNormalTex = FindProperty("_Enable_Normal_Texture", properties); + materialEditor.ShaderProperty(materialPropNormalTex, "Enable Normal Texture"); + + if (materialPropNormalTex.floatValue == 1) + { + showBaseNormals = EditorGUILayout.Foldout(showBaseNormals, "Base Normal Textures"); + if (showBaseNormals) + { + + + + // Normal Texture Parameters + shaderProperties = new[] + { + "_Normal_Texture", + "_Normal_Intensity", + "_Normal_Tiling", + "_Normal_Offset" + + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + + EditorGUILayout.Separator(); + + #region EmissionTextures + + EditorGUILayout.BeginVertical(backdropStyle); + MaterialProperty materialPropEmissionTex = FindProperty("_Enable_Emission_Texture", properties); + materialEditor.ShaderProperty(materialPropEmissionTex, "Enable Emission Texture"); + if (materialPropEmissionTex.floatValue == 1) + { + showBaseEmissions = EditorGUILayout.Foldout(showBaseEmissions, "Base Emission Textures"); + if (isTriplanarEmissionEnabled) + { + EditorGUILayout.LabelField(">>> Emission Triplanar Enabled, Section Overriden <<<", EditorStyles.boldLabel); + EditorGUILayout.Separator(); + } + if (showBaseEmissions) + { + // Emission Texture Parameters + shaderProperties = new[] + { + "_Emission_Texture", + "_Emission_Tiling", + "_Emission_Offset", + "_Emission_Color_Tint" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + + EditorGUILayout.Separator(); + + #region Ambient Occlusion + EditorGUILayout.BeginVertical(backdropStyle); + + MaterialProperty materialPropBaseAO = FindProperty("_Enable_Ambient_Occlusion", properties); + materialEditor.ShaderProperty(materialPropBaseAO, "Enable Ambient Occlusion"); + if (materialPropBaseAO.floatValue == 1) + { + showBaseAO = EditorGUILayout.Foldout(showBaseAO, "Ambient Occlusion"); + if (showBaseAO) + { + // Base Texture Parameters + shaderProperties = new[] + { + "_AO_Intensity", + "_AO_Texture", + "_AO_Tiling", + "_AO_Offset", + "_Generate_From_Base_Normals" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + + } + + #endregion + + //Tab 2 + #region OverlayProperties + private void DrawOverlaySettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyleOverlay = makeBackdrop(); + GUILayout.Label("Overlay Texture Properties", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(backdropStyleOverlay); + + MaterialProperty materialPropOverlayTex = FindProperty("_Enable_Overlay_Texture", properties); + materialEditor.ShaderProperty(materialPropOverlayTex, "Enable Overlay Texture"); + if (materialPropOverlayTex.floatValue == 1) + { + string[] shaderProperties = + { + "_Overlay_Texture", + "_Overlay_Tiling", + "_Overlay_Offset", + "_OVERLAY_UV_CHANNEL", + "_Overlay_Intensity" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + EditorGUILayout.EndVertical(); + } + #endregion + + //Tab 3 + #region TriplanarProperties + + bool enableTriplanarBase = true; + bool enableTriplanarNormals = true; + bool enableTriplanarEmission = true; + + private void DrawTriplanarSettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyleTriplanar = makeBackdrop(); + #region Base Triplanar Textures + + EditorGUILayout.BeginVertical(backdropStyleTriplanar); + MaterialProperty materialPropTriplanarBase = FindProperty("_Enable_Triplanar_Texture", properties); + materialEditor.ShaderProperty(materialPropTriplanarBase, "Enable Base Triplanar Textures"); + + if (materialPropTriplanarBase.floatValue == 1) + { + isTriplanarBaseEnabled = true; + enableTriplanarBase = EditorGUILayout.Foldout(enableTriplanarBase, "Triplanar Base Textures"); + if (enableTriplanarBase) + { + // Triplanar Base + string[] shaderProperties = + { + "_Triplanar_Texture_Top", + "_Triplanar_Tiling_Top", + "_Triplanar_Offset_Top", + "_Triplanar_Texture_Bottom", + "_Triplanar_Tiling_Bottom", + "_Triplanar_Offset_Bottom", + "_Triplanar_Texture_Side", + "_Triplanar_Tiling_Side", + "_Triplanar_Offset_Side", + "_Triplanar_Top_To_Side_Difference", + "_Triplanar_Fade", + "_Triplanar_Intensity", + "_Top_Metallic", + "_Side_Metallic", + "_Bottom_Metallic", + "_Top_Smoothness", + "_Side_Smoothness", + "_Bottom_Smoothness" + + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + + } + else + { + isTriplanarBaseEnabled = false; + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + #region Normal Triplanar Textures + EditorGUILayout.BeginVertical(backdropStyleTriplanar); + MaterialProperty materialPropTriplanarNormals = FindProperty("_Enable_Triplanar_Normals", properties); + materialEditor.ShaderProperty(materialPropTriplanarNormals, "Enable Triplanar Normals"); + + if (materialPropTriplanarNormals.floatValue == 1) + { + enableTriplanarNormals = EditorGUILayout.Foldout(enableTriplanarNormals, "Triplanar Normal Textures"); + if (enableTriplanarNormals) + { + // Triplanar Base + string[] shaderProperties = + { + "_Triplanar_Normal_Texture_Top", + "_Triplanar_Normal_Intensity_Top", + "_Triplanar_Normal_Tiling_Top", + "_Triplanar_Normal_Offset_Top", + "_Triplanar_Normal_Texture_Bottom", + "_Triplanar_Normal_Intensity_Bottom", + "_Triplanar_Normal_Tiling_Bottom", + "_Triplanar_Normal_Offset_Bottom", + "_Triplanar_Normal_Texture_Side", + "_Triplanar_Normal_Intensity_Side", + "_Triplanar_Normal_Tiling_Side", + "_Triplanar_Normal_Offset_Side", + "_Triplanar_Normal_Top_To_Side_Difference", + "_Triplanar_Normal_Fade" + + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + } + EditorGUILayout.EndVertical(); + #endregion + EditorGUILayout.Separator(); + #region Emission Triplanar Textures + EditorGUILayout.BeginVertical(backdropStyleTriplanar); + MaterialProperty materialPropTriplanarEmission = FindProperty("_Enable_Triplanar_Emission", properties); + materialEditor.ShaderProperty(materialPropTriplanarEmission, "Enable Triplanar Emission"); + + if (materialPropTriplanarEmission.floatValue == 1) + { + isTriplanarEmissionEnabled = true; + enableTriplanarEmission = EditorGUILayout.Foldout(enableTriplanarEmission, "Triplanar Emission Textures"); + if (enableTriplanarEmission) + { + // Triplanar Base + string[] shaderProperties = + { + "_Triplanar_Emission_Texture", + "_Triplanar_Emission_Tiling", + "_Triplanar_Emission_Blend", + "_Triplanar_Emission_Intensity", + "_Triplanar_Emission_Color_Tint" + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + + } + else + { + isTriplanarEmissionEnabled = false; + } + EditorGUILayout.EndVertical(); + #endregion + + } + #endregion + + //Tab 4 + #region SnowProperties + private void DrawSnowSettings(MaterialEditor materialEditor, MaterialProperty[] properties) + { + GUIStyle backdropStyleSnow = makeBackdrop(); + GUILayout.Label("Snow Properties", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(backdropStyleSnow); + MaterialProperty materialPropSnow = FindProperty("_Enable_Snow", properties); + materialEditor.ShaderProperty(materialPropSnow, "Enable Snow"); + + if (materialPropSnow.floatValue == 1) + { + string[] shaderProperties = + { + "_Snow_Use_World_Up", + "_Snow_Color", + "_Snow_Metallic", + "_Snow_Smoothness", + "_Snow_Level", + "_Snow_Transition" + + }; + + setProperties(materialEditor, properties, shaderProperties, vecGuiProperties); + } + EditorGUILayout.EndVertical(); + } + #endregion + + #region Create Properties + //Gathers list of properties to sort and display in inspector + private static void setProperties(MaterialEditor materialEditor, MaterialProperty[] properties, string[] shaderProperties, Dictionary vecGuiProperties) + { + foreach (string property in shaderProperties) + { + MaterialProperty propertyReference = FindProperty(property, properties); + + if (vecGuiProperties.ContainsKey(property)) + { + string type = vecGuiProperties[property]; + + if (type == "Vector2") + { + Vector2 vec2Value = new Vector2(propertyReference.vectorValue.x, propertyReference.vectorValue.y); + vec2Value = EditorGUILayout.Vector2Field(propertyReference.displayName, vec2Value); + propertyReference.vectorValue = new Vector4(vec2Value.x, vec2Value.y, 0, 0); + } + else if (type == "Vector3") + { + Vector3 vec3Value = new Vector3(propertyReference.vectorValue.x, propertyReference.vectorValue.y, propertyReference.vectorValue.z); + vec3Value = EditorGUILayout.Vector3Field(propertyReference.displayName, vec3Value); + propertyReference.vectorValue = new Vector4(vec3Value.x, vec3Value.y, vec3Value.z, 0); + } + + } + else + { + materialEditor.ShaderProperty(propertyReference, propertyReference.displayName); + } + + + } + } + #endregion + +} diff --git a/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs.meta b/Assets/External/Models/PolygonGeneric/Shaders/InterfaceOverrides/Editor/polygonShader_UI.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_01/Materials/FantasyKnights_01.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_01/Materials/FantasyKnights_01.mat index 575103e6..ab227414 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_01/Materials/FantasyKnights_01.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_01/Materials/FantasyKnights_01.mat @@ -8,16 +8,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_01 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -164,6 +168,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &1358846705396397422 MonoBehaviour: m_ObjectHideFlags: 11 @@ -176,7 +181,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 --- !u!114 &7967226135815873431 MonoBehaviour: m_ObjectHideFlags: 11 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_02/Materials/FantasyKnights_02.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_02/Materials/FantasyKnights_02.mat index eddc5214..c2748556 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_02/Materials/FantasyKnights_02.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_02/Materials/FantasyKnights_02.mat @@ -8,16 +8,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_02 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -164,6 +168,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &7993738256033606102 MonoBehaviour: m_ObjectHideFlags: 11 @@ -189,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_03/Materials/FantasyKnights_03.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_03/Materials/FantasyKnights_03.mat index 4ad7fab3..3e0b9c06 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_03/Materials/FantasyKnights_03.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_03/Materials/FantasyKnights_03.mat @@ -8,16 +8,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_03 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -164,6 +168,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &5122993062315569858 MonoBehaviour: m_ObjectHideFlags: 11 @@ -176,7 +181,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 --- !u!114 &8780454250115516571 MonoBehaviour: m_ObjectHideFlags: 11 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_04/Materials/FantasyKnights_04.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_04/Materials/FantasyKnights_04.mat index 2d486209..6ed6f92a 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_04/Materials/FantasyKnights_04.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_04/Materials/FantasyKnights_04.mat @@ -21,16 +21,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_04 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -177,6 +181,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &6809264838136373543 MonoBehaviour: m_ObjectHideFlags: 11 @@ -189,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_05/Materials/FantasyKnights_05.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_05/Materials/FantasyKnights_05.mat index 28a4d1db..c263c48b 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_05/Materials/FantasyKnights_05.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_05/Materials/FantasyKnights_05.mat @@ -25,7 +25,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 --- !u!21 &2100000 Material: serializedVersion: 8 @@ -34,16 +34,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_05 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -190,3 +194,4 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_06/Materials/FantasyKnights_06.mat b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_06/Materials/FantasyKnights_06.mat index 804c2f3b..5809cea2 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_06/Materials/FantasyKnights_06.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/FantasyKnights/FantasyKnights_06/Materials/FantasyKnights_06.mat @@ -8,16 +8,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: FantasyKnights_06 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -164,6 +168,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &1513622437145775386 MonoBehaviour: m_ObjectHideFlags: 11 @@ -176,7 +181,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 --- !u!114 &5488310361178818670 MonoBehaviour: m_ObjectHideFlags: 11 diff --git a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_01/Materials/HumanSpecies_01.mat b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_01/Materials/HumanSpecies_01.mat index 2873f051..0d9a2d5b 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_01/Materials/HumanSpecies_01.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_01/Materials/HumanSpecies_01.mat @@ -21,16 +21,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: HumanSpecies_01 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -177,6 +181,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &153752790335324610 MonoBehaviour: m_ObjectHideFlags: 11 @@ -189,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_02/Materials/HumanSpecies_02.mat b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_02/Materials/HumanSpecies_02.mat index 887433fb..78b15666 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_02/Materials/HumanSpecies_02.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_02/Materials/HumanSpecies_02.mat @@ -21,16 +21,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: HumanSpecies_02 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -148,6 +152,7 @@ Material: - _DirtAmount: 0.306 - _DstBlend: 0 - _EnvironmentReflections: 1 + - _EyelinerAmount: 0 - _FeminieAmount: 0 - _GlossMapScale: 1 - _Glossiness: 0.5 @@ -176,6 +181,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &1793314631237679544 MonoBehaviour: m_ObjectHideFlags: 11 @@ -188,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_03/Materials/HumanSpecies_03.mat b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_03/Materials/HumanSpecies_03.mat index adf9f33f..455b32ae 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_03/Materials/HumanSpecies_03.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_03/Materials/HumanSpecies_03.mat @@ -21,16 +21,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: HumanSpecies_03 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -177,6 +181,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &7804425326570313428 MonoBehaviour: m_ObjectHideFlags: 11 @@ -189,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_04/Materials/HumanSpecies_04.mat b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_04/Materials/HumanSpecies_04.mat index d02ef0b9..b47a968e 100644 --- a/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_04/Materials/HumanSpecies_04.mat +++ b/Assets/External/Models/SidekickCharacters/Characters/HumanSpecies/HumanSpecies_04/Materials/HumanSpecies_04.mat @@ -21,16 +21,20 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: HumanSpecies_04 - m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: db628544640279b41a4a7aa5d75c0322, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: [] - m_InvalidKeywords: [] + m_InvalidKeywords: + - _EMISSION m_LightmapFlags: 2 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: -1 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -177,6 +181,7 @@ Material: - _Grey: {r: 0.59748423, g: 0.59748423, b: 0.59748423, a: 0} - _SkinColor: {r: 0, g: 0, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &6958986610217973014 MonoBehaviour: m_ObjectHideFlags: 11 @@ -189,4 +194,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 10 diff --git a/Assets/External/Models/SidekickCharacters/Database/Side_Kick_Data.db.meta b/Assets/External/Models/SidekickCharacters/Database/Side_Kick_Data.db.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs b/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs old mode 100644 new mode 100755 index aafe675e..9daa3e6a --- a/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs +++ b/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs @@ -1,29 +1,29 @@ -using System.Resources; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SQLite-net Official Portable Library")] -[assembly: AssemblyDescription("Light weight library providing easy SQLite database storage")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Krueger Systems, Inc.")] -[assembly: AssemblyProduct("SQLite-net")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Resources; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SQLite-net Official Portable Library")] +[assembly: AssemblyDescription("Light weight library providing easy SQLite database storage")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Krueger Systems, Inc.")] +[assembly: AssemblyProduct("SQLite-net")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs.meta b/Assets/External/Models/SidekickCharacters/Plugins/unity-sqlite-net-1.2.4/Runtime/sqlite-net/AssemblyInfo.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Resources/Materials/M_BaseMaterial.mat.meta b/Assets/External/Models/SidekickCharacters/Resources/Materials/M_BaseMaterial.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Resources/Materials/M_PresetColor.mat.meta b/Assets/External/Models/SidekickCharacters/Resources/Materials/M_PresetColor.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs b/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs old mode 100644 new mode 100755 index 41785c2a..d4a9018b --- a/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs @@ -1,5015 +1,5008 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -#if UNITY_EDITOR - -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using Synty.SidekickCharacters.Filters; -using Synty.SidekickCharacters.Serialization; -using Synty.SidekickCharacters.SkinnedMesh; -using Synty.SidekickCharacters.Synty.SidekickCharacters.Scripts.Editor.UI; -using Synty.SidekickCharacters.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Unity.VisualScripting.YamlDotNet.Serialization; -using UnityEditor; -using UnityEditor.Animations; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.UIElements; -using Debug = UnityEngine.Debug; -using Object = UnityEngine.Object; -using Random = UnityEngine.Random; - -namespace Synty.SidekickCharacters -{ - public class ModularCharacterWindow : EditorWindow - { - private const string _AUTOSAVE_KEY = "SK_Autosave_character"; - private const string _AUTOSAVE_MISSING_PARTS = "SK_Autosave_missing_parts"; - private const string _AUTOSAVE_STATE = "SK_Autosave_state"; - private const string _BASE_COLOR_SET_NAME = "Species"; - private const string _BASE_COLOR_SET_PATH = "Assets/External/Models/SidekickCharacters/Resources/Species"; - private const string _BASE_MESH_NAME = "Meshes/SK_BaseModel"; - private const string _BASE_MATERIAL_NAME = "Materials/M_BaseMaterial"; - private const string _BLEND_GENDER_NAME = "masculineFeminine"; - private const string _BLEND_MUSCLE_NAME = "defaultBuff"; - private const string _BLEND_SHAPE_HEAVY_NAME = "defaultHeavy"; - private const string _BLEND_SHAPE_SKINNY_NAME = "defaultSkinny"; - private const string _AUTO_OPEN_STATE = "syntySkAutoOpenState"; - private const string _OUTPUT_MODEL_NAME = "Combined Character"; - private const string _PART_COUNT_BODY = " parts in library"; - private const string _TEXTURE_COLOR_NAME = "ColorMap.png"; - private const string _TEXTURE_METALLIC_NAME = "MetallicMap.png"; - private const string _TEXTURE_SMOOTHNESS_NAME = "SmoothnessMap.png"; - private const string _TEXTURE_REFLECTION_NAME = "ReflectionMap.png"; - private const string _TEXTURE_EMISSION_NAME = "EmissionMap.png"; - private const string _TEXTURE_OPACITY_NAME = "OpacityMap.png"; - private const string _TEXTURE_PREFIX = "T_"; - - private static readonly int _COLOR_MAP = Shader.PropertyToID("_ColorMap"); - private static readonly int _METALLIC_MAP = Shader.PropertyToID("_MetallicMap"); - private static readonly int _SMOOTHNESS_MAP = Shader.PropertyToID("_SmoothnessMap"); - private static readonly int _REFLECTION_MAP = Shader.PropertyToID("_ReflectionMap"); - private static readonly int _EMISSION_MAP = Shader.PropertyToID("_EmissionMap"); - private static readonly int _OPACITY_MAP = Shader.PropertyToID("_OpacityMap"); - private static Queue _callbackQueue = new Queue(); - private static bool _openWindowOnStart = true; - private readonly List _visibleColorRows = new List(); - - private List _allColorRows = new List(); - private List _allParts; - private List _allSpecies; - private ObjectField _animationField; - private FilterGroup _appliedPartFilters; - private bool _applyingPreset = false; - private List _availablePartList; - List _availablePresets; - private bool _bakeBlends = true; - private ObjectField _baseModelField; - private Dictionary _blendShapeRigMovement = new Dictionary(); - private Dictionary _blendShapeRigRotation = new Dictionary(); - private ToolbarToggle _bodyPartsTab; - private ToolbarToggle _bodyPresetTab; - private ToolbarToggle _bodyShapeTab; - private ScrollView _bodyShapeView; - private float _bodySizeHeavyBlendValue; - private float _bodySizeSkinnyBlendValue; - private Slider _bodySizeSlider; - private Slider _bodyTypeSlider; - private VisualElement _colorSelectionRowView; - private ToolbarToggle _colorSelectionTab; - private ScrollView _colorSelectionView; - private DropdownField _colorSetsDropdown; - private bool _combineMeshes = true; - private AnimatorController _currentAnimationController; - private Dictionary _currentBodyPresetDictionary = new Dictionary(); - private Dictionary _currentCharacter = new Dictionary(); - private Dictionary _currentColorSpeciesPresetDictionary = new Dictionary(); - private Dictionary _currentColorOutfitsPresetDictionary = new Dictionary(); - private Dictionary _currentColorAttachmentsPresetDictionary = new Dictionary(); - private Dictionary _currentColorMaterialsPresetDictionary = new Dictionary(); - private Dictionary _currentColorElementsPresetDictionary = new Dictionary(); - private SidekickColorSet _currentColorSet; - private bool _currentGlobalLockStatus; - private Material _currentMaterial; - private Dictionary _previousPartSelections; - private ColorPartType _currentPartType; - private Dictionary _currentHeadPresetDictionary = new Dictionary(); - private Dictionary _currentUpperBodyPresetDictionary = new Dictionary(); - private Dictionary _currentLowerBodyPresetDictionary = new Dictionary(); - private SidekickSpecies _currentSpecies; - private TabView _currentTab; - private Dictionary> _currentUVDictionary = new Dictionary>(); - private List _currentUVList = new List(); - private DatabaseManager _dbManager; - private string _dbPath; - private ToolbarToggle _decalSelectionTab; - private ScrollView _decalSelectionView; - private StyleSheet _editorStyle; - private bool _showAllColourProperties = false; - private float _bodyTypeBlendValue; - private bool _loadingCharacter = false; - private bool _loadingContent = false; - private Image _loadingImage; - private ObjectField _materialField; - private float _musclesBlendValue; - private Slider _musclesSlider; - private GameObject _newModel; - private VisualElement _newSetNameContainer; - private ScrollView _optionSelectionView; - private ToolbarToggle _optionTab; - private Label _partCountLabel; - private Dictionary _partDictionary; - private Dictionary> _partLibrary; - private Dictionary> _allPartsLibrary; - private Dictionary> _partOutfitMap; - private Dictionary, bool> _partLockMap; - private Dictionary _partSelectionDictionary; - private Foldout _partsFoldout; - private Dictionary> _partSpeciesMap; - private Dictionary _partPresetFilterToggleMap = new Dictionary(); - private ScrollView _partView; - private Dictionary _presetDefaultValues = new Dictionary(); - private VisualElement _presetPartContainer; - private ScrollView _presetView; - private Toggle _previewToggle; - private bool _processingSpeciesChange = false; - private bool _requiresWrap = false; - private VisualElement _root; - private bool _showMissingPartsPopup = false; - private SidekickRuntime _sidekickRuntime; - private DropdownField _speciesField; - private DropdownField _speciesPresetField; - private PlayModeStateChange _stateChange; - private bool _useAutoSaveAndLoad = false; - private List _visibleColorSets = new List(); - - // Animation variables - private Animator _currentAnimator; - private string _defaultStateName = "Idle"; - private float _defaultClipDurationFallback = 2f; - private float _blendDuration = 0.5f; // seconds - private List _otherStates = new List(); - private string _currentState; - private float _playbackTime; - private float _stateDuration = 1f; - private int _loopsRemaining = 0; - private bool _playingDefault = true; - private double _lastEditorTime; - private Transform[] _animatorBones; - private Dictionary _previousPosePos = new Dictionary(); - private Dictionary _previousPoseRot = new Dictionary(); - private float _blendElapsedTime = 0f; - private bool _blending = false; - - /// - private void Awake() - { - InitializeEditorWindow(); - } - - /// - private void OnDestroy() - { - if (_useAutoSaveAndLoad) - { - SerializedCharacter savedCharacter = CreateSerializedCharacter(_OUTPUT_MODEL_NAME); - Serializer serializer = new Serializer(); - string serializedCharacter = serializer.Serialize(savedCharacter); - EditorPrefs.SetString(_AUTOSAVE_KEY, serializedCharacter); - } - - // ensures we release the file lock on the database - _dbManager?.CloseConnection(); - } - -#if UNITY_EDITOR - /// - private void OnEnable() - { - EditorApplication.playModeStateChanged += StateChange; - EditorApplication.update += AnimationUpdate; - } - - private void OnDisable() - { - EditorApplication.update -= AnimationUpdate; - } - - /// - private void Update() - { - if (_loadingContent && _loadingImage != null) - { - Vector3 rotation = _loadingImage.transform.rotation.eulerAngles; - rotation += new Vector3(0, 0, 0.5f * Time.deltaTime); - _loadingImage.transform.rotation = Quaternion.Euler(rotation); - } - - while (_callbackQueue.Count > 0) - { - Action action = null; - lock (_callbackQueue) - { - if (_callbackQueue.Count > 0) - { - action = _callbackQueue.Dequeue(); - } - } - action?.Invoke(); - } - } - - /// - /// Sets up the animation controllers for playing during runtime. - /// - /// True if it is set up; otherwise false. - private bool SetupAnimationControllers() - { - _loopsRemaining = 0; - - _currentAnimator = _newModel.GetComponent(); - if (_currentAnimator != null) - { - _currentAnimationController = _currentAnimator.runtimeAnimatorController as AnimatorController; - _sidekickRuntime.CurrentAnimationController = _currentAnimationController; - } - else - { - return false; - } - - _animatorBones = _currentAnimator.GetComponentsInChildren(); - CollectOtherStates(); - - if (string.IsNullOrEmpty(_currentState)) - { - StartDefaultState(); - } - else - { - SetState(_currentState); - } - - _lastEditorTime = EditorApplication.timeSinceStartup; - return true; - } - - /// - /// Plays the animation during edit time. - /// - private void AnimationUpdate() - { - if (Application.isPlaying) - { - return; - } - - if (_animationField == null || _animationField.value == null) - { - return; - } - - if (_currentAnimator == null || _currentAnimationController == null) - { - if (!SetupAnimationControllers()) - { - return; - } - } - - double currentTime = EditorApplication.timeSinceStartup; - float deltaTime = (float)(currentTime - _lastEditorTime); - _lastEditorTime = currentTime; - - _playbackTime += deltaTime; - float normalizedTime = (_playbackTime % _stateDuration) / _stateDuration; - - _currentAnimator.Play(_currentState, 0, normalizedTime); - _currentAnimator.Update(0f); - - // Blend from previous pose (if blending) - if (_blending) - { - _blendElapsedTime += deltaTime; - float t = Mathf.Clamp01(_blendElapsedTime / _blendDuration); - - foreach (var bone in _animatorBones) - { - if (bone == null) - { - continue; - } - - if (_previousPosePos.TryGetValue(bone, out Vector3 prevPos)) - { - bone.localPosition = Vector3.Lerp(prevPos, bone.localPosition, t); - } - - if (_previousPoseRot.TryGetValue(bone, out Quaternion prevRot)) - { - bone.localRotation = Quaternion.Slerp(prevRot, bone.localRotation, t); - } - } - - if (t >= +_blendDuration) - { - _blending = false; - } - } - - SceneView.RepaintAll(); - - if (_playbackTime >= _stateDuration) - { - _playbackTime = 0f; - _loopsRemaining--; - - if (_loopsRemaining <= 0) - { - if (!_playingDefault) - { - StartDefaultState(); - } - else - { - _loopsRemaining = Int32.MaxValue; - } - } - } - } - - /// - /// Collect other states from the animation contoller. - /// - private void CollectOtherStates() - { - _otherStates.Clear(); - if (_currentAnimationController == null) - { - return; - } - - foreach (var layer in _currentAnimationController.layers) - { - foreach (var state in layer.stateMachine.states) - { - string stateName = state.state.name; - if (stateName != _defaultStateName) - { - _otherStates.Add(stateName); - } - } - } - } - - /// - /// - /// - private void StartDefaultState() - { - SetState(_defaultStateName); - } - - /// - /// Sets the state of the animation controller. - /// - /// The name of the state to set. - private void SetState(string stateName) - { - if (_currentAnimationController == null || _currentAnimator == null) - { - return; - } - - CacheCurrentPose(); - - _currentState = stateName; - _playbackTime = 0f; - _blendElapsedTime = 0f; - _blending = true; - _loopsRemaining = stateName == _defaultStateName ? Int32.MaxValue : 1; - _playingDefault = stateName == _defaultStateName; - - var sm = _currentAnimationController.layers[0].stateMachine; - foreach (var state in sm.states) - { - if (state.state.name == stateName && state.state.motion is AnimationClip clip) - { - _stateDuration = Mathf.Max(clip.length, 0.01f); - goto Found; - } - } - - _stateDuration = _defaultClipDurationFallback; - - Found: - _currentAnimator.Play(stateName, 0, 0f); - _currentAnimator.Update(0f); - } - - /// - /// Caches the current animation pose - /// - private void CacheCurrentPose() - { - _previousPosePos.Clear(); - _previousPoseRot.Clear(); - - foreach (var bone in _animatorBones) - { - if (bone == null) continue; - _previousPosePos[bone] = bone.localPosition; - _previousPoseRot[bone] = bone.localRotation; - } - } - - /// - /// Processes the callback from the play mode state change. - /// - /// The current PlayModeStateChange - private void StateChange(PlayModeStateChange stateChange) - { - if (_useAutoSaveAndLoad && stateChange == PlayModeStateChange.ExitingEditMode || _useAutoSaveAndLoad && stateChange == PlayModeStateChange.ExitingPlayMode) - { - SerializedCharacter savedCharacter = CreateSerializedCharacter(_OUTPUT_MODEL_NAME); - Serializer serializer = new Serializer(); - string serializedCharacter = serializer.Serialize(savedCharacter); - EditorPrefs.SetString(_AUTOSAVE_KEY, serializedCharacter); - } - - if (_useAutoSaveAndLoad && stateChange == PlayModeStateChange.EnteredEditMode || _useAutoSaveAndLoad && stateChange == PlayModeStateChange.EnteredPlayMode) - { - _stateChange = stateChange; - } - } -#endif - - /// - public async void CreateGUI() - { - _loadingContent = true; - InitializeEditorWindow(); - _root = rootVisualElement; - _root.Clear(); - if (_editorStyle != null) - { - _root.styleSheets.Add(_editorStyle); - } - - InitializeDatabase(); - // if we still can't connect, something's gone wrong, don't keep building the GUI - if (_dbManager?.GetCurrentDbConnection() == null) - { - _loadingContent = false; - return; - } - - // Maintains a linking to the model if the editor window is closed and re-opened. - _newModel = GameObject.Find(_OUTPUT_MODEL_NAME); - - _previousPartSelections = new Dictionary(); - foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) - { - _previousPartSelections.Add(type, "None"); - } - - _partCountLabel = new Label("") - { - style = - { - unityTextAlign = TextAnchor.MiddleLeft - } - }; - - Image bannerImage = new Image - { - image = (Texture2D) Resources.Load("UI/T_SidekickTitle"), - scaleMode = ScaleMode.ScaleToFit, - }; - VisualElement bannerLayout = new VisualElement - { - style = - { - backgroundColor = new Color(209f/256, 34f/256, 51f/256), - minHeight = 150, - paddingBottom = 5, - paddingTop = 5, - } - }; - bannerLayout.Add(bannerImage); - _root.Add(bannerLayout); - - _presetView = new ScrollView(ScrollViewMode.Vertical); - _partView = new ScrollView(ScrollViewMode.Vertical) - { - style = - { - display = DisplayStyle.None - } - }; - _bodyShapeView = new ScrollView(ScrollViewMode.Vertical) - { - style = - { - display = DisplayStyle.None - } - }; - - _colorSelectionView = new ScrollView(ScrollViewMode.Vertical) - { - style = - { - display = DisplayStyle.None - } - }; - - // TODO: Uncomment when Decals added to the system. - // _decalSelectionView = new ScrollView(ScrollViewMode.Vertical) - // { - // style = - // { - // display = DisplayStyle.None - // } - // }; - - _optionSelectionView = new ScrollView(ScrollViewMode.Vertical) - { - style = - { - display = DisplayStyle.None - } - }; - - // TODO: Replace this tabbed menu code with TabView when 2023 LTS in the minimum supported version. - Toolbar tabBar = new Toolbar - { - style = - { - width = Length.Percent(100) - } - }; - - _bodyPresetTab = new ToolbarToggle - { - text = "Presets", - tooltip = "Create a character using preset combinations of parts, body types and colors" - }; - - _bodyPartsTab = new ToolbarToggle - { - text = "Parts", - tooltip = "Edit individual character parts on your character" - }; - - _bodyShapeTab = new ToolbarToggle - { - text = "Body", - tooltip = "Edit the body type, size, musculature of your character" - }; - - _colorSelectionTab = new ToolbarToggle - { - text = "Colors", - tooltip = "Edit individual colors of your character" - }; - - // TODO: Uncomment when Decals added to the system. - // _decalSelectionTab = new ToolbarToggle - // { - // text = "Decals", - // tooltip = "Edit the decals applied to your character" - // }; - - _optionTab = new ToolbarToggle - { - text = "Options", - tooltip = "Change the options of the tool" - }; - - tabBar.Add(_bodyPresetTab); - tabBar.Add(_bodyPartsTab); - tabBar.Add(_bodyShapeTab); - tabBar.Add(_colorSelectionTab); - // TODO: Uncomment when Decals added to the system. - // tabBar.Add(_decalSelectionTab); - tabBar.Add(_optionTab); - _root.Add(tabBar); - - _bodyPresetTab.RegisterValueChangedCallback( - delegate - { - if (_currentTab != TabView.Preset && _bodyPresetTab.value) - { - SwitchToTab(TabView.Preset); - } - } - ); - - _bodyPartsTab.RegisterValueChangedCallback( - delegate - { - if (_currentTab != TabView.Parts && _bodyPartsTab.value) - { - SwitchToTab(TabView.Parts); - } - } - ); - - _bodyShapeTab.RegisterValueChangedCallback( - delegate - { - if (_currentTab != TabView.Body && _bodyShapeTab.value) - { - AddBodyShapeTabContent(_bodyShapeView); - SwitchToTab(TabView.Body); - } - } - ); - - _colorSelectionTab.RegisterValueChangedCallback( - delegate - { - if (_currentTab != TabView.Colors && _colorSelectionTab.value) - { - // always re-populate the color rows with the latest when switching tabs - if (_allColorRows.Count == 0) - { - PopulateColorRowsFromTextures(); - } - else - { - PopulatePartColorRows(); - RefreshVisibleColorRows(); - } - - SwitchToTab(TabView.Colors); - } - } - ); - - // TODO: Uncomment when Decals added to the system. - // _decalSelectionTab.RegisterValueChangedCallback( - // delegate - // { - // if (_currentTab != TabView.Decals && _decalSelectionTab.value) - // { - // SwitchToTab(TabView.Decals); - // } - // } - // ); - - _optionTab.RegisterValueChangedCallback( - delegate - { - if (_currentTab != TabView.Options && _optionTab.value) - { - SwitchToTab(TabView.Options); - } - // If currently on this tab, and button is toggled to "off", toggle back to "on" - else if (_currentTab == TabView.Options && !_optionTab.value) - { - _optionTab.value = true; - } - } - ); - - _root.Add(_presetView); - _root.Add(_partView); - _root.Add(_bodyShapeView); - _root.Add(_colorSelectionView); - // TODO: Uncomment when Decals added to the system. - // root.Add(_decalSelectionView); - _root.Add(_optionSelectionView); - - AddOptionsTabContent(_optionSelectionView); - - // set the default colour set (this will change on various input triggers, but we need it to not be null) - _currentColorSet = SidekickColorSet.GetDefault(_dbManager); - - _partDictionary = new Dictionary(); - _currentCharacter = new Dictionary(); - - _sidekickRuntime = new SidekickRuntime((GameObject) _baseModelField.value, (Material) _materialField.value, _currentAnimationController, _dbManager); - - Label loadingLabel = new Label - { - text = "Loading Content..", - style = - { - fontSize = 20, - unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), - marginTop = 20 - } - }; - - _presetView.Add(loadingLabel); - - _loadingImage = new Image - { - image = (Texture2D) Resources.Load("UI/T_LoadingCircle"), - scaleMode = ScaleMode.ScaleToFit, - style = - { - width = 28, - height = 28, - unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), - alignContent = new StyleEnum(Align.Center), - alignSelf = new StyleEnum(Align.Center) - } - }; - - _presetView.Add(_loadingImage); - - _bodyPresetTab.value = true; - SwitchToTab(TabView.Preset); - - VisualElement saveLoadButtons = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - width = Length.Percent(100), - alignContent = new StyleEnum(Align.FlexStart), - alignItems = new StyleEnum(Align.FlexStart), - flexWrap = new StyleEnum(Wrap.Wrap), - justifyContent = new StyleEnum(Justify.SpaceBetween), - minHeight = 30, - marginTop = 20 - } - }; - - _root.Add(saveLoadButtons); - - Button loadCharacterButton = new Button(LoadCharacter) - { - text = "Load Character", - style = - { - minHeight = 30, - width = Length.Percent(48) - } - }; - saveLoadButtons.Add(loadCharacterButton); - - Button saveCharacterButton = new Button(SaveCharacter) - { - text = "Save Character", - style = - { - minHeight = 30, - width = Length.Percent(48) - } - }; - - saveLoadButtons.Add(saveCharacterButton); - - Button createCharacterButton = new Button(CreateCharacterPrefab) - { - text = "Export Character as Prefab", - style = - { - minHeight = 50, - marginTop = 5 - } - }; - _root.Add(createCharacterButton); - - // Populate the data in an async process, if not already populated - try - { - await Task.Run( - async () => - { - await SidekickRuntime.PopulateToolData(_sidekickRuntime); - _callbackQueue.Enqueue(AddAllTabContent); - if (_useAutoSaveAndLoad && _stateChange == PlayModeStateChange.EnteredEditMode - || _useAutoSaveAndLoad && _stateChange == PlayModeStateChange.EnteredPlayMode) - { - _callbackQueue.Enqueue(ReloadCharacterFromStateChange); - } - } - ); - } - catch - { - Debug.LogWarning("Failed to load tool data. Please try again.\nPlease note that data loading may take some time."); - } - } - - /// - /// Reloads the character based on auto saved character - /// - private void ReloadCharacterFromStateChange() - { - if (_stateChange == PlayModeStateChange.EnteredEditMode) - { - GameObject existingModel = GameObject.Find(_OUTPUT_MODEL_NAME); - while (existingModel != null) - { - GameObject.DestroyImmediate(existingModel); - existingModel = GameObject.Find(_OUTPUT_MODEL_NAME); - } - } - - string serializedCharacterString = EditorPrefs.GetString(_AUTOSAVE_KEY, null); - - if (!string.IsNullOrEmpty(serializedCharacterString)) - { - Deserializer deserializer = new Deserializer(); - SerializedCharacter serializedCharacter = deserializer.Deserialize(serializedCharacterString); - LoadSerializedCharacter(serializedCharacter, _showAllColourProperties); - } - - _stateChange = PlayModeStateChange.ExitingEditMode; - } - - /// - /// Adds the UI content to all tabs (excluding Options tab as it is already populated) - /// - private void AddAllTabContent() - { - if (_sidekickRuntime.PartCount < 15) - { - if (EditorUtility.DisplayDialog( - "Unable to strat Sidekicks Tool", - "There are not enough Sidekicks parts currently in your project. The tool is unable to start without the requisite parts", - "Ok" - )) - { - Close(); - } - - } - else { - _allPartsLibrary = _sidekickRuntime.AllPartsLibrary; - _allParts = SidekickPart.GetAll(_dbManager); - - _allSpecies = SidekickSpecies.GetAll(_dbManager); - _currentSpecies = _allSpecies[0]; - _sidekickRuntime.CurrentSpecies = _currentSpecies; - - _partCountLabel.text = _sidekickRuntime.PartCount + _PART_COUNT_BODY; - _partOutfitMap = _sidekickRuntime.PartOutfitMap; - - AddBodyShapeTabContent(_bodyShapeView); - AddColorTabContent(_colorSelectionView); - // TODO: Uncomment when Decals added to the system. - // _decalSelectionView.Add(new Label("Decal selections will go here.")); - - UpdatePartUVData(); - - PopulatePartUI(); - PopulatePresetUI(); - - if (_currentSpecies == null) - { - _currentSpecies = _currentSpecies = _allSpecies.FirstOrDefault(species => species.Name == _speciesField.value); - } - - if (_useAutoSaveAndLoad) - { - string serializedCharacterString = EditorPrefs.GetString(_AUTOSAVE_KEY, null); - - if (!string.IsNullOrEmpty(serializedCharacterString)) - { - try - { - Deserializer deserializer = new Deserializer(); - SerializedCharacter serializedCharacter = deserializer.Deserialize(serializedCharacterString); - LoadSerializedCharacter(serializedCharacter, _showAllColourProperties); - } - catch (Exception ex) - { - EditorUtility.DisplayDialog( - "Something Went Wrong", - "Unable to load saved character.", - "OK" - ); - Debug.LogWarning(ex); - _useAutoSaveAndLoad = false; - EditorPrefs.SetBool(_AUTOSAVE_STATE, _useAutoSaveAndLoad); - } - } - } - _loadingContent = false; - - } - } - - /// - /// Initializes all the database setup, and provides the status label reference for users - /// - private void InitializeDatabase() - { - // TODO: always reinstantiate instead? - if (_dbManager != null) - { - return; - } - - _dbManager = new DatabaseManager(); - _dbManager.GetDbConnection(true); - } - - /// - /// Initializes the editor window. - /// - private void InitializeEditorWindow() - { - _editorStyle = Resources.Load("Styles/EditorStyles"); - _openWindowOnStart = EditorPrefs.GetBool(_AUTO_OPEN_STATE, true); - _useAutoSaveAndLoad = EditorPrefs.GetBool(_AUTOSAVE_STATE, false); - _showMissingPartsPopup = EditorPrefs.GetBool(_AUTOSAVE_MISSING_PARTS, false); - } - - /// - /// Adds the contents and change listeners for the body shape tab. - /// - /// The tabview to add the content to. - private void AddBodyShapeTabContent(ScrollView view) - { - view.Clear(); - - _bodyTypeSlider = new Slider("Body Type", -100, 100) - { - value = _bodyTypeBlendValue, - style = - { - maxWidth = new StyleLength(StyleKeyword.Auto) - }, - showInputField = true, - tooltip = "Blend the body type of the character between masculine and feminine" - }; - - VisualElement bodyTypeLabels = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - width = Length.Percent(100), - paddingLeft = 155 - } - }; - - Label labelMasculine = new Label("Masculine") - { - style = - { - position = new StyleEnum(Position.Absolute), - left = 155 - } - }; - bodyTypeLabels.Add(labelMasculine); - - Label labelFeminine = new Label("Feminine") - { - style = - { - position = new StyleEnum(Position.Absolute), - right = 58 - } - }; - bodyTypeLabels.Add(labelFeminine); - - _bodySizeSlider = new Slider("Body Size", -100, 100) - { - value = _bodySizeSkinnyBlendValue > 0 ? -_bodySizeSkinnyBlendValue : _bodySizeHeavyBlendValue, - style = - { - maxWidth = new StyleLength(StyleKeyword.Auto), - marginTop = 30 - }, - showInputField = true, - tooltip = "Blend the body size of the character between slim and heavy" - }; - - VisualElement bodySizeLabels = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - width = Length.Percent(100), - paddingLeft = 155 - } - }; - - Label labelSlim = new Label("Slim") - { - style = - { - position = new StyleEnum(Position.Absolute), - left = 155 - } - }; - bodySizeLabels.Add(labelSlim); - - Label labelHeavy = new Label("Heavy") - { - style = - { - position = new StyleEnum(Position.Absolute), - right = 58 - } - }; - bodySizeLabels.Add(labelHeavy); - - _musclesSlider = new Slider("Musculature", -100, 100) - { - value = _musclesBlendValue, - style = - { - maxWidth = new StyleLength(StyleKeyword.Auto), - marginTop = 30 - }, - showInputField = true, - tooltip = "Blend the musculature of the character between lean and muscular" - }; - - VisualElement muscleLabels = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - width = Length.Percent(100), - height = 20, - paddingLeft = 155 - } - }; - - Label labelLean = new Label("Lean") - { - style = - { - position = new StyleEnum(Position.Absolute), - left = 155 - } - }; - muscleLabels.Add(labelLean); - - Label labelBulk = new Label("Muscular") - { - style = - { - position = new StyleEnum(Position.Absolute), - right = 58 - } - }; - muscleLabels.Add(labelBulk); - - view.Add(_bodyTypeSlider); - view.Add(bodyTypeLabels); - view.Add(_bodySizeSlider); - view.Add(bodySizeLabels); - view.Add(_musclesSlider); - view.Add(muscleLabels); - - _bodyTypeSlider.RegisterValueChangedCallback( - evt => - { - _bodyTypeBlendValue = evt.newValue; - _sidekickRuntime.BodyTypeBlendValue = evt.newValue; - - string body = "None"; - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Torso, out PartTypeControls bodySelection)) - { - body = bodySelection.PartDropdown.value; - } - - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) - { - if (body != "None" && _requiresWrap && _bodyTypeBlendValue > 0) - { - wrapSelection.PartDropdown.SetEnabled(true); - wrapSelection.RandomisePartDropdownValue(); - } - else - { - wrapSelection.PartDropdown.SetEnabled(false); - wrapSelection.SetPartDropdownValue(null); - _currentCharacter.Remove(CharacterPartType.Wrap); - } - } - - if (_newModel == null) - { - _newModel = GenerateCharacter(false, true); - UpdatePartUVData(); - } - - _sidekickRuntime.UpdateBlendShapes(_newModel); - _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); - _sidekickRuntime.ProcessBoneMovement(_newModel); - } - ); - - _bodySizeSlider.RegisterValueChangedCallback( - evt => - { - float newValue = evt.newValue; - if (newValue > 0) - { - _bodySizeHeavyBlendValue = newValue; - _bodySizeSkinnyBlendValue = 0; - _sidekickRuntime.BodySizeHeavyBlendValue = newValue; - _sidekickRuntime.BodySizeSkinnyBlendValue = 0; - } - else if (newValue < 0) - { - _bodySizeHeavyBlendValue = 0; - _bodySizeSkinnyBlendValue = -newValue; - _sidekickRuntime.BodySizeHeavyBlendValue = 0; - _sidekickRuntime.BodySizeSkinnyBlendValue = -newValue; - } - else - { - _bodySizeHeavyBlendValue = 0; - _bodySizeSkinnyBlendValue = 0; - _sidekickRuntime.BodySizeHeavyBlendValue = 0; - _sidekickRuntime.BodySizeSkinnyBlendValue = 0; - } - - if (_newModel == null) - { - _newModel = GenerateCharacter(false, true); - UpdatePartUVData(); - } - - _sidekickRuntime.UpdateBlendShapes(_newModel); - _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); - _sidekickRuntime.ProcessBoneMovement(_newModel); - } - ); - - _musclesSlider.RegisterValueChangedCallback( - evt => - { - _musclesBlendValue = evt.newValue; - _sidekickRuntime.MusclesBlendValue = evt.newValue; - - if (_newModel == null) - { - _newModel = GenerateCharacter(false, true); - UpdatePartUVData(); - } - - _sidekickRuntime.UpdateBlendShapes(_newModel); - _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); - _sidekickRuntime.ProcessBoneMovement(_newModel); - } - ); - } - - /// - /// Adds the content to the Color tab. - /// - /// The view to add the content to. - private void AddColorTabContent(ScrollView view) - { - _colorSetsDropdown = new DropdownField - { - style = - { - maxWidth = Length.Percent(65) - } - }; - - Label filterPartsLabel = new Label("Filter - Parts") - { - tooltip = "Filter the displayed colors to focus on specific areas of the character and reduce the number of properties" - }; - view.Add(filterPartsLabel); - DropdownField partTypeDropdown = new DropdownField(); - string[] colorPartTypes = Enum.GetNames(typeof(ColorPartType)); - // Enum names can't have spaces so we add in the space manually for display. - for (int i = 0; i < colorPartTypes.Length; i++) - { - colorPartTypes[i] = StringUtils.AddSpacesBeforeCapitalLetters(colorPartTypes[i]); - } - - partTypeDropdown.choices = colorPartTypes.ToList(); - partTypeDropdown.value = colorPartTypes[0]; - view.Add(partTypeDropdown); - - partTypeDropdown.RegisterValueChangedCallback( - (evt) => - { - if (Enum.TryParse(typeof(ColorPartType), evt.newValue.Replace(" ", ""), out object newType)) - { - _currentPartType = (ColorPartType) newType; - _colorSetsDropdown.value = "Custom"; - } - - PopulatePartColorRows(); - RefreshVisibleColorRows(); - } - ); - - _currentPartType = ColorPartType.AllParts; - - // TODO: Hidden due to early access, enable when feature complete - // Label colorSetsLabel = new Label("Color Sets"); - // view.Add(colorSetsLabel); - // - // VisualElement colorSetsRow = new VisualElement - // { - // style = - // { - // flexDirection = new StyleEnum(FlexDirection.Row), - // width = Length.Percent(100), - // alignContent = new StyleEnum(Align.FlexStart), - // alignItems = new StyleEnum(Align.FlexStart), - // flexWrap = new StyleEnum(Wrap.Wrap), - // justifyContent = new StyleEnum(Justify.SpaceBetween), - // marginBottom = 10 - // } - // }; - - UpdateVisibleColorSets(); - - // TODO: Hidden due to early access, enable when feature complete - // colorSetsRow.Add(_colorSetsDropdown); - // - // _colorSetsDropdown.RegisterValueChangedCallback( - // evt => - // { - // if (evt.newValue != "Custom") - // { - // SidekickColorSet newSet = _visibleColorSets.First(set => set.Name == evt.newValue); - // List newRows = SidekickColorRow.GetAllBySet(_dbManager, newSet); - // if (_currentPartType == ColorPartType.AllParts && _allColorRows.All(row => row.IsLocked == false)) - // { - // _currentColorSet = newSet; - // _allColorRows = newRows; - // if (_allColorRows.Count == 0) - // { - // PopulateColorRowsFromTextures(); - // } - // else - // { - // PopulatePartColorRows(); - // RefreshVisibleColorRows(); - // } - // } - // else - // { - // foreach (SidekickColorRow row in _visibleColorRows) - // { - // SidekickColorRow newRow = newRows.FirstOrDefault(r => r.ColorProperty.ID == row.ColorProperty.ID); - // if (newRow != null) - // { - // row.NiceColor = newRow.NiceColor; - // row.NiceMetallic = newRow.NiceMetallic; - // row.NiceSmoothness = newRow.NiceSmoothness; - // row.NiceReflection = newRow.NiceReflection; - // row.NiceEmission = newRow.NiceEmission; - // row.NiceOpacity = newRow.NiceOpacity; - // } - // } - // - // RefreshVisibleColorRows(); - // } - // - // UpdateAllVisibleColors(); - // } - // } - // ); - // - // Button previousSetButton = new Button( - // () => - // { - // if (_colorSetsDropdown.index > 0) - // { - // _colorSetsDropdown.index -= 1; - // } - // } - // ) - // { - // tooltip = "Previous Color Set" - // }; - // - // previousSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("tab_prev", "|Previous Color Set").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(previousSetButton); - // Button nextSetButton = new Button( - // () => - // { - // if (_colorSetsDropdown.index < _colorSetsDropdown.choices.Count - 1) - // { - // _colorSetsDropdown.index += 1; - // } - // } - // ) - // { - // tooltip = "Next Color Set" - // }; - // - // nextSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("tab_next", "|Next Color Set").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(nextSetButton); - // Button resetSetButton = new Button(ResetColorSet) - // { - // tooltip = "Reset Color Set from Disk" - // }; - // resetSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("Refresh", "|Reset Color Set From Disk").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(resetSetButton); - // Button newSetButton = new Button(ShowCreateNewColorSet) - // { - // tooltip = "Create New Color Set" - // }; - // newSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("Toolbar Plus", "|Create New Color Set").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(newSetButton); - // Button deleteSetButton = new Button(DeleteColorSet) - // { - // tooltip = "Delete Color Set" - // }; - // deleteSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("close", "|Delete Color Set").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(deleteSetButton); - // Button saveSetButton = new Button(SaveColorSet) - // { - // tooltip = "Save Color Set" - // }; - // saveSetButton.Add( - // new Image - // { - // image = EditorGUIUtility.IconContent("SaveAs", "|Save Color Set").image, - // scaleMode = ScaleMode.ScaleToFit - // } - // ); - // - // colorSetsRow.Add(saveSetButton); - // view.Add(colorSetsRow); - // - // _newSetNameContainer = new VisualElement - // { - // style = - // { - // flexDirection = new StyleEnum(FlexDirection.Row), - // width = Length.Percent(100), - // alignContent = new StyleEnum(Align.FlexStart), - // alignItems = new StyleEnum(Align.FlexStart), - // flexWrap = new StyleEnum(Wrap.Wrap), - // marginBottom = 10, - // display = DisplayStyle.None - // } - // }; - // - // TextField newNameField = new TextField("New Set Name") - // { - // style = - // { - // minWidth = Length.Percent(70) - // } - // }; - // _newSetNameContainer.Add(newNameField); - // - // Button newSetCreateButton = new Button( - // () => - // { - // CreateNewColorSet(newNameField.value); - // List choices = _colorSetsDropdown.choices; - // choices.Add(newNameField.value); - // _colorSetsDropdown.choices = choices; - // _colorSetsDropdown.value = newNameField.value; - // _newSetNameContainer.style.display = DisplayStyle.None; - // } - // ) - // { - // text = "Create Set" - // }; - // - // newNameField.RegisterValueChangedCallback( - // evt => - // { - // newSetCreateButton.SetEnabled(!SidekickColorSet.DoesNameExist(_dbManager, evt.newValue)); - // } - // ); - // - // _newSetNameContainer.Add(newSetCreateButton); - // view.Add(_newSetNameContainer); - // - // VisualElement allRow = new VisualElement(); - // allRow.AddToClassList("colorSelectionRow"); - // - // Label allItemsLabel = new Label("All"); - // allItemsLabel.AddToClassList("colorSelectionRowLabel"); - // allRow.Add(allItemsLabel); - // - // VisualElement allRowContent = new VisualElement(); - // allRowContent.AddToClassList("colorSelectionRowContent"); - // allRow.Add(allRowContent); - // - // Button btnAllLock = new Button - // { - // style = - // { - // left = 0 - // } - // }; - // allRowContent.Add(btnAllLock); - // Image lockButtonImage = new Image - // { - // image = _currentGlobalLockStatus - // ? EditorGUIUtility.IconContent("Locked").image - // : EditorGUIUtility.IconContent("Unlocked").image, - // scaleMode = ScaleMode.ScaleToFit - // }; - // - // btnAllLock.Add(lockButtonImage); - // - // btnAllLock.clickable.clicked += () => - // { - // foreach (SidekickColorRow colorRow in _visibleColorRows) - // { - // colorRow.IsLocked = !_currentGlobalLockStatus; - // if (colorRow.ButtonImage != null) - // { - // colorRow.ButtonImage.image = - // colorRow.IsLocked - // ? EditorGUIUtility.IconContent("Locked").image - // : EditorGUIUtility.IconContent("Unlocked").image; - // } - // } - // - // _currentGlobalLockStatus = !_currentGlobalLockStatus; - // lockButtonImage.image = _currentGlobalLockStatus - // ? EditorGUIUtility.IconContent("Locked").image - // : EditorGUIUtility.IconContent("Unlocked").image; - // }; - // - // TODO: Uncomment once all colors options are re-enabled - // Button randomAllButton = new Button - // { - // text = "R", - // style = - // { - // right = 0 - // } - // }; - // allRowContent.Add(randomAllButton); - // - // view.Add(allRow); - - _colorSelectionRowView = new VisualElement - { - style = - { - width = Length.Percent(100) - } - }; - - view.Add(_colorSelectionRowView); - - UpdateColorTabContent(); - } - - /// - /// Adds the content to the options tab. - /// - /// The view to add the content to. - private void AddOptionsTabContent(VisualElement view) - { - Label baseAssetLabel = new Label - { - style = - { - marginTop = 5, - marginLeft = 12, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - text = "Base Assets", - tooltip = "These assets are used to construct the character" - }; - - view.Add(baseAssetLabel); - - _baseModelField = new ObjectField - { - style = - { - marginLeft = 15, - marginRight = 15 - }, - tooltip = "The rigged character model used when constructing a character", - objectType = typeof(GameObject), - label = "Model" - }; - - _baseModelField.RegisterCallback>( - changeEvent => - { - // TODO: Check the model has a minimum of 1 SkinnedMeshRenderer as a child. - } - ); - view.Add(_baseModelField); - - _baseModelField.value = Resources.Load(_BASE_MESH_NAME); - - _materialField = new ObjectField - { - tooltip = "The material used when constructing a character", - objectType = typeof(Material), - label = "Material", - style = - { - marginLeft = 15, - marginRight = 15 - } - }; - - view.Add(_materialField); - - _materialField.value = Resources.Load(_BASE_MATERIAL_NAME); - - _animationField = new ObjectField - { - tooltip = "The animation controller applied when constructing a character", - objectType = typeof(AnimatorController), - label = "Animation Controller", - value = _currentAnimationController, - style = - { - marginLeft = 15, - marginRight = 15 - } - }; - - view.Add(_animationField); - - _animationField.RegisterValueChangedCallback( - evt => - { - _currentAnimationController = (AnimatorController) evt.newValue; - _sidekickRuntime.CurrentAnimationController = _currentAnimationController; - } - ); - - VisualElement updateLibraryLayout = new VisualElement - { - style = - { - minHeight = 20, - display = DisplayStyle.Flex, - flexDirection = FlexDirection.Row, - marginBottom = 2, - marginTop = 10, - marginLeft = 15, - marginRight = 2 - } - }; - - Button uploadLibraryButton = new Button() - { - text = "Update Part Library", - tooltip = "Re-scans the project folders to update the parts list" - }; - - uploadLibraryButton.clickable.clicked += async delegate - { - CreateGUI(); - await Task.Run( - async () => - { - await SidekickRuntime.PopulateToolData(_sidekickRuntime); - _callbackQueue.Enqueue(AddAllTabContent); - } - ); - - }; - - updateLibraryLayout.Add(uploadLibraryButton); - updateLibraryLayout.Add(_partCountLabel); - view.Add(updateLibraryLayout); - - Label prefabOptions = new Label - { - style = - { - marginTop = 5, - marginLeft = 12, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - text = "Prefab Options", - tooltip = "Options for how prefabs are created" - }; - - view.Add(prefabOptions); - - Toggle combineToggle = new Toggle("Combine Character Meshes") - { - value = _combineMeshes, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Whether or not to bake all the meshes down to a single mesh in the output model." - }; - - combineToggle.RegisterValueChangedCallback( - evt => - { - _combineMeshes = evt.newValue; - } - ); - - view.Add(combineToggle); - - Toggle bakeBlendsToggle = new Toggle("Combine Body Blend Shapes") - { - value = _bakeBlends, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Whether or not to bake the body blend shapes into the mesh in the output model." - }; - - bakeBlendsToggle.RegisterValueChangedCallback( - evt => - { - _bakeBlends = evt.newValue; - } - ); - - view.Add(bakeBlendsToggle); - - Label toolOptions = new Label - { - style = - { - marginTop = 5, - marginLeft = 12, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - text = "Tool Options", - tooltip = "Options for how the tool behaves" - }; - - view.Add(toolOptions); - - _previewToggle = new Toggle("Auto Build Model") - { - value = true, - style = - { - marginTop = 10, - marginLeft = 15 - } - }; - - //view.Add(_previewToggle); - - Toggle filterColorsToggle = new Toggle("Show all color properties") - { - value = _showAllColourProperties, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Display all color properties in the color tab rather than limited to only what the current character is using" - }; - - filterColorsToggle.RegisterValueChangedCallback( - evt => - { - _showAllColourProperties = evt.newValue; - UpdateVisibleColorSets(); - UpdateColorTabContent(); - } - ); - - view.Add(filterColorsToggle); - - Toggle autoOpenToggle = new Toggle("Open tool on startup") - { - value = _openWindowOnStart, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Opens the Sidekick character tool on Unity startup" - }; - - autoOpenToggle.RegisterValueChangedCallback( - evt => - { - _openWindowOnStart = evt.newValue; - EditorPrefs.SetBool(_AUTO_OPEN_STATE, _openWindowOnStart); - } - ); - - view.Add(autoOpenToggle); - - Toggle autoSaveToggle = new Toggle("Remember character") - { - value = _useAutoSaveAndLoad, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Auto saves and loads character on run/stop and unity or tool open and close." - }; - - autoSaveToggle.RegisterValueChangedCallback( - evt => - { - _useAutoSaveAndLoad = evt.newValue; - EditorPrefs.SetBool(_AUTOSAVE_STATE, _useAutoSaveAndLoad); - } - ); - - view.Add(autoSaveToggle); - - // TODO: Change to showing presets when parts are missing - Toggle showMissingParts = new Toggle("Show missing parts warning") - { - value = _showMissingPartsPopup, - style = - { - marginTop = 10, - marginLeft = 15 - }, - tooltip = "Shows a popup for missing parts when selecting a preset." - }; - - showMissingParts.RegisterValueChangedCallback( - evt => - { - _showMissingPartsPopup = evt.newValue; - EditorPrefs.SetBool(_AUTOSAVE_MISSING_PARTS, _showMissingPartsPopup); - } - ); - - view.Add(showMissingParts); - - VisualElement row = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - alignContent = new StyleEnum(Align.Center), - justifyContent = new StyleEnum(Justify.SpaceAround), - marginTop = 30 - } - }; - - Button documentationButton = new Button - { - text = "Documentation", - style = - { - width = Length.Percent(30) - }, - tooltip = "Open documentation for Sidekick characters" - }; - - documentationButton.clickable.clicked += delegate - { - string documentationPath = Path.Combine(DatabaseManager.GetPackageRootAbsolutePath() ?? string.Empty, "Documentation", "SidekickCharacters_UserGuide.pdf"); - documentationPath = Path.GetFullPath(documentationPath); - if (File.Exists(documentationPath)) - { - Application.OpenURL("file:" + documentationPath); - } - }; - - Button storeButton = new Button - { - text = "Synty Store", - style = - { - width = Length.Percent(30) - }, - tooltip = "www.syntystore.com" - }; - - storeButton.clickable.clicked += delegate - { - Application.OpenURL("https://syntystore.com"); - }; - - Button tutorialButton = new Button - { - text = "Tutorials", - style = - { - width = Length.Percent(30) - }, - tooltip = "Sidekick Characters - Quick start guide" - }; - - tutorialButton.clickable.clicked += delegate - { - // TODO: Change to direct link to tutorial playlist, when available - Application.OpenURL("https://www.youtube.com/@syntystudios"); - }; - - row.Add(documentationButton); - row.Add(storeButton); - row.Add(tutorialButton); - view.Add(row); - } - - /// - /// Reset the color rows for this color set back to the colors stored on the saved textures. - /// - private void ResetColorSet() - { - PopulateColorRowsFromTextures(); - } - - /// - /// Shows the name field and creation button for creating a new color set. - /// - private void ShowCreateNewColorSet() - { - _newSetNameContainer.style.display = DisplayStyle.Flex; - } - - /// - /// Creates a new color set with the given name. - /// - /// The name for the color set. - private void CreateNewColorSet(string setName) - { - ResetCurrentColorSet(setName); - SaveColorSet(); - } - - /// - /// Sets the current color set to a new, in-memory set of rows independent of the database - /// - /// Name of the new color set - private void ResetCurrentColorSet(string setName = "Custom") - { - _currentColorSet.ID = -1; - _currentColorSet.Species = _currentSpecies; - _currentColorSet.Name = setName; - - foreach (SidekickColorRow row in _allColorRows) - { - row.ID = -1; - row.ColorSet = _currentColorSet; - } - } - - /// - /// Deletes a color set from the database. The color set will still be available in the app until the app is closed. - /// - private void DeleteColorSet() - { - List rowsToDelete = SidekickColorRow.GetAllBySet(_dbManager, _currentColorSet); - foreach (SidekickColorRow row in rowsToDelete) - { - row.Delete(_dbManager); - } - - _currentColorSet.Delete(_dbManager); - UpdateVisibleColorSets(); - ResetCurrentColorSet(); - - } - - /// - /// Saves the current color row to the database. If it is a new color row, it is inserted into the DB; otherwise it is updated in the DB. - /// - private void SaveColorSet() - { - string baseColorSetPath = DatabaseManager.GetPackageAssetPath("Resources", "Species") ?? _BASE_COLOR_SET_PATH; - string path = Path.Combine(baseColorSetPath, _currentSpecies.Name); - path = Path.Combine(path, _currentColorSet.Name.Replace(" ", "_")); - - SaveTexturesToDisk(path); - - _currentColorSet.Save(_dbManager); - foreach (SidekickColorRow row in _allColorRows) - { - row.Save(_dbManager); - } - - UpdateVisibleColorSets(false); - - // TODO : refresh the project inspector window so the new textures show up - } - - /// - /// Saves texture files to disk at the given path. - /// - /// The path to save the textures to. - private void SaveTexturesToDisk(string path, string additionalNaming = "") - { - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - - // if no parts are selected, don't try and save a non-existent material, instead create one - if (_currentMaterial == null) - { - _currentMaterial = (Material) _materialField.value; - } - - string filename = _TEXTURE_PREFIX; - - if (!string.IsNullOrEmpty(additionalNaming)) - { - filename += additionalNaming; - } - - string filePath = Path.Combine(path, filename + _TEXTURE_COLOR_NAME); - Texture2D texture = (Texture2D) _currentMaterial.GetTexture(_COLOR_MAP); - File.WriteAllBytes(filePath, texture.EncodeToPNG()); - _currentColorSet.SourceColorPath = filePath; - // TODO: Hidden due to early access, enable when feature complete - // filePath = Path.Combine(path, filename + _TEXTURE_METALLIC_NAME); - // texture = (Texture2D) _currentMaterial.GetTexture(_METALLIC_MAP); - // File.WriteAllBytes(filePath, texture.EncodeToPNG()); - // _currentColorSet.SourceMetallicPath = filePath; - // filePath = Path.Combine(path, filename + _TEXTURE_SMOOTHNESS_NAME); - // texture = (Texture2D) _currentMaterial.GetTexture(_SMOOTHNESS_MAP); - // File.WriteAllBytes(filePath, texture.EncodeToPNG()); - // _currentColorSet.SourceSmoothnessPath = filePath; - // filePath = Path.Combine(path, filename + _TEXTURE_REFLECTION_NAME); - // texture = (Texture2D) _currentMaterial.GetTexture(_REFLECTION_MAP); - // File.WriteAllBytes(filePath, texture.EncodeToPNG()); - // _currentColorSet.SourceReflectionPath = filePath; - // filePath = Path.Combine(path, filename + _TEXTURE_EMISSION_NAME); - // texture = (Texture2D) _currentMaterial.GetTexture(_EMISSION_MAP); - // File.WriteAllBytes(filePath, texture.EncodeToPNG()); - // _currentColorSet.SourceEmissionPath = filePath; - // filePath = Path.Combine(path, filename + _TEXTURE_OPACITY_NAME); - // texture = (Texture2D) _currentMaterial.GetTexture(_OPACITY_MAP); - // File.WriteAllBytes(filePath, texture.EncodeToPNG()); - // _currentColorSet.SourceOpacityPath = filePath; - } - - /// - /// Updates the color sets that are selectable in the dropdown on the colors tab - /// - /// Whether to set the color sets dropdown value to 'Custom' - private void UpdateVisibleColorSets(bool setDropdownToCustom = true) - { - List sets = SidekickColorSet.GetAllBySpecies(_dbManager, _currentSpecies); - if (sets.Count == 0) - { - sets.Add(SidekickColorSet.GetDefault(_dbManager)); - } - - List setNames = sets.Select(set => set.Name).ToList(); - _colorSetsDropdown.choices = setNames; - _visibleColorSets = sets; - - if (setDropdownToCustom) - { - _colorSetsDropdown.value = "Custom"; - } - } - - /// - /// Updates all the color rows currently visible in the UI. - /// - private void UpdateAllVisibleColors() - { - foreach (SidekickColorRow row in _visibleColorRows) - { - UpdateAllColors(row); - } - } - - /// - /// Updates all the color types for a given color row. - /// - /// The color row to update. - private void UpdateAllColors(SidekickColorRow colorRow) - { - foreach (ColorType colorType in Enum.GetValues(typeof(ColorType))) - { - _sidekickRuntime.UpdateColor(colorType, colorRow); - } - } - - /// - /// Populates the part color rows based on the filter being used. - /// - private void PopulatePartColorRows() - { - List propertiesToShow = new List(); - - switch (_currentPartType) - { - case ColorPartType.Species: - List speciesProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Species); - foreach (SidekickColorProperty property in speciesProperties) - { - Vector2 uv = new Vector2(property.U, property.V); - if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.Outfit: - List outfitProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Outfits); - foreach (SidekickColorProperty property in outfitProperties) - { - Vector2 uv = new Vector2(property.U, property.V); - if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.Attachments: - List attachmentProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Attachments); - foreach (SidekickColorProperty property in attachmentProperties) - { - Vector2 uv = new Vector2(property.U, property.V); - if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.Materials: - List materialProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Materials); - foreach (SidekickColorProperty property in materialProperties) - { - Vector2 uv = new Vector2(property.U, property.V); - if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.Elements: - List elementProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Elements); - foreach (SidekickColorProperty property in elementProperties) - { - Vector2 uv = new Vector2(property.U, property.V); - if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.CharacterHead: - List headProperties = new List(); - foreach (ColorPartType type in ColorPartType.CharacterHead.GetPartTypes()) - { - headProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); - } - - foreach (SidekickColorProperty property in headProperties) - { - if (!propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.CharacterUpperBody: - List upperProperties = new List(); - foreach (ColorPartType type in ColorPartType.CharacterUpperBody.GetPartTypes()) - { - upperProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); - } - - foreach (SidekickColorProperty property in upperProperties) - { - if (!propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.CharacterLowerBody: - List lowerProperties = new List(); - foreach (ColorPartType type in ColorPartType.CharacterLowerBody.GetPartTypes()) - { - lowerProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); - } - - foreach (SidekickColorProperty property in lowerProperties) - { - if (!propertiesToShow.Contains(property)) - { - propertiesToShow.Add(property); - } - } - - break; - case ColorPartType.Head: - case ColorPartType.Hair: - case ColorPartType.EyebrowLeft: - case ColorPartType.EyebrowRight: - case ColorPartType.EyeLeft: - case ColorPartType.EyeRight: - case ColorPartType.EarLeft: - case ColorPartType.EarRight: - case ColorPartType.FacialHair: - case ColorPartType.Torso: - case ColorPartType.ArmUpperLeft: - case ColorPartType.ArmUpperRight: - case ColorPartType.ArmLowerLeft: - case ColorPartType.ArmLowerRight: - case ColorPartType.HandLeft: - case ColorPartType.HandRight: - case ColorPartType.Hips: - case ColorPartType.LegLeft: - case ColorPartType.LegRight: - case ColorPartType.FootLeft: - case ColorPartType.FootRight: - case ColorPartType.AttachmentHead: - case ColorPartType.AttachmentFace: - case ColorPartType.AttachmentBack: - case ColorPartType.AttachmentHipsFront: - case ColorPartType.AttachmentHipsBack: - case ColorPartType.AttachmentHipsLeft: - case ColorPartType.AttachmentHipsRight: - case ColorPartType.AttachmentShoulderLeft: - case ColorPartType.AttachmentShoulderRight: - case ColorPartType.AttachmentElbowLeft: - case ColorPartType.AttachmentElbowRight: - case ColorPartType.AttachmentKneeLeft: - case ColorPartType.AttachmentKneeRight: - case ColorPartType.Nose: - case ColorPartType.Teeth: - case ColorPartType.Tongue: - case ColorPartType.Wrap:/* - case ColorPartType.AttachmentHandLeft: - case ColorPartType.AttachmentHandRight: */ - propertiesToShow = SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[_currentPartType]); - break; - case ColorPartType.AllParts: - default: - propertiesToShow = _showAllColourProperties || _currentUVList == null - ? SidekickColorProperty.GetAll(_dbManager) - : SidekickColorProperty.GetByUVs(_dbManager, _currentUVList); - break; - } - - _visibleColorRows.Clear(); - - // when filtering the view to a specific UV dictionary, we need to reset the property order - propertiesToShow.Sort((a, b) => a.ID.CompareTo(b.ID)); - - foreach (SidekickColorProperty property in propertiesToShow) - { - foreach (SidekickColorRow row in _allColorRows.Where(row => row.ColorProperty.ID == property.ID)) - { - _visibleColorRows.Add(row); - } - } - } - - /// - /// Refreshes the visible color rows in the UI. - /// - private void RefreshVisibleColorRows() - { - _colorSelectionRowView.Clear(); - - foreach (ColorGroup group in Enum.GetValues(typeof(ColorGroup))) - { - List properties = _visibleColorRows - .Select(row => row.ColorProperty) - .Where(prop => prop.Group == group) - .ToList(); - - string tooltipText = ""; - - switch (group) - { - case ColorGroup.Species: - tooltipText = "Species colors make up the character as if it has no outfit on. (for example - skin, teeth, tongue, fingernails etc)"; - break; - case ColorGroup.Outfits: - tooltipText = "Outfit colors make up the clothing on the character. (for example - Torso outfit, arm outfit, hand outfit etc)"; - break; - case ColorGroup.Attachments: - tooltipText = "Attachment colors make up the additional parts attached to a character. (for example - a backpack, shoulder pads, elbow pads, knee pads etc)"; - break; - case ColorGroup.Materials: - tooltipText = "material colors make up a collection of shared standard materials (for example - wood, metal, leather, paper, bone etc)"; - break; - } - - if (properties.Count > 0) - { - Label groupLabel = new Label(group.ToString()) - { - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold), - marginBottom = 4, - marginTop = 6 - }, - tooltip = tooltipText - }; - _colorSelectionRowView.Add(groupLabel); - - VisualElement headerContainer = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - fontSize = 10, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - Label colorHeader = new Label("Color") - { - style = - { - width = 103, - marginLeft = 155 - } - }; - Label metallicHeader = new Label("Metallic") - { - style = - { - width = 66 - } - }; - Label smoothnessHeader = new Label("Smoothness") - { - style = - { - width = 66 - } - }; - Label reflectionHeader = new Label("Reflection") - { - style = - { - width = 66 - } - }; - Label emissionHeader = new Label("Emission") - { - style = - { - width = 66 - } - }; - Label opacityHeader = new Label("Opacity") - { - style = - { - width = 66 - } - }; - - headerContainer.Add(colorHeader); - // headerContainer.Add(metallicHeader); - // headerContainer.Add(smoothnessHeader); - // headerContainer.Add(reflectionHeader); - // headerContainer.Add(emissionHeader); - // headerContainer.Add(opacityHeader); - - _colorSelectionRowView.Add(headerContainer); - - foreach (SidekickColorProperty property in properties) - { - foreach (SidekickColorRow row in _visibleColorRows.Where(row => row.ColorProperty.ID == property.ID)) - { - CreateColorRow(_colorSelectionRowView, row); - } - } - } - } - } - - /// - /// Populates the color rows from texture files on the disk. - /// - private void PopulateColorRowsFromTextures() - { - TextureImporter textureImporter = null; - - Texture2D mainColor = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceColorPath); - if (mainColor != null) - { - mainColor.filterMode = FilterMode.Point; - if (!mainColor.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceColorPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - else - { - Material defaultMaterial = (Material) _materialField.value; - mainColor = (Texture2D) defaultMaterial.mainTexture; - } - - Texture2D metallic = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceMetallicPath); - if (metallic != null) - { - metallic.filterMode = FilterMode.Point; - if (!metallic.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceMetallicPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - - Texture2D smoothness = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceSmoothnessPath); - if (smoothness != null) - { - smoothness.filterMode = FilterMode.Point; - if (!smoothness.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceSmoothnessPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - - Texture2D reflection = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceReflectionPath); - if (reflection != null) - { - reflection.filterMode = FilterMode.Point; - if (!reflection.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceReflectionPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - - Texture2D emission = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceEmissionPath); - if (emission != null) - { - emission.filterMode = FilterMode.Point; - if (!emission.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceEmissionPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - - Texture2D opacity = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceOpacityPath); - if (opacity != null) - { - opacity.filterMode = FilterMode.Point; - if (!opacity.isReadable) - { - textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceOpacityPath); - textureImporter.isReadable = true; - textureImporter.SaveAndReimport(); - } - } - - List newColorRows = new List(); - - List currentSetColors = SidekickColorRow.GetAllBySet(_dbManager, _currentColorSet); - - // TODO : if textures don't exist BUT color rows exist in DB, ask user if they want to re-save the textures from the DB values, loop back and reimport - // TODO : if textures don't exist AND color rows don't exist in DB, delete the colorset entry in DB/dropdown, advance to next on list and reload - - foreach (SidekickColorProperty property in SidekickColorProperty.GetAll(_dbManager)) - { - SidekickColorRow existingRow = currentSetColors.FirstOrDefault(row => row.ColorProperty.ID == property.ID); - SidekickColorRow newRow = new SidekickColorRow - { - ID = existingRow?.ID ?? -1, - ColorSet = _currentColorSet, - ColorProperty = property, - // TODO remove null checks when we know we have textures - NiceColor = mainColor?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceColor ?? Color.red, - // NiceMetallic = metallic?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceMetallic ?? Color.red, - // NiceSmoothness = smoothness?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceSmoothness ?? Color.red, - // NiceReflection = reflection?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceReflection ?? Color.red, - // NiceEmission = emission?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceEmission ?? Color.red, - // NiceOpacity = opacity?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceOpacity ?? Color.red - }; - - newRow.Save(_dbManager); - newColorRows.Add(newRow); - } - - _allColorRows = newColorRows; - PopulatePartColorRows(); - RefreshVisibleColorRows(); - } - - /// - /// Adds a color row to the given view. - /// - /// The view to add the color row to. - /// The color row to populate this UI element with. - private void CreateColorRow(VisualElement view, SidekickColorRow colorRow) - { - VisualElement row = new VisualElement(); - row.AddToClassList("colorSelectionRow"); - - Label rowLabel = new Label(colorRow.ColorProperty.Name); - rowLabel.AddToClassList("colorSelectionRowLabel"); - row.Add(rowLabel); - - VisualElement rowContent = new VisualElement(); - rowContent.AddToClassList("colorSelectionRowContent"); - - row.Add(rowContent); - - // TODO: uncomment when locking is required. - // Button btnLock = new Button(); - // - // Image lockImage = new Image - // { - // image = colorRow.IsLocked ? EditorGUIUtility.IconContent("Locked").image : EditorGUIUtility.IconContent("Unlocked").image, - // scaleMode = ScaleMode.ScaleToFit - // }; - // - // btnLock.Add(lockImage); - // colorRow.ButtonImage = lockImage; - // rowContent.Add(btnLock); - // btnLock.clickable.clicked += () => - // { - // colorRow.IsLocked = !colorRow.IsLocked; - // lockImage.image = colorRow.IsLocked - // ? EditorGUIUtility.IconContent("Locked").image - // : EditorGUIUtility.IconContent("Unlocked").image; - // }; - - ColorField colorField = new ColorField - { - value = colorRow.NiceColor, - tooltip = colorRow.ColorProperty.Name + " Color", - style = - { - // TODO: shrink to 50 once all colors options are re-enabled - width = 100 - } - }; - rowContent.Add(colorField); - colorField.RegisterValueChangedCallback( - evt => - { - colorRow.NiceColor = evt.newValue; - _sidekickRuntime.UpdateColor(ColorType.MainColor, colorRow); - } - ); - - // TODO: Uncomment once all colors options are re-enabled - // ColorField metallicField = new ColorField - // { - // value = colorRow.NiceMetallic, - // tooltip = colorRow.ColorProperty.Name + " Metallic", - // style = - // { - // width = 60 - // } - // }; - // rowContent.Add(metallicField); - // metallicField.RegisterValueChangedCallback( - // evt => - // { - // colorRow.NiceMetallic = evt.newValue; - // _sidekickRuntime.UpdateColor(ColorType.Metallic, colorRow); - // } - // ); - // - // ColorField smoothnessField = new ColorField - // { - // value = colorRow.NiceSmoothness, - // tooltip = colorRow.ColorProperty.Name + " Smoothness", - // style = - // { - // width = 60 - // } - // }; - // rowContent.Add(smoothnessField); - // smoothnessField.RegisterValueChangedCallback( - // evt => - // { - // colorRow.NiceSmoothness = evt.newValue; - // _sidekickRuntime.UpdateColor(ColorType.Smoothness, colorRow); - // } - // ); - // - // ColorField reflectionField = new ColorField - // { - // value = colorRow.NiceReflection, - // tooltip = colorRow.ColorProperty.Name + " Reflection", - // style = - // { - // width = 60 - // } - // }; - // rowContent.Add(reflectionField); - // reflectionField.RegisterValueChangedCallback( - // evt => - // { - // colorRow.NiceReflection = evt.newValue; - // _sidekickRuntime.UpdateColor(ColorType.Reflection, colorRow); - // } - // ); - // - // ColorField emissionField = new ColorField - // { - // value = colorRow.NiceEmission, - // tooltip = colorRow.ColorProperty.Name + " Emission", - // style = - // { - // width = 60 - // } - // }; - // rowContent.Add(emissionField); - // emissionField.RegisterValueChangedCallback( - // evt => - // { - // colorRow.NiceEmission = evt.newValue; - // _sidekickRuntime.UpdateColor(ColorType.Emission, colorRow); - // } - // ); - // - // ColorField opacityField = new ColorField - // { - // value = colorRow.NiceOpacity, - // tooltip = colorRow.ColorProperty.Name + " Opacity", - // style = - // { - // width = 60 - // } - // }; - // rowContent.Add(opacityField); - // opacityField.RegisterValueChangedCallback( - // evt => - // { - // colorRow.NiceOpacity = evt.newValue; - // _sidekickRuntime.UpdateColor(ColorType.Opacity, colorRow); - // } - // ); - - // Button randomButton = new Button - // { - // text = "R", - // style = - // { - // right = 0 - // } - // }; - // rowContent.Add(randomButton); - - view.Add(row); - } - - /// - /// Switches the currently visible tab to the given tab. - /// - /// The tab to switch to. - private void SwitchToTab(TabView newTab) - { - if (_currentTab == newTab) - { - return; - } - - _currentTab = newTab; - - _bodyPresetTab.value = _currentTab == TabView.Preset; - _bodyPartsTab.value = _currentTab == TabView.Parts; - _bodyShapeTab.value = _currentTab == TabView.Body; - _colorSelectionTab.value = _currentTab == TabView.Colors; - // _decalSelectionTab.value = _currentTab == TabView.Decals; - _optionTab.value = _currentTab == TabView.Options; - - _presetView.style.display = _bodyPresetTab.value ? DisplayStyle.Flex : DisplayStyle.None; - _partView.style.display = _bodyPartsTab.value ? DisplayStyle.Flex : DisplayStyle.None; - _bodyShapeView.style.display = _bodyShapeTab.value ? DisplayStyle.Flex : DisplayStyle.None; - _colorSelectionView.style.display = _colorSelectionTab.value ? DisplayStyle.Flex : DisplayStyle.None; - //_decalSelectionView.style.display = _decalSelectionTab.value ? DisplayStyle.Flex : DisplayStyle.None; - _optionSelectionView.style.display = _optionTab.value ? DisplayStyle.Flex : DisplayStyle.None; - } - - /// - /// Populate the preset tab content. - /// - private void PopulatePresetUI() - { - _presetView.Clear(); - - Dictionary> dropdowns = new Dictionary>(); - - Foldout speciesFoldout = new Foldout - { - text = "Select - Species", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - }; - - List speciesNames = _allSpecies.Select(species => species.Name).ToList(); - - _speciesPresetField = new DropdownField - { - label = "Species", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) - }, - tooltip = "Select the species of your character" - }; - _speciesPresetField.choices = speciesNames; - _speciesPresetField.RegisterValueChangedCallback( - evt => - { - _speciesField.value = _speciesPresetField.value; - ProcessSpeciesChange(evt.newValue); - } - ); - - _speciesPresetField.index = _currentSpecies != null && speciesNames.Count > 0 ? _speciesPresetField.choices.IndexOf(_currentSpecies.Name) : 0; - speciesFoldout.Add(_speciesPresetField); - _presetView.Add(speciesFoldout); - - List allFilters = SidekickPresetFilter.GetAll(_dbManager); - - allFilters.Sort( - (filterA, filterB) => String.CompareOrdinal(filterA.Term, filterB.Term) - ); - - if (allFilters.Count > 0) - { - Foldout filterFoldout = new Foldout() - { - text = "Select - Preset Part Filter", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - VisualElement filterContent = new VisualElement - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - flexWrap = new StyleEnum(Wrap.Wrap) - } - }; - - Color borderColor = new Color(0.17f, 0.17f, 0.17f); - Color backgroundColor = new Color(0.35f, 0.35f, 0.35f); - List allFilterToggles = new List(); - - foreach (SidekickPresetFilter filter in allFilters) - { - Toggle outfitToggle = new Toggle(filter.Term) - { - value = !_partPresetFilterToggleMap.TryGetValue(filter, out bool toggleValue) || toggleValue, - style = - { - width = 160, - borderBottomWidth = 1, - borderBottomColor = borderColor, - paddingBottom = 2, - borderLeftWidth = 1, - borderLeftColor = borderColor, - paddingLeft = 2, - borderRightWidth = 1, - borderRightColor = borderColor, - paddingRight = 2, - borderTopWidth = 1, - borderTopColor = borderColor, - paddingTop = 2, - borderBottomLeftRadius = 3, - borderBottomRightRadius = 3, - borderTopLeftRadius = 3, - borderTopRightRadius = 3, - backgroundColor = backgroundColor, - textOverflow = new StyleEnum(TextOverflow.Ellipsis) - } - }; - - allFilterToggles.Add(outfitToggle); - - if (outfitToggle.value) - { - _partPresetFilterToggleMap[filter] = outfitToggle.value; - } - - outfitToggle.RegisterValueChangedCallback( - evt => - { - _partPresetFilterToggleMap[filter] = evt.newValue; - PopulatePresetPartDropdowns(dropdowns); - } - ); - - filterContent.Add(outfitToggle); - } - - VisualElement buttonRow = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row) - } - }; - - Button selectAll = new Button( - delegate - { - foreach (Toggle toggle in allFilterToggles) - { - toggle.value = true; - } - } - ) - { - text = "Select All" - }; - - Button selectNone = new Button( - delegate - { - foreach (Toggle toggle in allFilterToggles) - { - toggle.value = false; - } - } - ) - { - text = "Select None" - }; - - buttonRow.Add(selectAll); - buttonRow.Add(selectNone); - - filterFoldout.Add(buttonRow); - filterFoldout.Add(filterContent); - - _presetView.Add(filterFoldout); - } - - _availablePresets = SidekickPartPreset.GetAll(_dbManager); - - Foldout generateFoldout = new Foldout - { - text = "Randomize Character", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - //tooltip = "Create a character based on the selected species" - }; - - Button generateButton = new Button() - { - style = - { - minHeight = 50, - marginRight = 18, - flexDirection = new StyleEnum(FlexDirection.Row), - alignContent = new StyleEnum(Align.Center), - alignItems = new StyleEnum(Align.Center), - unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), - justifyContent = new StyleEnum(Justify.Center) - }, - tooltip = "Generate a character at the push of a button" - }; - - Texture2D randomImage = Resources.Load("UI/T_Random"); - generateButton.Add( - new Image - { - image = randomImage, - scaleMode = ScaleMode.ScaleToFit, - style = - { - paddingTop = new StyleLength(1), - paddingBottom = new StyleLength(1), - paddingRight = 5, - alignSelf = new StyleEnum(Align.Center) - } - } - ); - generateButton.Add( - new Label - { - text = "Randomize Character", - style = - { - alignSelf = new StyleEnum(Align.Center) - } - } - ); - - generateFoldout.Add(generateButton); - _presetView.Add(generateFoldout); - - Foldout presetsFoldout = new Foldout() - { - text = "Presets", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - //tooltip = "Select from a number of collections of parts, body types and colors" - }; - - Label partTitle = new Label("Parts") - { - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - tooltip = "Collections of character parts ie. Head attachment, Torso, Nose that make up the character" - }; - - string tooltipText = ""; - - presetsFoldout.Add(partTitle); - _presetView.Add(presetsFoldout); - - _presetPartContainer = new VisualElement(); - presetsFoldout.Add(_presetPartContainer); - - PopulatePresetPartDropdowns(dropdowns); - - Label bodyTitle = new Label("Body") - { - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - tooltip = "Preset bodies in a number of types, sizes and musculature" - }; - - presetsFoldout.Add(bodyTitle); - _currentBodyPresetDictionary = new Dictionary(); - List bodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); - List bodyShapeNames = bodyShapes.Select(b => b.Name).ToList(); - for (int i = 0; i < bodyShapeNames.Count; i++) - { - _currentBodyPresetDictionary.Add(bodyShapeNames[i], bodyShapes[i]); - } - - string bodyTypeLabel = "Body Type"; - - string bodyShapeDefaultValue = "Androgynous Medium"; - - if (bodyShapeNames.Count > 0) - { - bodyShapeDefaultValue = _presetDefaultValues.TryGetValue(bodyTypeLabel, out string bodyShapeValue) - ? bodyShapeValue - : bodyShapeDefaultValue; - } - - bodyShapeNames.Sort(); - - tooltipText = "Select a body preset for you character - a body type preset is made up of combinations of body type, size and musculature."; - - dropdowns[bodyTypeLabel] = CreatePresetRow(presetsFoldout, bodyTypeLabel, tooltipText, bodyShapeNames, false, bodyShapeDefaultValue, PresetDropdownType.Body); - - Label colorTitle = new Label("Colors") - { - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - }, - tooltip = "Collections of character colors ie. Skin color, teeth color, eye color, hair color that make up the characters colors" - }; - - SidekickSpecies unrestrictedSpecies = SidekickSpecies.GetByName(_dbManager, "Unrestricted"); - - presetsFoldout.Add(colorTitle); - _currentColorSpeciesPresetDictionary = new Dictionary(); - _currentColorOutfitsPresetDictionary = new Dictionary(); - _currentColorAttachmentsPresetDictionary = new Dictionary(); - _currentColorMaterialsPresetDictionary = new Dictionary(); - _currentColorElementsPresetDictionary = new Dictionary(); - foreach (ColorGroup colorGroup in Enum.GetValues(typeof(ColorGroup))) - { - // TODO: remove when Element colors are re-added - if (colorGroup == ColorGroup.Elements) - { - continue; - } - - List colorPresets = colorGroup is ColorGroup.Species && _currentSpecies.ID != unrestrictedSpecies.ID - ? SidekickColorPreset.GetAllByColorGroupAndSpecies(_dbManager, colorGroup, _currentSpecies) - : SidekickColorPreset.GetAllByColorGroup(_dbManager, colorGroup); - - List colorPresetNames = colorPresets.Select(cp => cp.Name).ToList(); - for (int i = 0; i < colorPresetNames.Count; i++) - { - switch (colorGroup) - { - case ColorGroup.Species: - _currentColorSpeciesPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); - tooltipText = "Select a species color preset for your character - a species color preset is made up of the colors that would make up the character if it had no outfit on. (for example - skin, teeth, tongue, fingernails etc)"; - break; - case ColorGroup.Outfits: - _currentColorOutfitsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); - tooltipText = "Select an outfit color preset for your character - an outfit color preset is made up of the colors that make up the clothing on the character. (for example - torso outfit, arm outfit, hand outfit etc)"; - break; - case ColorGroup.Attachments: - _currentColorAttachmentsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); - tooltipText = "Select an attachments color preset for your character - an attachments color preset is made up of the colors used on additional parts on the character. (for example - shoulder attachments, back attachments, hip attachments etc)"; - break; - case ColorGroup.Materials: - _currentColorMaterialsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); - tooltipText = "Select a materials color preset for your character - a materials color preset is made up of the colors that make up general materials of the outfit and attachments. (for example - metal, wood, leather, plastic, bone etc)"; - break; - case ColorGroup.Elements: - _currentColorElementsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); - break; - } - } - - string defaultValue = "None"; - - if (colorPresetNames.Count > 0) - { - defaultValue = _presetDefaultValues.TryGetValue(colorGroup.ToString(), out string value) - ? value - : defaultValue; - } - - colorPresetNames.Sort(); - - if (_processingSpeciesChange && colorGroup == ColorGroup.Species && !_loadingCharacter) - { - defaultValue = colorPresetNames.Count > 0 ? colorPresetNames[0] : "None"; - } - - dropdowns[colorGroup.ToString()] = CreatePresetRow(presetsFoldout, colorGroup.ToString(), tooltipText, colorPresetNames, true, defaultValue, PresetDropdownType.Color); - } - - /* TODO: When decals are added (issue 1108), uncomment and update this section - Label textureTitle = new Label("Textures") - { - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - presetsFoldout.Add(textureTitle); - CreatePresetRow(presetsFoldout, "Skin", new List(), true, "None", PresetDropdownType.Texture); - CreatePresetRow(presetsFoldout, "Outfit", new List(), true, "None", PresetDropdownType.Texture); - */ - - generateButton.clickable.clicked += delegate - { - _applyingPreset = true; - foreach (PopupField dropdown in dropdowns.Values) - { - List values = dropdown.choices; - values.Remove("None"); - string newValue = "None"; - if (values.Count > 0) - { - newValue = values[Random.Range(0, values.Count - 1)]; - } - dropdown.value = newValue; - } - - // if (_newModel != null) - // { - // DestroyImmediate(_newModel); - // } - - _newModel = GenerateCharacter(false, true); - UpdatePartUVData(); - _applyingPreset = false; - }; - } - - /// - /// Populates the preset part dropdowns. - /// - /// The list of all preset dropdowns to put the preset part dropdowns into once populated - /// - private void PopulatePresetPartDropdowns(Dictionary> dropdowns) - { - _presetPartContainer.Clear(); - string tooltipText = ""; - _currentHeadPresetDictionary = new Dictionary(); - _currentUpperBodyPresetDictionary = new Dictionary(); - _currentLowerBodyPresetDictionary = new Dictionary(); - HashSet mappedPresets = new HashSet(); - - if (_partPresetFilterToggleMap.Count > 0) - { - foreach (KeyValuePair entry in _partPresetFilterToggleMap) - { - if (entry.Value) - { - if (_sidekickRuntime.MappedPresetFilterDictionary.TryGetValue(entry.Key.Term, out List presets)) - { - mappedPresets.UnionWith(presets); - } - } - } - - if (_sidekickRuntime.MappedBasePresetDictionary.TryGetValue(_currentSpecies, out List basePresets)) - { - mappedPresets.UnionWith(basePresets); - } - } - else - { - mappedPresets.UnionWith(_availablePresets); - } - - List allPresets = mappedPresets.ToList(); - - SidekickSpecies unrestrictedSpecies = SidekickSpecies.GetByName(_dbManager, "Unrestricted"); - - foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) - { - // only filter head part presets by species - List presets = partGroup is PartGroup.Head && _currentSpecies.ID != unrestrictedSpecies?.ID - ? allPresets.Where(preset => preset.Species.ID == _currentSpecies.ID && preset.PartGroup == partGroup).ToList() - : allPresets.Where(preset => preset.PartGroup == partGroup).ToList(); - List presetNames = new List(); - foreach (SidekickPartPreset preset in presets) - { - switch (partGroup) - { - case PartGroup.Head: - _currentHeadPresetDictionary.Add(preset.Name, preset); - tooltipText = "Select a head preset for you character - a head preset is made up of parts like a head, nose, eyes and teeth etc."; - break; - case PartGroup.UpperBody: - _currentUpperBodyPresetDictionary.Add(preset.Name, preset); - tooltipText = "Select an upper body preset for you character - an upper body preset is made up of parts like a torso, arms, hands and a back attachment etc."; - break; - case PartGroup.LowerBody: - _currentLowerBodyPresetDictionary.Add(preset.Name, preset); - tooltipText = "Select a lower body preset for you character - a lower body preset is made up of parts like hips, legs, feet and hip attachments etc."; - break; - } - - presetNames.Add(preset.Name); - } - - string defaultValue = "None"; - - if (presetNames.Count > 0) - { - if (_presetDefaultValues.TryGetValue(partGroup.ToString(), out string value)) - { - defaultValue = presetNames.Contains(value) ? value : "None"; - - if (_processingSpeciesChange && partGroup == PartGroup.Head && value != "None" && defaultValue == "None") - { - defaultValue = presetNames[Random.Range(0, presetNames.Count - 1)]; - } - } - } - - presetNames.Sort(); - - dropdowns[partGroup.ToString()] = CreatePresetRow(_presetPartContainer, partGroup.ToString(), tooltipText, presetNames, true, defaultValue, PresetDropdownType.Part); - } - } - - /// - /// Create a selection row for the preset tab with the given values. - /// - /// The view to add the row to. - /// The label to put in the row. - /// The tooltip to display for this row. - /// The values for the dropdown in the row. - /// Whether to include `None` as a value in the dropdown. - /// The default value to select from the dropdown. - /// What section of the preset UI this dropdown is part of. - /// The dropdown selection UI element. - private PopupField CreatePresetRow( - VisualElement view, - string rowLabel, - string tooltipText, - List dropdownValues, - bool includeNoneValue, - string defaultValue, - PresetDropdownType dropdownType) - { - VisualElement partContainer = new VisualElement - { - style = - { - minHeight = 20, - display = DisplayStyle.Flex, - flexDirection = FlexDirection.Row, - marginBottom = 2, - marginTop = 2, - marginLeft = 15, - marginRight = 2, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) - } - }; - - Label partTypeTitle = new Label(rowLabel.ToString()) - { - style = - { - unityTextAlign = TextAnchor.MiddleLeft, - width = 150 - }, - tooltip = tooltipText - }; - - Button removeButton = new Button() - { - tooltip = "Remove this preset, resets selection to None" - }; - - removeButton.Add( - new Image - { - image = Resources.Load("UI/T_Clear"), - scaleMode = ScaleMode.ScaleToFit - } - ); - - int marginLeft = 0; - if (dropdownType != PresetDropdownType.Part) - { - marginLeft = 36; - } - - Button previousButton = new Button() - { - tooltip = "Select the previous preset", - style = - { - marginLeft = marginLeft - } - }; - - previousButton.Add( - new Image - { - image = EditorGUIUtility.IconContent("tab_prev", "|Previous Preset").image, - scaleMode = ScaleMode.ScaleToFit - } - ); - - Button nextButton = new Button() - { - tooltip = "Select the next preset" - }; - - nextButton.Add( - new Image - { - image = EditorGUIUtility.IconContent("tab_next", "|Next Preset").image, - scaleMode = ScaleMode.ScaleToFit - } - ); - - Button randomButton = new Button() - { - tooltip = "Randomly select a preset" - }; - - Texture2D randomImage = Resources.Load("UI/T_Random"); - randomButton.Add( - new Image - { - image = randomImage, - scaleMode = ScaleMode.ScaleToFit, - style = - { - paddingTop = new StyleLength(1), - paddingBottom = new StyleLength(1) - } - } - ); - - if (!dropdownValues.Contains(defaultValue)) - { - defaultValue = includeNoneValue ? "None" : dropdownValues[0]; - } - - List popupValues = new List(); - if (includeNoneValue) - { - popupValues.Add("None"); - }; - - popupValues.AddRange(dropdownValues); - - PopupField partSelection = new PopupField(popupValues, 0) - { - value = "None", - style = - { - minWidth = 180 - }, - tooltip = tooltipText - }; - - partSelection.RegisterValueChangedCallback( - evt => - { - _presetDefaultValues[rowLabel] = evt.newValue; - - // Correctly enable/disable next and previous buttons based on selection - previousButton.SetEnabled(partSelection.index > 0); - nextButton.SetEnabled(partSelection.index < popupValues.Count - 1); - - switch (dropdownType) - { - case PresetDropdownType.Part: - _applyingPreset = true; - - bool hasErrors = false; - string errorMessage = "The following parts could not be found in your project:\n"; - Enum.TryParse(rowLabel, out PartGroup group); - List partTypesToRemove = group.GetPartTypes(); - SidekickPartPreset currentPartPreset = null; - List presetParts = new List(); - // NOTE : need to ensure evt.newValue is always in the dictionary ahead of this, or change to GetValueOrDefault() - if (evt.newValue != "None") - { - switch (group) - { - case PartGroup.Head: - currentPartPreset = _currentHeadPresetDictionary[evt.newValue]; - break; - case PartGroup.UpperBody: - currentPartPreset = _currentUpperBodyPresetDictionary[evt.newValue]; - break; - case PartGroup.LowerBody: - currentPartPreset = _currentLowerBodyPresetDictionary[evt.newValue]; - break; - } - presetParts = SidekickPartPresetRow.GetAllByPreset(_dbManager, currentPartPreset); - } - - foreach (SidekickPartPresetRow presetPart in presetParts) - { - if (Enum.TryParse(CharacterPartTypeUtils.GetTypeNameFromShortcode(presetPart.PartType), out CharacterPartType partType)) - { - if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls currentField)) - { - if (presetPart.Part != null) - { - _currentCharacter[partType] = presetPart.Part; - } - - UpdateResult result = new UpdateResult(errorMessage, hasErrors); - - if (partType == CharacterPartType.Wrap) - { - if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls wrapSelection)) - { - if (_requiresWrap && _bodyTypeBlendValue > 0) - { - wrapSelection.PartDropdown.SetEnabled(true); - wrapSelection.RandomisePartDropdownValue(); - } - else - { - wrapSelection.PartDropdown.SetEnabled(false); - wrapSelection.SetPartDropdownValue(null); - _currentCharacter.Remove(CharacterPartType.Wrap); - } - } - } - else - { - result = UpdatePartDropdown( - currentField, - presetPart.Part?.Name ?? "None", - errorMessage, - hasErrors - ); - } - - hasErrors = result.HasErrors; - errorMessage = result.ErrorMessage; - partTypesToRemove.Remove(partType); - } - } - } - - foreach (CharacterPartType partType in partTypesToRemove) - { - if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls currentField)) - { - UpdateResult result = UpdatePartDropdown(currentField, "None", errorMessage, hasErrors); - - hasErrors = result.HasErrors; - errorMessage = result.ErrorMessage; - } - } - - if (hasErrors) - { - EditorUtility.DisplayDialog( - "Assets Missing", - errorMessage, - "OK" - ); - } - - _applyingPreset = false; - - _newModel = GameObject.Find(_OUTPUT_MODEL_NAME); - - // if (_newModel != null) - // { - // DestroyImmediate(_newModel); - // } - - _newModel = GenerateCharacter(false, true); - UpdatePartUVData(); - break; - case PresetDropdownType.Body: - SidekickBodyShapePreset bodyShapePreset = _currentBodyPresetDictionary[evt.newValue]; - if (Math.Abs(_bodyTypeSlider.value - bodyShapePreset.BodyType) < 0.001f) - { - string body = "None"; - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Torso, out PartTypeControls bodySelection)) - { - body = bodySelection.PartDropdown.value; - } - - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) - { - if (body != "None" && _requiresWrap && _bodyTypeBlendValue > 0) - { - wrapSelection.PartDropdown.SetEnabled(true); - wrapSelection.RandomisePartDropdownValue(); - } - else - { - wrapSelection.PartDropdown.SetEnabled(false); - wrapSelection.SetPartDropdownValue(null); - _currentCharacter.Remove(CharacterPartType.Wrap); - } - } - } - - _bodyTypeSlider.value = bodyShapePreset.BodyType; - _bodySizeSlider.value = bodyShapePreset.BodySize; - _musclesSlider.value = bodyShapePreset.Musculature; - break; - case PresetDropdownType.Color: - if (evt.newValue == "None") - { - return; - } - - ResetCurrentColorSet(); - - Enum.TryParse(rowLabel, out ColorGroup colorGroup); - SidekickColorPreset colorPreset = null; - // NOTE : need to ensure evt.newValue is always in the dictionary ahead of this, or change to GetValueOrDefault() - switch (colorGroup) - { - case ColorGroup.Species: - colorPreset = _currentColorSpeciesPresetDictionary[evt.newValue]; - break; - case ColorGroup.Outfits: - colorPreset = _currentColorOutfitsPresetDictionary[evt.newValue]; - break; - case ColorGroup.Attachments: - colorPreset = _currentColorAttachmentsPresetDictionary[evt.newValue]; - break; - case ColorGroup.Materials: - colorPreset = _currentColorMaterialsPresetDictionary[evt.newValue]; - break;/* - case ColorGroup.Elements: - colorPreset = _currentColorElementsPresetDictionary[evt.newValue]; - break;*/ - } - - List presetColorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, colorPreset); - foreach (SidekickColorPresetRow row in presetColorRows) - { - SidekickColorRow existingRow = _allColorRows.Find(r => r.ColorProperty.ID == row.ColorProperty.ID); - if (existingRow == null) - { - existingRow = new SidekickColorRow() - { - ID = -1, - ColorSet = _currentColorSet, - ColorProperty = row.ColorProperty, - NiceColor = row.NiceColor, - NiceMetallic = row.NiceMetallic, - NiceSmoothness = row.NiceSmoothness, - NiceReflection = row.NiceReflection, - NiceEmission = row.NiceEmission, - NiceOpacity = row.NiceOpacity - }; - - _allColorRows.Add(existingRow); - } - else - { - existingRow.NiceColor = row.NiceColor; - existingRow.NiceMetallic = row.NiceMetallic; - existingRow.NiceSmoothness = row.NiceSmoothness; - existingRow.NiceReflection = row.NiceReflection; - existingRow.NiceEmission = row.NiceEmission; - existingRow.NiceOpacity = row.NiceOpacity; - } - - UpdateAllColors(existingRow); - } - - PopulatePartColorRows(); - RefreshVisibleColorRows(); - break; - case PresetDropdownType.Texture: - // TODO: Add texture setting functionality once decal system in place - break; - default: - throw new ArgumentOutOfRangeException(nameof(dropdownType), dropdownType, null); - } - } - ); - - removeButton.clickable.clicked += delegate - { - // TODO: Change to default character when available - partSelection.value = "None"; - }; - - previousButton.clickable.clicked += delegate - { - int newIndex = partSelection.index - 1; - if (newIndex <= 0) - { - newIndex = 0; - } - - partSelection.index = newIndex; - }; - - nextButton.clickable.clicked += delegate - { - int newIndex = partSelection.index + 1; - if (newIndex >= partSelection.choices.Count - 1) - { - newIndex = partSelection.choices.Count - 1; - } - - partSelection.index = newIndex; - }; - - randomButton.clickable.clicked += delegate - { - int currentIndex = partSelection.index; - if (partSelection.choices.Count - 1 > 1) - { - while (partSelection.index == currentIndex) - { - partSelection.index = Random.Range(1, partSelection.choices.Count); - } - } - }; - - partContainer.Add(partTypeTitle); - if (dropdownType == PresetDropdownType.Part) - { - partContainer.Add(removeButton); - } - partContainer.Add(previousButton); - partContainer.Add(nextButton); - partContainer.Add(randomButton); - partContainer.Add(partSelection); - view.Add(partContainer); - - partSelection.value = defaultValue; - - return partSelection; - } - - /// - /// Updates the required parts of the UI on a species change. - /// - /// The name of the species being changed to. - private void ProcessSpeciesChange(string newSpecies) - { - // don't need to re-process if multiple callbacks are triggered - if (_currentSpecies.Name == newSpecies) - { - return; - } - - _currentSpecies = _allSpecies.FirstOrDefault(species => species.Name == newSpecies); - _sidekickRuntime.CurrentSpecies = _currentSpecies; - UpdateVisibleColorSets(); - ResetCurrentColorSet(); - if (_allColorRows.Count == 0) - { - PopulateColorRowsFromTextures(); - } - - _appliedPartFilters.ResetFiltersForSpeciesChange(); - - _processingSpeciesChange = true; - UpdatePartDropdowns(); - PopulatePresetUI(); - _processingSpeciesChange = false; - } - - /// - /// Populates the parts UI. - /// - private void PopulatePartUI() - { - _partView.Clear(); - - _availablePartList = new List(); - _partSelectionDictionary = new Dictionary(); - _partLockMap = new Dictionary, bool>(); - - Foldout speciesFoldout = new Foldout - { - text = "Select - Species", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - List speciesNames = _allSpecies.Select(species => species.Name).ToList(); - - _speciesField = new DropdownField - { - label = "Species", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) - }, - tooltip = "Select the species of your character" - }; - _speciesField.choices = speciesNames; - _speciesField.RegisterValueChangedCallback( - evt => - { - _speciesPresetField.value = _speciesField.value; - ProcessSpeciesChange(evt.newValue); - } - ); - - _speciesField.index = _currentSpecies != null && speciesNames.Count > 0 ? _speciesField.choices.IndexOf(_currentSpecies.Name) : 0; - speciesFoldout.Add(_speciesField); - _partView.Add(speciesFoldout); - - _partsFoldout = new Foldout() - { - text = "Select - Parts", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - List outfitFilters = SidekickPartFilter.GetAllForFilterType(_dbManager, FilterType.Outfit); - List orderedFilters = new List(); - - outfitFilters.Sort( - (filterA, filterB) => String.CompareOrdinal(filterA.Term, filterB.Term) - ); - - orderedFilters.AddRange(outfitFilters); - - Foldout filterFoldout = new Foldout() - { - text = "Select - Outfit Filter", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - _appliedPartFilters = new FilterGroup() - { - Runtime = _sidekickRuntime, - CombineType = FilterCombineType.Or - }; - - VisualElement toggleList = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row), - flexWrap = new StyleEnum(Wrap.Wrap) - } - }; - - List allFilterToggles = new List(); - - Color borderColor = new Color(0.17f, 0.17f, 0.17f); - Color backgroundColor = new Color(0.35f, 0.35f, 0.35f); - - foreach (SidekickPartFilter filter in orderedFilters) - { - Toggle outfitToggle = new Toggle(filter.Term) - { - value = true, - style = - { - width = 160, - borderBottomWidth = 1, - borderBottomColor = borderColor, - paddingBottom = 2, - borderLeftWidth = 1, - borderLeftColor = borderColor, - paddingLeft = 2, - borderRightWidth = 1, - borderRightColor = borderColor, - paddingRight = 2, - borderTopWidth = 1, - borderTopColor = borderColor, - paddingTop = 2, - borderBottomLeftRadius = 3, - borderBottomRightRadius = 3, - borderTopLeftRadius = 3, - borderTopRightRadius = 3, - backgroundColor = backgroundColor, - textOverflow = new StyleEnum(TextOverflow.Ellipsis) - } - }; - - FilterItem filterItem = new FilterItem(_sidekickRuntime, filter, FilterCombineType.Or); - _appliedPartFilters.AddFilterItem(filterItem); - - outfitToggle.RegisterValueChangedCallback( - evt => - { - if (evt.newValue) - { - _appliedPartFilters.AddFilterItem(filterItem); - } - else - { - _appliedPartFilters.RemoveFilterItem(filterItem); - } - UpdatePartDropdowns(); - } - ); - - toggleList.Add(outfitToggle); - allFilterToggles.Add(outfitToggle); - } - - VisualElement buttonRow = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row) - } - }; - - Button selectAll = new Button( - delegate - { - foreach (Toggle toggle in allFilterToggles) - { - toggle.value = true; - } - } - ) - { - text = "Select All" - }; - - Button selectNone = new Button( - delegate - { - foreach (Toggle toggle in allFilterToggles) - { - toggle.value = false; - } - } - ) - { - text = "Select None" - }; - - buttonRow.Add(selectAll); - buttonRow.Add(selectNone); - - filterFoldout.Add(buttonRow); - filterFoldout.Add(toggleList); - - _partView.Add(filterFoldout); - - foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) - { - string labelText = StringUtils.AddSpacesBeforeCapitalLetters(partGroup.ToString()); - Foldout partGroupFoldout = new Foldout - { - text = labelText, - style = - { - marginLeft = 15, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - Button randomiseAllButton = new Button() - { - text = "Randomize " + labelText - }; - - partGroupFoldout.Add(randomiseAllButton); - - foreach (CharacterPartType value in partGroup.GetPartTypes()) - { - VisualElement partContainer = new VisualElement - { - style = - { - minHeight = 20, - display = DisplayStyle.Flex, - flexDirection = FlexDirection.Row, - marginBottom = 2, - marginTop = 2, - marginRight = 2, - unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) - } - }; - BuildPartDetails(value, partContainer); - partGroupFoldout.Add(partContainer); - } - - _partsFoldout.Add(partGroupFoldout); - - randomiseAllButton.clickable.clicked += delegate - { - foreach (CharacterPartType value in partGroup.GetPartTypes()) - { - PartTypeControls dropdown = _partSelectionDictionary[value]; - bool locked = _partLockMap[dropdown.PartDropdown]; - if (!locked) - { - if (dropdown.PartDropdown.choices.Count > 1) - { - dropdown.RandomisePartDropdownValue(); - } - else - { - dropdown.SetPartDropdownValue("None"); - } - } - } - }; - } - - UpdatePartDropdowns(); - - _partView.Add(_partsFoldout); - } - - /// - /// Builds the UI details for each different part type. - /// - /// The type of the part to build the UI for. - /// The container to add the UI to. - private void BuildPartDetails(CharacterPartType type, VisualElement partContainer) - { - List partsList = new List(); - - foreach (SidekickPart part in _allPartsLibrary[type]) - { - if (_availablePartList.Any(p => p.ID == part.ID)) - { - partsList.Add(part); - } - } - - Label partTypeTitle = new Label(type.ToString()) - { - style = - { - unityTextAlign = TextAnchor.MiddleLeft, - width = 150 - }, - tooltip = type.GetTooltipForPartType() - }; - - Image lockImage = new Image - { - image = EditorGUIUtility.IconContent("LockIcon", "|Lock Part").image, - scaleMode = ScaleMode.ScaleToFit, - style = - { - alignSelf = new StyleEnum(Align.Center), - width = 15, - height = 15, - paddingTop = 2 - } - }; - - Button lockButton = new Button() - { - tooltip = "Remove this part" - }; - - lockButton.Add( - lockImage - ); - - Button removeButton = new Button() - { - tooltip = "Remove this part" - }; - - removeButton.Add( - new Image - { - image = Resources.Load("UI/T_Clear"), - scaleMode = ScaleMode.ScaleToFit - } - ); - - Button previousButton = new Button() - { - tooltip = "Select the previous part" - }; - - previousButton.Add( - new Image - { - image = EditorGUIUtility.IconContent("tab_prev", "|Previous Part").image, - scaleMode = ScaleMode.ScaleToFit - } - ); - - Button nextButton = new Button() - { - tooltip = "Select the next part" - }; - - nextButton.Add( - new Image - { - image = EditorGUIUtility.IconContent("tab_next", "|Next Part").image, - scaleMode = ScaleMode.ScaleToFit - } - ); - - Button randomButton = new Button() - { - tooltip = "Randomly select a part" - }; - - Texture2D randomImage = Resources.Load("UI/T_Random"); - randomButton.Add( - new Image - { - image = randomImage, - scaleMode = ScaleMode.ScaleToFit, - style = - { - paddingTop = new StyleLength(1), - paddingBottom = new StyleLength(1) - } - } - ); - - List popupValues = new List(); - - if (type != CharacterPartType.Wrap) - { - popupValues.Add("None"); - } - - foreach (SidekickPart part in partsList) - { - SidekickPartSpeciesLink link = SidekickPartSpeciesLink.GetForSpeciesAndPart(_dbManager, _currentSpecies, part); - if (link != null) - { - popupValues.Add(part.Name); - } - } - - _currentCharacter.TryGetValue(type, out SidekickPart selectedPart); - string currentSelection = selectedPart?.Name ?? "None"; - if (_processingSpeciesChange) - { - if (popupValues.Count < 1 || (popupValues.Count == 1 && popupValues[0] == "None")) - { - _previousPartSelections[type] = currentSelection; - currentSelection = "None"; - } - else if (PartUtils.IsBaseSpeciesPart(currentSelection)) - { - _previousPartSelections[type] = currentSelection; - currentSelection = popupValues.Find(n => n.Contains("BASE")) ?? "None"; - } - else if (currentSelection == "None" && _previousPartSelections[type] != "None" && popupValues.Count > 1) - { - currentSelection = _previousPartSelections[type]; - _previousPartSelections[type] = "None"; - } - - if (!popupValues.Contains(currentSelection)) - { - _previousPartSelections[type] = currentSelection; - currentSelection = FindClosestPartMatch(popupValues, currentSelection); - } - } - - PopupField partSelection = new PopupField(popupValues, 0) - { - value = currentSelection - }; - - PartTypeControls controls = new PartTypeControls - { - PartType = type, - PartDropdown = partSelection, - ClearButton = removeButton, - NextButton = nextButton, - PreviousButton = previousButton, - RandomButton = randomButton - }; - - partSelection.RegisterCallback>( - changeEvent => - { - PartSelectionChangeEvent(changeEvent, type, controls); - } - ); - - _partLockMap[partSelection] = false; - - lockButton.clickable.clicked += delegate - { - bool newValue = !_partLockMap[partSelection]; - _partLockMap[partSelection] = newValue; - - if (newValue) - { - partSelection.SetEnabled(false); - removeButton.SetEnabled(false); - nextButton.SetEnabled(false); - previousButton.SetEnabled(false); - randomButton.SetEnabled(false); - lockImage.image = EditorGUIUtility.IconContent("LockIcon-On", "|Unlock Part").image; - lockButton.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f); - } - else - { - partSelection.SetEnabled(true); - removeButton.SetEnabled(true); - nextButton.SetEnabled(true); - previousButton.SetEnabled(true); - randomButton.SetEnabled(true); - PartSelectionChangeEvent(new ChangeEvent(), type, controls); - lockImage.image = EditorGUIUtility.IconContent("LockIcon", "|Lock Part").image; - lockButton.style.backgroundColor = new Color(0.345098f, 0.345098f, 0.345098f); - } - }; - - if (_processingSpeciesChange) - { - ChangeEvent changeEvent = ChangeEvent.GetPooled(_previousPartSelections[type], currentSelection); - PartSelectionChangeEvent(changeEvent, type, controls); - changeEvent.Dispose(); - } - - _partSelectionDictionary.Add(type, controls); - - removeButton.clickable.clicked += delegate - { - partSelection.value = "None"; - }; - - previousButton.clickable.clicked += delegate - { - int newIndex = partSelection.index - 1; - if (newIndex <= 0) - { - newIndex = 0; - } - - partSelection.index = newIndex; - }; - - nextButton.clickable.clicked += delegate - { - int newIndex = partSelection.index + 1; - if (newIndex >= partSelection.choices.Count - 1) - { - newIndex = partSelection.choices.Count - 1; - } - - partSelection.index = newIndex; - }; - - randomButton.clickable.clicked += delegate - { - int currentIndex = partSelection.index; - if (partSelection.choices.Count - 1 > 1) - { - while (partSelection.index == currentIndex) - { - partSelection.index = Random.Range(1, partSelection.choices.Count); - } - } - }; - - partContainer.Add(partTypeTitle); - partContainer.Add(lockButton); - partContainer.Add(removeButton); - partContainer.Add(previousButton); - partContainer.Add(nextButton); - partContainer.Add(randomButton); - partContainer.Add(partSelection); - } - - private void UpdatePartDropdowns() - { - Dictionary> filteredParts = _appliedPartFilters.GetFilteredParts(); - Dictionary> baseParts = _sidekickRuntime.MappedBasePartDictionary[_currentSpecies]; - - foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) - { - PartTypeControls controls = _partSelectionDictionary[type]; - HashSet popupItems = new HashSet(); - - if (type != CharacterPartType.Wrap) - { - popupItems.Add("None"); - }; - - HashSet itemList = baseParts.TryGetValue(type, out List items) ? items.ToHashSet() : new HashSet(); - popupItems.UnionWith(itemList); - itemList = filteredParts.TryGetValue(type, out List filteredItems) ? filteredItems.ToHashSet() : new HashSet(); - popupItems.UnionWith(itemList); - - List popupValues = popupItems.ToList(); - - _currentCharacter.TryGetValue(type, out SidekickPart selectedPart); - string currentSelection = selectedPart?.Name ?? "None"; - if (_processingSpeciesChange) - { - if (popupValues.Count < 1 || (popupValues.Count == 1 && popupValues[0] == "None")) - { - _previousPartSelections[type] = currentSelection; - currentSelection = "None"; - } - else if (PartUtils.IsBaseSpeciesPart(currentSelection)) - { - _previousPartSelections[type] = currentSelection; - currentSelection = popupValues.Find(n => n.Contains("BASE")) ?? "None"; - } - else if (currentSelection == "None" && _previousPartSelections[type] != "None" && popupValues.Count > 1) - { - currentSelection = _previousPartSelections[type]; - _previousPartSelections[type] = "None"; - } - - if (!popupValues.Contains(currentSelection)) - { - _previousPartSelections[type] = currentSelection; - currentSelection = FindClosestPartMatch(popupValues, currentSelection); - } - } - - if (type == CharacterPartType.Wrap && currentSelection == "None") - { - currentSelection = null; - } - - controls.UpdateDropdownValues(popupValues); - controls.SetPartDropdownValue(currentSelection); - controls.UpdateControls(); - } - } - - /// - /// Process the change event when a new part is selected. - /// - /// The change event to process. - /// The type of part that has been changed. - /// The UI PopupField the change event is happening for. - private void PartSelectionChangeEvent(ChangeEvent changeEvent, CharacterPartType type, PartTypeControls partSelection) - { - try - { - if (_currentTab == TabView.Parts - && _sidekickRuntime.MappedPartDictionary.ContainsKey(type) - && changeEvent.newValue != null - && _sidekickRuntime.MappedPartDictionary[type].TryGetValue(changeEvent.newValue, out SidekickPart selectedPart)) - { - - GameObject partModel = selectedPart.GetPartModel(); - SkinnedMeshRenderer selectedMesh = partModel.GetComponentInChildren(); - _partDictionary[type] = selectedMesh; - _currentCharacter[type] = selectedPart; - - if (!_processingSpeciesChange) - { - _previousPartSelections[type] = changeEvent.newValue; - } - - if (type == CharacterPartType.Torso) - { - _requiresWrap = selectedPart.UsesWrap; - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) - { - if (_requiresWrap) - { - wrapSelection.PartDropdown.SetEnabled(true); - wrapSelection.RandomisePartDropdownValue(); - ; - } - else - { - wrapSelection.PartDropdown.SetEnabled(false); - wrapSelection.SetPartDropdownValue(null); - } - } - } - } - else if (changeEvent.newValue == "None") - { - _currentCharacter.Remove(type); - _partDictionary.Remove(type); - if (!_processingSpeciesChange) - { - _previousPartSelections[type] = "None"; - } - - if (type == CharacterPartType.Torso) - { - if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) - { - wrapSelection.PartDropdown.SetEnabled(false); - wrapSelection.SetPartDropdownValue(null); - _currentCharacter.Remove(CharacterPartType.Wrap); - } - } - } - else - { - _partDictionary.Remove(type); - } - - if (!_applyingPreset && _previewToggle.value) - { - // if (_combineMeshes && _newModel != null) - // { - // DestroyImmediate(_newModel); - // } - - _newModel = GenerateCharacter(false, true); - bool switchAnimation = SetupAnimationControllers(); - - if (switchAnimation && (type == CharacterPartType.HandLeft || type == CharacterPartType.HandRight)) - { - SetState("InspectHands"); - } - - UpdatePartUVData(); - } - - partSelection.UpdateControls(); - } - catch (Exception ex) - { - EditorUtility.DisplayDialog("Failed loading part", "Failed to load the following part\n" + changeEvent.newValue, "OK"); - Debug.LogWarning(ex); - } - } - - /// - /// Selects the first match, with the highest number of matching terms from a list of parts. - /// - /// The list of parts. - /// The part to find the closest match for. - /// The part with the closest match to the given part. - private string FindClosestPartMatch(List availableParts, string existingPart) - { - string closestMatch = "None"; - List partSections = existingPart.Split("_").ToList(); - Dictionary matchCounts = new Dictionary(); - foreach (string section in partSections) - { - foreach (string part in availableParts) - { - if (part.Contains(section)) - { - if (matchCounts.TryGetValue(part, out int count)) - { - matchCounts[part] = count + 1; - } - else - { - matchCounts[part] = 1; - } - } - } - } - - int currentMax = 0; - - foreach (KeyValuePair match in matchCounts) - { - if (match.Value > currentMax) - { - closestMatch = match.Key; - currentMax = match.Value; - } - } - - return closestMatch; - } - - /// - /// Generates a character from the current selected parts. - /// - private GameObject GenerateCharacter(bool combineMesh, bool processBoneMovement) - { - List parts = new List(); - foreach (KeyValuePair entry in _currentCharacter) - { - if (entry.Value != null) - { - // Only apply wrap when required - if (entry.Key == CharacterPartType.Wrap && (!_requiresWrap || _bodyTypeBlendValue < 0)) - { - continue; - } - - GameObject partModel = entry.Value.GetPartModel(); - - if (partModel == null) - { - if (_showMissingPartsPopup) - { - EditorUtility.DisplayDialog( - "Error loading part", - "Unable to load part: " + entry.Value.Name + ".", - "Ok" - ); - } - continue; - } - - SkinnedMeshRenderer selectedMesh = partModel.GetComponentInChildren(); - if (selectedMesh != null) - { - parts.Add(selectedMesh); - } - } - } - - GameObject newModel = null; - try - { - newModel = _sidekickRuntime.CreateCharacter( _OUTPUT_MODEL_NAME, parts, combineMesh, processBoneMovement, _newModel); - _currentAnimator = null; - } - catch (Exception ex) - { - EditorUtility.DisplayDialog( - "Error creating character", - "Something went wrong when creating the character.\nPlease try again.", - "Ok" - ); - Debug.LogWarning(ex); - } - - return newModel; - } - - /// - /// Saves a character (Parts and Colors) out to a file which can be imported by the tool into any project. - /// - private void SaveCharacter() - { - try - { - SaveCharacter(null); - } - catch - { - Debug.LogWarning("Failed to save character. Please try again."); - } - } - - /// - /// Saves a character (Parts and Colors) out to a file which can be imported by the tool into any project to a given path. - /// - /// The path to save the character to. - private void SaveCharacter(string savePath) - { - bool showSuccessMessage = false; - - if (string.IsNullOrEmpty(savePath)) - { - savePath = ShowCharacterSaveDialog(); - showSuccessMessage = true; - } - - if (string.IsNullOrEmpty(savePath)) - { - // EditorUtility.DisplayDialog("Save Cancelled", "No save file selected. Saving cancelled.", "OK"); - return; - } - - string filename = Path.GetFileNameWithoutExtension(savePath); - SerializedCharacter savedCharacter = CreateSerializedCharacter(filename); - - Serializer serializer = new Serializer(); - - File.WriteAllBytes(savePath, Encoding.ASCII.GetBytes(serializer.Serialize(savedCharacter))); - if (showSuccessMessage) - { - EditorUtility.DisplayDialog("Save Successful", "Character successfully saved to " + Path.GetFileName(savePath), "OK"); - } - } - - /// - /// Crates a serialized character from the current tool selections. - /// - /// The name to store in the serialized character. - /// A SerializedCharacter from the selections in the tool. - private SerializedCharacter CreateSerializedCharacter(string characterName) - { - SerializedCharacter savedCharacter = new SerializedCharacter - { - Species = _currentSpecies.ID, - Name = characterName - }; - - List usedParts = new List(); - foreach (KeyValuePair entry in _currentCharacter) - { - // TODO: Update the part version to use actual version once the information is available. - usedParts.Add(new SerializedPart(entry.Value.Name, entry.Key, "1")); - } - - savedCharacter.Parts = usedParts; - SerializedColorSet savedSet = new SerializedColorSet(); - savedSet.PopulateFromSidekickColorSet(_currentColorSet, _currentSpecies); - savedCharacter.ColorSet = savedSet; - - savedCharacter.BlendShapes = new SerializedBlendShapeValues() - { - BodyTypeValue = _bodyTypeSlider.value, - BodySizeValue = _bodySizeSlider.value, - MuscleValue = _musclesSlider.value - }; - - List savedColorRows = new List(); - foreach (SidekickColorRow row in _allColorRows) - { - savedColorRows.Add(new SerializedColorRow(row)); - } - - savedCharacter.ColorRows = savedColorRows; - - return savedCharacter; - } - - /// - /// Loads a character (Parts and Colors) into the tool. - /// - private void LoadCharacter() - { - _loadingCharacter = true; - bool showAllColors = _showAllColourProperties; - _showAllColourProperties = true; - - string filePath = EditorUtility.OpenFilePanel("Load Character", "", "sk"); - if (string.IsNullOrEmpty(filePath)) - { - EditorUtility.DisplayDialog("No File Chosen", "No file was chosen to load.", "OK"); - return; - } - - _bodyPartsTab.value = true; - SwitchToTab(TabView.Parts); - - byte[] bytes = File.ReadAllBytes(filePath); - string data = Encoding.ASCII.GetString(bytes); - - Deserializer deserializer = new Deserializer(); - SerializedCharacter savedCharacter = deserializer.Deserialize(data); - - LoadSerializedCharacter(savedCharacter, showAllColors); - _loadingCharacter = false; - } - - /// - /// Loads a character into the tool from a serialized character. - /// - /// The serialized character to load. - /// Whether to show all colors or not. - private void LoadSerializedCharacter(SerializedCharacter serializedCharacter, bool showAllColors) - { - SidekickSpecies species = SidekickSpecies.GetByID(_dbManager, serializedCharacter.Species); - _speciesField.value = species.Name; - ProcessSpeciesChange(species.Name); - - bool hasErrors = false; - string errorMessage = "The following parts could not be found in your project:\n"; - foreach (CharacterPartType currentType in Enum.GetValues(typeof(CharacterPartType))) - { - PartTypeControls currentField = _partSelectionDictionary[currentType]; - SerializedPart part = serializedCharacter.Parts.FirstOrDefault(p => p.PartType == currentType); - SidekickPart skPart = SidekickPart.SearchForByName(_dbManager, part?.Name); - if (skPart != null) - { - UpdateResult result = UpdatePartDropdown(currentField, skPart.Name, errorMessage, hasErrors); - hasErrors = result.HasErrors; - errorMessage = result.ErrorMessage; - } - else - { - currentField.SetPartDropdownValue("None"); - } - } - - if (hasErrors) - { - EditorUtility.DisplayDialog( - "Assets Missing", - errorMessage, - "OK" - ); - } - - - LoadColorSet(serializedCharacter); - - if (serializedCharacter.BlendShapes != null) - { - LoadBlendShapes(serializedCharacter); - } - - _showAllColourProperties = showAllColors; - UpdateColorTabContent(); - - if (_combineMeshes && _newModel != null) - { - DestroyImmediate(_newModel); - } - - _newModel = GenerateCharacter(_combineMeshes, true); - UpdatePartUVData(); - } - - /// - /// Updates a part dropdown to select a new part, if the part is not in the dropdown values, `None` is selected instead. - /// - /// The dropdown field to update. - /// The new part to select. - /// The error message to update if the part is not available. - /// The error flag to update if an error is encountered. - /// A PartUpdateResult with the results of the update. - private UpdateResult UpdatePartDropdown(PartTypeControls currentField, string partName, string errorMessage, bool hasErrors) - { - _partLockMap[currentField.PartDropdown] = false; - - if (partName == "None" || _allParts.Any(part => part.Name == partName)) - { - if (!currentField.PartDropdown.choices.Contains(partName) && PartUtils.IsBaseSpeciesPart(partName)) - { - currentField.SetPartDropdownValue(currentField.PartDropdown.choices.Find(n => n.Contains("BASE")) ?? "None"); - if (currentField.PartDropdown.value == "None") - { - hasErrors = true; - errorMessage += partName + "\n"; - } - } - else - { - currentField.SetPartDropdownValue(partName); - } - } - else if (PartUtils.IsBaseSpeciesPart(partName)) - { - currentField.SetPartDropdownValue(currentField.PartDropdown.choices.Find(n => n.Contains("BASE")) ?? "None"); - if (currentField.PartDropdown.value == "None") - { - hasErrors = true; - errorMessage += partName + "\n"; - } - } - else - { - currentField.SetPartDropdownValue("None"); - hasErrors = true; - errorMessage += partName + "\n"; - } - - return new UpdateResult(errorMessage, hasErrors); - } - - /// - /// Loads the color set for a saved character into memory. - /// - /// The character to load the color set for. - private void LoadColorSet(SerializedCharacter savedCharacter) - { - _currentColorSet = savedCharacter.ColorSet.CreateSidekickColorSet(_dbManager); - _colorSetsDropdown.value = "Custom"; - - List newRows = new List(); - foreach (SerializedColorRow row in savedCharacter.ColorRows) - { - newRows.Add(row.CreateSidekickColorRow(_dbManager, _currentColorSet)); - } - - _allColorRows = newRows; - UpdateColorTabContent(); - } - - /// - /// Updates the content of the Color Tab. - /// - private void UpdateColorTabContent() - { - PopulatePartColorRows(); - UpdateAllVisibleColors(); - RefreshVisibleColorRows(); - } - - /// - /// Loads the blend shapes from a saved character into the tool. - /// - /// The character to load the blend shapes for. - private void LoadBlendShapes(SerializedCharacter savedCharacter) - { - _bodyTypeSlider.value = savedCharacter.BlendShapes.BodyTypeValue; - _bodySizeSlider.value = savedCharacter.BlendShapes.BodySizeValue; - _musclesSlider.value = savedCharacter.BlendShapes.MuscleValue; - } - - /// - /// Shows the dialog box for where to save the character to, and also validates the save location and filename. - /// - /// The default path to save to. - /// The full file path and filename to save the character to. - private string ShowCharacterSaveDialog(string path = "") - { - string defaultName = _currentSpecies.Name + "-" + _currentColorSet.Name + ".sk"; - string defaultDirectory = ""; - if (!string.IsNullOrEmpty(path)) - { - defaultName = Path.GetFileName(path); - defaultDirectory = Path.GetDirectoryName(path); - } - - string savePath = EditorUtility.SaveFilePanel( - "Save New Character", - defaultDirectory, - defaultName, - "sk" - ); - - // if (!string.IsNullOrEmpty(savePath) && File.Exists(savePath)) - // { - // int option = EditorUtility.DisplayDialogComplex( - // "File Already Exists", - // "A file already exists with the same name, are you sure you wish to overwrite it?\nThis cannot be undone.", - // "Overwrite", - // "Rename", - // "Cancel" - // ); - // - // switch (option) - // { - // // Overwrite. - // case 0: - // EditorUtility.DisplayDialog("Overwrite Accepted", "Existing file will be overwritten.", "OK"); - // break; - // - // // Rename. - // case 1: - // savePath = ShowCharacterSaveDialog(savePath); - // break; - // - // // Cancel. - // case 2: - // default: - // savePath = null; - // break; - // } - // } - - return savePath; - } - - /// - /// Saves a created character as a prefab. - /// - private void CreateCharacterPrefab() - { - try - { - string savePath = SelectPrefabSaveLocation(); - - if (string.IsNullOrEmpty(savePath)) - { - // EditorUtility.DisplayDialog("Save Cancelled", "No save file selected. Saving cancelled.", "OK"); - return; - } - - string baseFilename = Path.GetFileNameWithoutExtension(savePath); - string directoryBase = Path.GetDirectoryName(savePath) ?? string.Empty; - string directory = Path.Combine(directoryBase, baseFilename); - savePath = Path.Combine(directory, Path.GetFileName(savePath)); - string textureDirectory = Path.Combine(directory, "Textures"); - string meshDirectory = Path.Combine(directory, "Meshes"); - string materialDirectory = Path.Combine(directory, "Materials"); - - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - - if (!Directory.Exists(meshDirectory)) - { - Directory.CreateDirectory(meshDirectory); - } - - if (!Directory.Exists(materialDirectory)) - { - Directory.CreateDirectory(materialDirectory); - } - - string savedCharacterPath = Path.Combine(directory, baseFilename + ".sk"); - SaveCharacter(savedCharacterPath); - - //TODO textures are shared between exports! - SaveTexturesToDisk(textureDirectory, baseFilename); - // Ensure textures are written to disk before proceeding. As it seems this happens outside the main Unity loop, so can't be easily checked - // for. - int cutoff = 0; - while (cutoff < 1000000000 && Directory.GetFiles(textureDirectory).Length <= 0) - { - cutoff++; - } - - AssetDatabase.Refresh(); - - GameObject clonedModel = GenerateCharacter(_combineMeshes, false); - - List allRenderers = clonedModel.GetComponentsInChildren().ToList(); - SkinnedMeshRenderer clonedRenderer = allRenderers[0]; - - if (_bakeBlends) - { - - // Copy mesh, bone weights and bindposes before baking so the mesh can be re-skinned after baking. - foreach (SkinnedMeshRenderer renderer in allRenderers) - { - if (clonedRenderer == null) - { - clonedRenderer = renderer; - } - - Mesh clonedSkinnedMesh = MeshUtils.CopyMesh(renderer.sharedMesh); - BoneWeight[] boneWeights = clonedSkinnedMesh.boneWeights; - Matrix4x4[] bindposes = clonedSkinnedMesh.bindposes; - List blendData = BlendShapeUtils.GetBlendShapeData( - clonedSkinnedMesh, - renderer, - new string[] - { - "defaultHeavy", "defaultBuff", "defaultSkinny", "masculineFeminine" - }, - 0, - new List() - ); - renderer.BakeMesh(clonedSkinnedMesh); - // Re-skin the new baked mesh. - clonedSkinnedMesh.boneWeights = boneWeights; - clonedSkinnedMesh.bindposes = bindposes; - // assign the new mesh to the renderer - renderer.sharedMesh = clonedSkinnedMesh; - - BlendShapeUtils.RestoreBlendShapeData(blendData, clonedSkinnedMesh, renderer); - } - } - - // now do the bone movements! - _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); - _sidekickRuntime.ProcessBoneMovement(clonedModel); - - Material newMaterial = CreateNewMaterialAssetFromSource( - clonedRenderer.sharedMaterial, - textureDirectory, - materialDirectory, - baseFilename, - baseFilename - ); - - foreach (SkinnedMeshRenderer renderer in allRenderers) - { - renderer.sharedMaterial = newMaterial; - } - - CreatePrefab(clonedModel, meshDirectory, savePath, baseFilename); - DestroyImmediate(clonedModel); - } - catch - { - Debug.LogWarning("Failed to create character prefab, please try again."); - } - } - - /// - /// Prompts the user to select a path and prefab name within the project. - /// - /// The path and filename to use to save the prefab to. - private string SelectPrefabSaveLocation() - { - string defaultName = _currentSpecies.Name + "-" + _currentColorSet.Name + ".prefab"; - - string savePath = EditorUtility.SaveFilePanelInProject( - "Save Character Prefab", - defaultName, - "prefab", - "Select where to save the prefab" - ); - - return savePath; - } - - /// - /// Sets the material to use the textures at the given location. - /// - /// The material to set the textures on. - /// The path to set the textures from. - /// Additional naming for the textures, if applicable. - /// The material with the paths set on it. - private Material SetTextureLinkOnMaterial(Material material, string texturePath, string textureName = "") - { - string filename = _TEXTURE_PREFIX; - - if (!string.IsNullOrEmpty(textureName)) - { - filename += textureName; - } - - material.SetTexture(_COLOR_MAP, null); - LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_COLOR_NAME, _COLOR_MAP); - // TODO: Uncomment when the shader has the these properties are enabled again - // material.SetTexture(_METALLIC_MAP, null); - // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_METALLIC_NAME, _METALLIC_MAP); - // material.SetTexture(_SMOOTHNESS_MAP, null); - // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_SMOOTHNESS_NAME, _SMOOTHNESS_MAP); - // material.SetTexture(_REFLECTION_MAP, null); - // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_REFLECTION_NAME, _REFLECTION_MAP); - // material.SetTexture(_EMISSION_MAP, null); - // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_EMISSION_NAME, _EMISSION_MAP); - // material.SetTexture(_OPACITY_MAP, null); - // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_OPACITY_NAME, _OPACITY_MAP); - - return material; - } - - /// - /// Loads a texture from disk and assigns it to the material in the given texture ID. - /// - /// The material to assign the texture to. - /// The path to load the texture from. - /// The name of the texture to load. - /// The texture ID to load the texture into on the material. - private void LoadAndAssignTexture(Material material, string texturePath, string textureName, int textureID) - { - string filePath = Path.Combine(texturePath, textureName); - while (material.GetTexture(textureID) == null) - { - TextureImporter textureImporter = AssetImporter.GetAtPath(filePath) as TextureImporter; - if (textureImporter != null) - { - textureImporter.wrapMode = TextureWrapMode.Clamp; - textureImporter.filterMode = FilterMode.Point; - textureImporter.mipmapEnabled = false; - textureImporter.SetPlatformTextureSettings(new TextureImporterPlatformSettings - { - maxTextureSize = 32, - resizeAlgorithm = TextureResizeAlgorithm.Bilinear, - format = TextureImporterFormat.RGB24 - }); - EditorUtility.SetDirty(textureImporter); - textureImporter.SaveAndReimport(); - } - - material.SetTexture(textureID, (Texture2D) AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture2D))); - } - } - - /// - /// Creates a new material to assign to the prefab. - /// - /// The existing material from the base model. - /// The directory to save the textures into. - /// The directory to save the material into. - /// The base filename to use for all assets. - /// Additional naming for the textures, if applicable. - /// The new material cloned from sourceMaterial saved to the asset database. - private Material CreateNewMaterialAssetFromSource( - Material sourceMaterial, - string textureDirectory, - string materialDirectory, - string baseFilename, - string textureName = "" - ) - { - Material clonedMaterial = new Material(sourceMaterial.shader); - // NOTE: this is copying the texture slots from oldMaterial, so they need to be null'd afterward in SetTextureLinkOnMaterial() - clonedMaterial.CopyPropertiesFromMaterial(sourceMaterial); - clonedMaterial = SetTextureLinkOnMaterial(clonedMaterial, textureDirectory, textureName); - string materialPath = Path.Combine(materialDirectory, baseFilename + ".mat"); - // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. - if (File.Exists(materialPath)) - { - File.Delete(materialPath); - } - - AssetDatabase.CreateAsset(clonedMaterial, materialPath); - return clonedMaterial; - } - - /// - /// Creates a prefab and the required assets for the model to work as an independent asset. - /// - /// Root game object for the prefab. - /// The directory to save the mesh and avatar assets to. - /// The path to save the prefab to. - /// The base filename to use for all assets. - private void CreatePrefab( - GameObject rootGameObject, - string meshDirectory, - string savePath, - string baseFilename - ) - { - List renderers = rootGameObject.GetComponentsInChildren().ToList(); - foreach (SkinnedMeshRenderer renderer in renderers) - { - string type = null; - if (renderer.name.Contains("_")) - { - type = Enum.GetName(typeof(CharacterPartType), _sidekickRuntime.ExtractPartType(renderer.name)); - } - Mesh sharedMesh = renderer.sharedMesh; - string meshPath = type == null ? Path.Combine(meshDirectory, baseFilename + ".asset") : Path.Combine(meshDirectory, baseFilename + "-" + type + ".asset"); - // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. - if (File.Exists(meshPath)) - { - File.Delete(meshPath); - } - - AssetDatabase.CreateAsset(sharedMesh, meshPath); - } - - Animator animator = rootGameObject.GetComponentInChildren(); - Avatar existingAvatar = animator.avatar; - Avatar newAvatar = Instantiate(existingAvatar); - animator.avatar = newAvatar; - string avatarPath = Path.Combine(meshDirectory, baseFilename + "-avatar.asset"); - // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. - if (File.Exists(avatarPath)) - { - File.Delete(avatarPath); - } - - AssetDatabase.CreateAsset(newAvatar, avatarPath); - AssetDatabase.SaveAssets(); - PrefabUtility.SaveAsPrefabAsset(rootGameObject, savePath); - } - - /// - /// Gets the "outfit" name from the part name. - /// TODO: This will be replaced once parts and outfits have a proper relationship. - /// - /// The part name to parse the "outfit" name from. - /// The "outfit" name. - private string GetOutfitNameFromPartName(string partName) - { - if (string.IsNullOrEmpty(partName)) - { - return "None"; - } - - return string.Join('_', partName.Substring(3).Split('_').Take(2)); - } - - /// - /// Updates the part UV data. - /// - private void UpdatePartUVData() - { - _currentUVDictionary = _sidekickRuntime.CurrentUVDictionary; - _currentUVList = _sidekickRuntime.CurrentUVList; - } - - /// - /// The available tab views - /// - private enum TabView - { - Preset, - Parts, - Body, - Colors, - Decals, - Options - } - - /// - /// The different types of preset dropdown - /// - private enum PresetDropdownType - { - Part, - Body, - Color, - Texture - } - - /// - /// Encapsulates the result from a dropdown update attempt. - /// - private class UpdateResult - { - public string ErrorMessage { get; private set; } - public bool HasErrors { get; private set; } - - public UpdateResult(string errorMessage, bool hasErrors) - { - ErrorMessage = errorMessage; - HasErrors = hasErrors; - } - } - } -} -#endif +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +#if UNITY_EDITOR + +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using Synty.SidekickCharacters.Filters; +using Synty.SidekickCharacters.Serialization; +using Synty.SidekickCharacters.SkinnedMesh; +using Synty.SidekickCharacters.Synty.SidekickCharacters.Scripts.Editor.UI; +using Synty.SidekickCharacters.Utils; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Unity.VisualScripting.YamlDotNet.Serialization; +using UnityEditor; +using UnityEditor.Animations; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; +using Debug = UnityEngine.Debug; +using Object = UnityEngine.Object; +using Random = UnityEngine.Random; + +namespace Synty.SidekickCharacters +{ + public class ModularCharacterWindow : EditorWindow + { + private const string _AUTOSAVE_KEY = "SK_Autosave_character"; + private const string _AUTOSAVE_MISSING_PARTS = "SK_Autosave_missing_parts"; + private const string _AUTOSAVE_STATE = "SK_Autosave_state"; + private const string _BASE_COLOR_SET_NAME = "Species"; + private const string _BASE_COLOR_SET_PATH = "Assets/External/Models/SidekickCharacters/Resources/Species"; + private const string _BASE_MESH_NAME = "Meshes/SK_BaseModel"; + private const string _BASE_MATERIAL_NAME = "Materials/M_BaseMaterial"; + private const string _BLEND_GENDER_NAME = "masculineFeminine"; + private const string _BLEND_MUSCLE_NAME = "defaultBuff"; + private const string _BLEND_SHAPE_HEAVY_NAME = "defaultHeavy"; + private const string _BLEND_SHAPE_SKINNY_NAME = "defaultSkinny"; + private const string _AUTO_OPEN_STATE = "syntySkAutoOpenState"; + private const string _OUTPUT_MODEL_NAME = "Combined Character"; + private const string _PART_COUNT_BODY = " parts in library"; + private const string _TEXTURE_COLOR_NAME = "ColorMap.png"; + private const string _TEXTURE_METALLIC_NAME = "MetallicMap.png"; + private const string _TEXTURE_SMOOTHNESS_NAME = "SmoothnessMap.png"; + private const string _TEXTURE_REFLECTION_NAME = "ReflectionMap.png"; + private const string _TEXTURE_EMISSION_NAME = "EmissionMap.png"; + private const string _TEXTURE_OPACITY_NAME = "OpacityMap.png"; + private const string _TEXTURE_PREFIX = "T_"; + + private static readonly int _COLOR_MAP = Shader.PropertyToID("_ColorMap"); + private static readonly int _METALLIC_MAP = Shader.PropertyToID("_MetallicMap"); + private static readonly int _SMOOTHNESS_MAP = Shader.PropertyToID("_SmoothnessMap"); + private static readonly int _REFLECTION_MAP = Shader.PropertyToID("_ReflectionMap"); + private static readonly int _EMISSION_MAP = Shader.PropertyToID("_EmissionMap"); + private static readonly int _OPACITY_MAP = Shader.PropertyToID("_OpacityMap"); + private static Queue _callbackQueue = new Queue(); + private static bool _openWindowOnStart = true; + private readonly List _visibleColorRows = new List(); + + private List _allColorRows = new List(); + private List _allParts; + private List _allSpecies; + private ObjectField _animationField; + private FilterGroup _appliedPartFilters; + private bool _applyingPreset = false; + private List _availablePartList; + List _availablePresets; + private bool _bakeBlends = true; + private ObjectField _baseModelField; + private Dictionary _blendShapeRigMovement = new Dictionary(); + private Dictionary _blendShapeRigRotation = new Dictionary(); + private ToolbarToggle _bodyPartsTab; + private ToolbarToggle _bodyPresetTab; + private ToolbarToggle _bodyShapeTab; + private ScrollView _bodyShapeView; + private float _bodySizeHeavyBlendValue; + private float _bodySizeSkinnyBlendValue; + private Slider _bodySizeSlider; + private Slider _bodyTypeSlider; + private VisualElement _colorSelectionRowView; + private ToolbarToggle _colorSelectionTab; + private ScrollView _colorSelectionView; + private DropdownField _colorSetsDropdown; + private bool _combineMeshes = true; + private AnimatorController _currentAnimationController; + private Dictionary _currentBodyPresetDictionary = new Dictionary(); + private Dictionary _currentCharacter = new Dictionary(); + private Dictionary _currentColorSpeciesPresetDictionary = new Dictionary(); + private Dictionary _currentColorOutfitsPresetDictionary = new Dictionary(); + private Dictionary _currentColorAttachmentsPresetDictionary = new Dictionary(); + private Dictionary _currentColorMaterialsPresetDictionary = new Dictionary(); + private Dictionary _currentColorElementsPresetDictionary = new Dictionary(); + private SidekickColorSet _currentColorSet; + private bool _currentGlobalLockStatus; + private Material _currentMaterial; + private Dictionary _previousPartSelections; + private ColorPartType _currentPartType; + private Dictionary _currentHeadPresetDictionary = new Dictionary(); + private Dictionary _currentUpperBodyPresetDictionary = new Dictionary(); + private Dictionary _currentLowerBodyPresetDictionary = new Dictionary(); + private SidekickSpecies _currentSpecies; + private TabView _currentTab; + private Dictionary> _currentUVDictionary = new Dictionary>(); + private List _currentUVList = new List(); + private DatabaseManager _dbManager; + private string _dbPath; + private ToolbarToggle _decalSelectionTab; + private ScrollView _decalSelectionView; + private StyleSheet _editorStyle; + private bool _showAllColourProperties = false; + private float _bodyTypeBlendValue; + private bool _loadingCharacter = false; + private bool _loadingContent = true; + private Image _loadingImage; + private ObjectField _materialField; + private float _musclesBlendValue; + private Slider _musclesSlider; + private GameObject _newModel; + private VisualElement _newSetNameContainer; + private ScrollView _optionSelectionView; + private ToolbarToggle _optionTab; + private Label _partCountLabel; + private Dictionary _partDictionary; + private Dictionary> _partLibrary; + private Dictionary> _allPartsLibrary; + private Dictionary> _partOutfitMap; + private Dictionary, bool> _partLockMap; + private Dictionary _partSelectionDictionary; + private Foldout _partsFoldout; + private Dictionary> _partSpeciesMap; + private Dictionary _partPresetFilterToggleMap = new Dictionary(); + private ScrollView _partView; + private Dictionary _presetDefaultValues = new Dictionary(); + private VisualElement _presetPartContainer; + private ScrollView _presetView; + private Toggle _previewToggle; + private bool _processingSpeciesChange = false; + private bool _requiresWrap = false; + private VisualElement _root; + private bool _showMissingPartsPopup = false; + private SidekickRuntime _sidekickRuntime; + private DropdownField _speciesField; + private DropdownField _speciesPresetField; + private PlayModeStateChange _stateChange; + private bool _useAutoSaveAndLoad = false; + private List _visibleColorSets = new List(); + + // Animation variables + private Animator _currentAnimator; + private string _defaultStateName = "Idle"; + private float _defaultClipDurationFallback = 2f; + private float _blendDuration = 0.5f; // seconds + private List _otherStates = new List(); + private string _currentState; + private float _playbackTime; + private float _stateDuration = 1f; + private int _loopsRemaining = 0; + private bool _playingDefault = true; + private double _lastEditorTime; + private Transform[] _animatorBones; + private Dictionary _previousPosePos = new Dictionary(); + private Dictionary _previousPoseRot = new Dictionary(); + private float _blendElapsedTime = 0f; + private bool _blending = false; + + /// + private void Awake() + { + InitializeEditorWindow(); + } + + /// + private void OnDestroy() + { + if (_useAutoSaveAndLoad) + { + SerializedCharacter savedCharacter = CreateSerializedCharacter(_OUTPUT_MODEL_NAME); + Serializer serializer = new Serializer(); + string serializedCharacter = serializer.Serialize(savedCharacter); + EditorPrefs.SetString(_AUTOSAVE_KEY, serializedCharacter); + } + + // ensures we release the file lock on the database + _dbManager.CloseConnection(); + } + +#if UNITY_EDITOR + /// + private void OnEnable() + { + EditorApplication.playModeStateChanged += StateChange; + EditorApplication.update += AnimationUpdate; + } + + private void OnDisable() + { + EditorApplication.update -= AnimationUpdate; + } + + /// + private void Update() + { + if (_loadingContent) + { + Vector3 rotation = _loadingImage.transform.rotation.eulerAngles; + rotation += new Vector3(0, 0, 0.5f * Time.deltaTime); + _loadingImage.transform.rotation = Quaternion.Euler(rotation); + } + + while (_callbackQueue.Count > 0) + { + Action action = null; + lock (_callbackQueue) + { + if (_callbackQueue.Count > 0) + { + action = _callbackQueue.Dequeue(); + } + } + action?.Invoke(); + } + } + + /// + /// Sets up the animation controllers for playing during runtime. + /// + /// True if it is set up; otherwise false. + private bool SetupAnimationControllers() + { + _loopsRemaining = 0; + + _currentAnimator = _newModel.GetComponent(); + if (_currentAnimator != null) + { + _currentAnimationController = _currentAnimator.runtimeAnimatorController as AnimatorController; + _sidekickRuntime.CurrentAnimationController = _currentAnimationController; + } + else + { + return false; + } + + _animatorBones = _currentAnimator.GetComponentsInChildren(); + CollectOtherStates(); + + if (string.IsNullOrEmpty(_currentState)) + { + StartDefaultState(); + } + else + { + SetState(_currentState); + } + + _lastEditorTime = EditorApplication.timeSinceStartup; + return true; + } + + /// + /// Plays the animation during edit time. + /// + private void AnimationUpdate() + { + if (Application.isPlaying) + { + return; + } + + if (_animationField == null || _animationField.value == null) + { + return; + } + + if (_currentAnimator == null || _currentAnimationController == null) + { + if (!SetupAnimationControllers()) + { + return; + } + } + + double currentTime = EditorApplication.timeSinceStartup; + float deltaTime = (float)(currentTime - _lastEditorTime); + _lastEditorTime = currentTime; + + _playbackTime += deltaTime; + float normalizedTime = (_playbackTime % _stateDuration) / _stateDuration; + + _currentAnimator.Play(_currentState, 0, normalizedTime); + _currentAnimator.Update(0f); + + // Blend from previous pose (if blending) + if (_blending) + { + _blendElapsedTime += deltaTime; + float t = Mathf.Clamp01(_blendElapsedTime / _blendDuration); + + foreach (var bone in _animatorBones) + { + if (bone == null) + { + continue; + } + + if (_previousPosePos.TryGetValue(bone, out Vector3 prevPos)) + { + bone.localPosition = Vector3.Lerp(prevPos, bone.localPosition, t); + } + + if (_previousPoseRot.TryGetValue(bone, out Quaternion prevRot)) + { + bone.localRotation = Quaternion.Slerp(prevRot, bone.localRotation, t); + } + } + + if (t >= +_blendDuration) + { + _blending = false; + } + } + + SceneView.RepaintAll(); + + if (_playbackTime >= _stateDuration) + { + _playbackTime = 0f; + _loopsRemaining--; + + if (_loopsRemaining <= 0) + { + if (!_playingDefault) + { + StartDefaultState(); + } + else + { + _loopsRemaining = Int32.MaxValue; + } + } + } + } + + /// + /// Collect other states from the animation contoller. + /// + private void CollectOtherStates() + { + _otherStates.Clear(); + if (_currentAnimationController == null) + { + return; + } + + foreach (var layer in _currentAnimationController.layers) + { + foreach (var state in layer.stateMachine.states) + { + string stateName = state.state.name; + if (stateName != _defaultStateName) + { + _otherStates.Add(stateName); + } + } + } + } + + /// + /// + /// + private void StartDefaultState() + { + SetState(_defaultStateName); + } + + /// + /// Sets the state of the animation controller. + /// + /// The name of the state to set. + private void SetState(string stateName) + { + if (_currentAnimationController == null || _currentAnimator == null) + { + return; + } + + CacheCurrentPose(); + + _currentState = stateName; + _playbackTime = 0f; + _blendElapsedTime = 0f; + _blending = true; + _loopsRemaining = stateName == _defaultStateName ? Int32.MaxValue : 1; + _playingDefault = stateName == _defaultStateName; + + var sm = _currentAnimationController.layers[0].stateMachine; + foreach (var state in sm.states) + { + if (state.state.name == stateName && state.state.motion is AnimationClip clip) + { + _stateDuration = Mathf.Max(clip.length, 0.01f); + goto Found; + } + } + + _stateDuration = _defaultClipDurationFallback; + + Found: + _currentAnimator.Play(stateName, 0, 0f); + _currentAnimator.Update(0f); + } + + /// + /// Caches the current animation pose + /// + private void CacheCurrentPose() + { + _previousPosePos.Clear(); + _previousPoseRot.Clear(); + + foreach (var bone in _animatorBones) + { + if (bone == null) continue; + _previousPosePos[bone] = bone.localPosition; + _previousPoseRot[bone] = bone.localRotation; + } + } + + /// + /// Processes the callback from the play mode state change. + /// + /// The current PlayModeStateChange + private void StateChange(PlayModeStateChange stateChange) + { + if (_useAutoSaveAndLoad && stateChange == PlayModeStateChange.ExitingEditMode || _useAutoSaveAndLoad && stateChange == PlayModeStateChange.ExitingPlayMode) + { + SerializedCharacter savedCharacter = CreateSerializedCharacter(_OUTPUT_MODEL_NAME); + Serializer serializer = new Serializer(); + string serializedCharacter = serializer.Serialize(savedCharacter); + EditorPrefs.SetString(_AUTOSAVE_KEY, serializedCharacter); + } + + if (_useAutoSaveAndLoad && stateChange == PlayModeStateChange.EnteredEditMode || _useAutoSaveAndLoad && stateChange == PlayModeStateChange.EnteredPlayMode) + { + _stateChange = stateChange; + } + } +#endif + + /// + public async void CreateGUI() + { + _loadingContent = true; + InitializeEditorWindow(); + _root = rootVisualElement; + _root.Clear(); + if (_editorStyle != null) + { + _root.styleSheets.Add(_editorStyle); + } + + InitializeDatabase(); + // if we still can't connect, something's gone wrong, don't keep building the GUI + if (_dbManager?.GetCurrentDbConnection() == null) + { + return; + } + + // Maintains a linking to the model if the editor window is closed and re-opened. + _newModel = GameObject.Find(_OUTPUT_MODEL_NAME); + + _previousPartSelections = new Dictionary(); + foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) + { + _previousPartSelections.Add(type, "None"); + } + + _partCountLabel = new Label("") + { + style = + { + unityTextAlign = TextAnchor.MiddleLeft + } + }; + + Image bannerImage = new Image + { + image = (Texture2D) Resources.Load("UI/T_SidekickTitle"), + scaleMode = ScaleMode.ScaleToFit, + }; + VisualElement bannerLayout = new VisualElement + { + style = + { + backgroundColor = new Color(209f/256, 34f/256, 51f/256), + minHeight = 150, + paddingBottom = 5, + paddingTop = 5, + } + }; + bannerLayout.Add(bannerImage); + _root.Add(bannerLayout); + + _presetView = new ScrollView(ScrollViewMode.Vertical); + _partView = new ScrollView(ScrollViewMode.Vertical) + { + style = + { + display = DisplayStyle.None + } + }; + _bodyShapeView = new ScrollView(ScrollViewMode.Vertical) + { + style = + { + display = DisplayStyle.None + } + }; + + _colorSelectionView = new ScrollView(ScrollViewMode.Vertical) + { + style = + { + display = DisplayStyle.None + } + }; + + // TODO: Uncomment when Decals added to the system. + // _decalSelectionView = new ScrollView(ScrollViewMode.Vertical) + // { + // style = + // { + // display = DisplayStyle.None + // } + // }; + + _optionSelectionView = new ScrollView(ScrollViewMode.Vertical) + { + style = + { + display = DisplayStyle.None + } + }; + + // TODO: Replace this tabbed menu code with TabView when 2023 LTS in the minimum supported version. + Toolbar tabBar = new Toolbar + { + style = + { + width = Length.Percent(100) + } + }; + + _bodyPresetTab = new ToolbarToggle + { + text = "Presets", + tooltip = "Create a character using preset combinations of parts, body types and colors" + }; + + _bodyPartsTab = new ToolbarToggle + { + text = "Parts", + tooltip = "Edit individual character parts on your character" + }; + + _bodyShapeTab = new ToolbarToggle + { + text = "Body", + tooltip = "Edit the body type, size, musculature of your character" + }; + + _colorSelectionTab = new ToolbarToggle + { + text = "Colors", + tooltip = "Edit individual colors of your character" + }; + + // TODO: Uncomment when Decals added to the system. + // _decalSelectionTab = new ToolbarToggle + // { + // text = "Decals", + // tooltip = "Edit the decals applied to your character" + // }; + + _optionTab = new ToolbarToggle + { + text = "Options", + tooltip = "Change the options of the tool" + }; + + tabBar.Add(_bodyPresetTab); + tabBar.Add(_bodyPartsTab); + tabBar.Add(_bodyShapeTab); + tabBar.Add(_colorSelectionTab); + // TODO: Uncomment when Decals added to the system. + // tabBar.Add(_decalSelectionTab); + tabBar.Add(_optionTab); + _root.Add(tabBar); + + _bodyPresetTab.RegisterValueChangedCallback( + delegate + { + if (_currentTab != TabView.Preset && _bodyPresetTab.value) + { + SwitchToTab(TabView.Preset); + } + } + ); + + _bodyPartsTab.RegisterValueChangedCallback( + delegate + { + if (_currentTab != TabView.Parts && _bodyPartsTab.value) + { + SwitchToTab(TabView.Parts); + } + } + ); + + _bodyShapeTab.RegisterValueChangedCallback( + delegate + { + if (_currentTab != TabView.Body && _bodyShapeTab.value) + { + AddBodyShapeTabContent(_bodyShapeView); + SwitchToTab(TabView.Body); + } + } + ); + + _colorSelectionTab.RegisterValueChangedCallback( + delegate + { + if (_currentTab != TabView.Colors && _colorSelectionTab.value) + { + // always re-populate the color rows with the latest when switching tabs + if (_allColorRows.Count == 0) + { + PopulateColorRowsFromTextures(); + } + else + { + PopulatePartColorRows(); + RefreshVisibleColorRows(); + } + + SwitchToTab(TabView.Colors); + } + } + ); + + // TODO: Uncomment when Decals added to the system. + // _decalSelectionTab.RegisterValueChangedCallback( + // delegate + // { + // if (_currentTab != TabView.Decals && _decalSelectionTab.value) + // { + // SwitchToTab(TabView.Decals); + // } + // } + // ); + + _optionTab.RegisterValueChangedCallback( + delegate + { + if (_currentTab != TabView.Options && _optionTab.value) + { + SwitchToTab(TabView.Options); + } + // If currently on this tab, and button is toggled to "off", toggle back to "on" + else if (_currentTab == TabView.Options && !_optionTab.value) + { + _optionTab.value = true; + } + } + ); + + _root.Add(_presetView); + _root.Add(_partView); + _root.Add(_bodyShapeView); + _root.Add(_colorSelectionView); + // TODO: Uncomment when Decals added to the system. + // root.Add(_decalSelectionView); + _root.Add(_optionSelectionView); + + AddOptionsTabContent(_optionSelectionView); + + // set the default colour set (this will change on various input triggers, but we need it to not be null) + _currentColorSet = SidekickColorSet.GetDefault(_dbManager); + + _partDictionary = new Dictionary(); + _currentCharacter = new Dictionary(); + + _sidekickRuntime = new SidekickRuntime((GameObject) _baseModelField.value, (Material) _materialField.value, _currentAnimationController, _dbManager); + + Label loadingLabel = new Label + { + text = "Loading Content..", + style = + { + fontSize = 20, + unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), + marginTop = 20 + } + }; + + _presetView.Add(loadingLabel); + + _loadingImage = new Image + { + image = (Texture2D) Resources.Load("UI/T_LoadingCircle"), + scaleMode = ScaleMode.ScaleToFit, + style = + { + width = 28, + height = 28, + unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), + alignContent = new StyleEnum(Align.Center), + alignSelf = new StyleEnum(Align.Center) + } + }; + + _presetView.Add(_loadingImage); + + _bodyPresetTab.value = true; + SwitchToTab(TabView.Preset); + + VisualElement saveLoadButtons = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + width = Length.Percent(100), + alignContent = new StyleEnum(Align.FlexStart), + alignItems = new StyleEnum(Align.FlexStart), + flexWrap = new StyleEnum(Wrap.Wrap), + justifyContent = new StyleEnum(Justify.SpaceBetween), + minHeight = 30, + marginTop = 20 + } + }; + + _root.Add(saveLoadButtons); + + Button loadCharacterButton = new Button(LoadCharacter) + { + text = "Load Character", + style = + { + minHeight = 30, + width = Length.Percent(48) + } + }; + saveLoadButtons.Add(loadCharacterButton); + + Button saveCharacterButton = new Button(SaveCharacter) + { + text = "Save Character", + style = + { + minHeight = 30, + width = Length.Percent(48) + } + }; + + saveLoadButtons.Add(saveCharacterButton); + + Button createCharacterButton = new Button(CreateCharacterPrefab) + { + text = "Export Character as Prefab", + style = + { + minHeight = 50, + marginTop = 5 + } + }; + _root.Add(createCharacterButton); + + // Populate the data in an async process, if not already populated + try + { + await Task.Run( + async () => + { + await SidekickRuntime.PopulateToolData(_sidekickRuntime); + _callbackQueue.Enqueue(AddAllTabContent); + if (_useAutoSaveAndLoad && _stateChange == PlayModeStateChange.EnteredEditMode + || _useAutoSaveAndLoad && _stateChange == PlayModeStateChange.EnteredPlayMode) + { + _callbackQueue.Enqueue(ReloadCharacterFromStateChange); + } + } + ); + } + catch + { + Debug.LogWarning("Failed to load tool data. Please try again.\nPlease note that data loading may take some time."); + } + } + + /// + /// Reloads the character based on auto saved character + /// + private void ReloadCharacterFromStateChange() + { + if (_stateChange == PlayModeStateChange.EnteredEditMode) + { + GameObject existingModel = GameObject.Find(_OUTPUT_MODEL_NAME); + while (existingModel != null) + { + GameObject.DestroyImmediate(existingModel); + existingModel = GameObject.Find(_OUTPUT_MODEL_NAME); + } + } + + string serializedCharacterString = EditorPrefs.GetString(_AUTOSAVE_KEY, null); + + if (!string.IsNullOrEmpty(serializedCharacterString)) + { + Deserializer deserializer = new Deserializer(); + SerializedCharacter serializedCharacter = deserializer.Deserialize(serializedCharacterString); + LoadSerializedCharacter(serializedCharacter, _showAllColourProperties); + } + + _stateChange = PlayModeStateChange.ExitingEditMode; + } + + /// + /// Adds the UI content to all tabs (excluding Options tab as it is already populated) + /// + private void AddAllTabContent() + { + if (_sidekickRuntime.PartCount < 15) + { + if (EditorUtility.DisplayDialog( + "Unable to strat Sidekicks Tool", + "There are not enough Sidekicks parts currently in your project. The tool is unable to start without the requisite parts", + "Ok" + )) + { + Close(); + } + + } + else { + _allPartsLibrary = _sidekickRuntime.AllPartsLibrary; + _allParts = SidekickPart.GetAll(_dbManager); + + _allSpecies = SidekickSpecies.GetAll(_dbManager); + _currentSpecies = _allSpecies[0]; + _sidekickRuntime.CurrentSpecies = _currentSpecies; + + _partCountLabel.text = _sidekickRuntime.PartCount + _PART_COUNT_BODY; + _partOutfitMap = _sidekickRuntime.PartOutfitMap; + + AddBodyShapeTabContent(_bodyShapeView); + AddColorTabContent(_colorSelectionView); + // TODO: Uncomment when Decals added to the system. + // _decalSelectionView.Add(new Label("Decal selections will go here.")); + + UpdatePartUVData(); + + PopulatePartUI(); + PopulatePresetUI(); + + if (_currentSpecies == null) + { + _currentSpecies = _currentSpecies = _allSpecies.FirstOrDefault(species => species.Name == _speciesField.value); + } + + if (_useAutoSaveAndLoad) + { + string serializedCharacterString = EditorPrefs.GetString(_AUTOSAVE_KEY, null); + + if (!string.IsNullOrEmpty(serializedCharacterString)) + { + try + { + Deserializer deserializer = new Deserializer(); + SerializedCharacter serializedCharacter = deserializer.Deserialize(serializedCharacterString); + LoadSerializedCharacter(serializedCharacter, _showAllColourProperties); + } + catch (Exception ex) + { + EditorUtility.DisplayDialog( + "Something Went Wrong", + "Unable to load saved character.", + "OK" + ); + Debug.LogWarning(ex); + _useAutoSaveAndLoad = false; + EditorPrefs.SetBool(_AUTOSAVE_STATE, _useAutoSaveAndLoad); + } + } + } + _loadingContent = false; + + } + } + + /// + /// Initializes all the database setup, and provides the status label reference for users + /// + private void InitializeDatabase() + { + // TODO: always reinstantiate instead? + if (_dbManager != null) + { + return; + } + + _dbManager = new DatabaseManager(); + _dbManager.GetDbConnection(true); + } + + /// + /// Initializes the editor window. + /// + private void InitializeEditorWindow() + { + _editorStyle = Resources.Load("Styles/EditorStyles"); + _openWindowOnStart = EditorPrefs.GetBool(_AUTO_OPEN_STATE, true); + _useAutoSaveAndLoad = EditorPrefs.GetBool(_AUTOSAVE_STATE, false); + _showMissingPartsPopup = EditorPrefs.GetBool(_AUTOSAVE_MISSING_PARTS, false); + } + + /// + /// Adds the contents and change listeners for the body shape tab. + /// + /// The tabview to add the content to. + private void AddBodyShapeTabContent(ScrollView view) + { + view.Clear(); + + _bodyTypeSlider = new Slider("Body Type", -100, 100) + { + value = _bodyTypeBlendValue, + style = + { + maxWidth = new StyleLength(StyleKeyword.Auto) + }, + showInputField = true, + tooltip = "Blend the body type of the character between masculine and feminine" + }; + + VisualElement bodyTypeLabels = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + width = Length.Percent(100), + paddingLeft = 155 + } + }; + + Label labelMasculine = new Label("Masculine") + { + style = + { + position = new StyleEnum(Position.Absolute), + left = 155 + } + }; + bodyTypeLabels.Add(labelMasculine); + + Label labelFeminine = new Label("Feminine") + { + style = + { + position = new StyleEnum(Position.Absolute), + right = 58 + } + }; + bodyTypeLabels.Add(labelFeminine); + + _bodySizeSlider = new Slider("Body Size", -100, 100) + { + value = _bodySizeSkinnyBlendValue > 0 ? -_bodySizeSkinnyBlendValue : _bodySizeHeavyBlendValue, + style = + { + maxWidth = new StyleLength(StyleKeyword.Auto), + marginTop = 30 + }, + showInputField = true, + tooltip = "Blend the body size of the character between slim and heavy" + }; + + VisualElement bodySizeLabels = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + width = Length.Percent(100), + paddingLeft = 155 + } + }; + + Label labelSlim = new Label("Slim") + { + style = + { + position = new StyleEnum(Position.Absolute), + left = 155 + } + }; + bodySizeLabels.Add(labelSlim); + + Label labelHeavy = new Label("Heavy") + { + style = + { + position = new StyleEnum(Position.Absolute), + right = 58 + } + }; + bodySizeLabels.Add(labelHeavy); + + _musclesSlider = new Slider("Musculature", -100, 100) + { + value = _musclesBlendValue, + style = + { + maxWidth = new StyleLength(StyleKeyword.Auto), + marginTop = 30 + }, + showInputField = true, + tooltip = "Blend the musculature of the character between lean and muscular" + }; + + VisualElement muscleLabels = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + width = Length.Percent(100), + height = 20, + paddingLeft = 155 + } + }; + + Label labelLean = new Label("Lean") + { + style = + { + position = new StyleEnum(Position.Absolute), + left = 155 + } + }; + muscleLabels.Add(labelLean); + + Label labelBulk = new Label("Muscular") + { + style = + { + position = new StyleEnum(Position.Absolute), + right = 58 + } + }; + muscleLabels.Add(labelBulk); + + view.Add(_bodyTypeSlider); + view.Add(bodyTypeLabels); + view.Add(_bodySizeSlider); + view.Add(bodySizeLabels); + view.Add(_musclesSlider); + view.Add(muscleLabels); + + _bodyTypeSlider.RegisterValueChangedCallback( + evt => + { + _bodyTypeBlendValue = evt.newValue; + _sidekickRuntime.BodyTypeBlendValue = evt.newValue; + + string body = "None"; + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Torso, out PartTypeControls bodySelection)) + { + body = bodySelection.PartDropdown.value; + } + + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) + { + if (body != "None" && _requiresWrap && _bodyTypeBlendValue > 0) + { + wrapSelection.PartDropdown.SetEnabled(true); + wrapSelection.RandomisePartDropdownValue(); + } + else + { + wrapSelection.PartDropdown.SetEnabled(false); + wrapSelection.SetPartDropdownValue(null); + _currentCharacter.Remove(CharacterPartType.Wrap); + } + } + + if (_newModel == null) + { + _newModel = GenerateCharacter(false, true); + UpdatePartUVData(); + } + + _sidekickRuntime.UpdateBlendShapes(_newModel); + _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); + _sidekickRuntime.ProcessBoneMovement(_newModel); + } + ); + + _bodySizeSlider.RegisterValueChangedCallback( + evt => + { + float newValue = evt.newValue; + if (newValue > 0) + { + _bodySizeHeavyBlendValue = newValue; + _bodySizeSkinnyBlendValue = 0; + _sidekickRuntime.BodySizeHeavyBlendValue = newValue; + _sidekickRuntime.BodySizeSkinnyBlendValue = 0; + } + else if (newValue < 0) + { + _bodySizeHeavyBlendValue = 0; + _bodySizeSkinnyBlendValue = -newValue; + _sidekickRuntime.BodySizeHeavyBlendValue = 0; + _sidekickRuntime.BodySizeSkinnyBlendValue = -newValue; + } + else + { + _bodySizeHeavyBlendValue = 0; + _bodySizeSkinnyBlendValue = 0; + _sidekickRuntime.BodySizeHeavyBlendValue = 0; + _sidekickRuntime.BodySizeSkinnyBlendValue = 0; + } + + if (_newModel == null) + { + _newModel = GenerateCharacter(false, true); + UpdatePartUVData(); + } + + _sidekickRuntime.UpdateBlendShapes(_newModel); + _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); + _sidekickRuntime.ProcessBoneMovement(_newModel); + } + ); + + _musclesSlider.RegisterValueChangedCallback( + evt => + { + _musclesBlendValue = evt.newValue; + _sidekickRuntime.MusclesBlendValue = evt.newValue; + + if (_newModel == null) + { + _newModel = GenerateCharacter(false, true); + UpdatePartUVData(); + } + + _sidekickRuntime.UpdateBlendShapes(_newModel); + _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); + _sidekickRuntime.ProcessBoneMovement(_newModel); + } + ); + } + + /// + /// Adds the content to the Color tab. + /// + /// The view to add the content to. + private void AddColorTabContent(ScrollView view) + { + _colorSetsDropdown = new DropdownField + { + style = + { + maxWidth = Length.Percent(65) + } + }; + + Label filterPartsLabel = new Label("Filter - Parts") + { + tooltip = "Filter the displayed colors to focus on specific areas of the character and reduce the number of properties" + }; + view.Add(filterPartsLabel); + DropdownField partTypeDropdown = new DropdownField(); + string[] colorPartTypes = Enum.GetNames(typeof(ColorPartType)); + // Enum names can't have spaces so we add in the space manually for display. + for (int i = 0; i < colorPartTypes.Length; i++) + { + colorPartTypes[i] = StringUtils.AddSpacesBeforeCapitalLetters(colorPartTypes[i]); + } + + partTypeDropdown.choices = colorPartTypes.ToList(); + partTypeDropdown.value = colorPartTypes[0]; + view.Add(partTypeDropdown); + + partTypeDropdown.RegisterValueChangedCallback( + (evt) => + { + if (Enum.TryParse(typeof(ColorPartType), evt.newValue.Replace(" ", ""), out object newType)) + { + _currentPartType = (ColorPartType) newType; + _colorSetsDropdown.value = "Custom"; + } + + PopulatePartColorRows(); + RefreshVisibleColorRows(); + } + ); + + _currentPartType = ColorPartType.AllParts; + + // TODO: Hidden due to early access, enable when feature complete + // Label colorSetsLabel = new Label("Color Sets"); + // view.Add(colorSetsLabel); + // + // VisualElement colorSetsRow = new VisualElement + // { + // style = + // { + // flexDirection = new StyleEnum(FlexDirection.Row), + // width = Length.Percent(100), + // alignContent = new StyleEnum(Align.FlexStart), + // alignItems = new StyleEnum(Align.FlexStart), + // flexWrap = new StyleEnum(Wrap.Wrap), + // justifyContent = new StyleEnum(Justify.SpaceBetween), + // marginBottom = 10 + // } + // }; + + UpdateVisibleColorSets(); + + // TODO: Hidden due to early access, enable when feature complete + // colorSetsRow.Add(_colorSetsDropdown); + // + // _colorSetsDropdown.RegisterValueChangedCallback( + // evt => + // { + // if (evt.newValue != "Custom") + // { + // SidekickColorSet newSet = _visibleColorSets.First(set => set.Name == evt.newValue); + // List newRows = SidekickColorRow.GetAllBySet(_dbManager, newSet); + // if (_currentPartType == ColorPartType.AllParts && _allColorRows.All(row => row.IsLocked == false)) + // { + // _currentColorSet = newSet; + // _allColorRows = newRows; + // if (_allColorRows.Count == 0) + // { + // PopulateColorRowsFromTextures(); + // } + // else + // { + // PopulatePartColorRows(); + // RefreshVisibleColorRows(); + // } + // } + // else + // { + // foreach (SidekickColorRow row in _visibleColorRows) + // { + // SidekickColorRow newRow = newRows.FirstOrDefault(r => r.ColorProperty.ID == row.ColorProperty.ID); + // if (newRow != null) + // { + // row.NiceColor = newRow.NiceColor; + // row.NiceMetallic = newRow.NiceMetallic; + // row.NiceSmoothness = newRow.NiceSmoothness; + // row.NiceReflection = newRow.NiceReflection; + // row.NiceEmission = newRow.NiceEmission; + // row.NiceOpacity = newRow.NiceOpacity; + // } + // } + // + // RefreshVisibleColorRows(); + // } + // + // UpdateAllVisibleColors(); + // } + // } + // ); + // + // Button previousSetButton = new Button( + // () => + // { + // if (_colorSetsDropdown.index > 0) + // { + // _colorSetsDropdown.index -= 1; + // } + // } + // ) + // { + // tooltip = "Previous Color Set" + // }; + // + // previousSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("tab_prev", "|Previous Color Set").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(previousSetButton); + // Button nextSetButton = new Button( + // () => + // { + // if (_colorSetsDropdown.index < _colorSetsDropdown.choices.Count - 1) + // { + // _colorSetsDropdown.index += 1; + // } + // } + // ) + // { + // tooltip = "Next Color Set" + // }; + // + // nextSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("tab_next", "|Next Color Set").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(nextSetButton); + // Button resetSetButton = new Button(ResetColorSet) + // { + // tooltip = "Reset Color Set from Disk" + // }; + // resetSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("Refresh", "|Reset Color Set From Disk").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(resetSetButton); + // Button newSetButton = new Button(ShowCreateNewColorSet) + // { + // tooltip = "Create New Color Set" + // }; + // newSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("Toolbar Plus", "|Create New Color Set").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(newSetButton); + // Button deleteSetButton = new Button(DeleteColorSet) + // { + // tooltip = "Delete Color Set" + // }; + // deleteSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("close", "|Delete Color Set").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(deleteSetButton); + // Button saveSetButton = new Button(SaveColorSet) + // { + // tooltip = "Save Color Set" + // }; + // saveSetButton.Add( + // new Image + // { + // image = EditorGUIUtility.IconContent("SaveAs", "|Save Color Set").image, + // scaleMode = ScaleMode.ScaleToFit + // } + // ); + // + // colorSetsRow.Add(saveSetButton); + // view.Add(colorSetsRow); + // + // _newSetNameContainer = new VisualElement + // { + // style = + // { + // flexDirection = new StyleEnum(FlexDirection.Row), + // width = Length.Percent(100), + // alignContent = new StyleEnum(Align.FlexStart), + // alignItems = new StyleEnum(Align.FlexStart), + // flexWrap = new StyleEnum(Wrap.Wrap), + // marginBottom = 10, + // display = DisplayStyle.None + // } + // }; + // + // TextField newNameField = new TextField("New Set Name") + // { + // style = + // { + // minWidth = Length.Percent(70) + // } + // }; + // _newSetNameContainer.Add(newNameField); + // + // Button newSetCreateButton = new Button( + // () => + // { + // CreateNewColorSet(newNameField.value); + // List choices = _colorSetsDropdown.choices; + // choices.Add(newNameField.value); + // _colorSetsDropdown.choices = choices; + // _colorSetsDropdown.value = newNameField.value; + // _newSetNameContainer.style.display = DisplayStyle.None; + // } + // ) + // { + // text = "Create Set" + // }; + // + // newNameField.RegisterValueChangedCallback( + // evt => + // { + // newSetCreateButton.SetEnabled(!SidekickColorSet.DoesNameExist(_dbManager, evt.newValue)); + // } + // ); + // + // _newSetNameContainer.Add(newSetCreateButton); + // view.Add(_newSetNameContainer); + // + // VisualElement allRow = new VisualElement(); + // allRow.AddToClassList("colorSelectionRow"); + // + // Label allItemsLabel = new Label("All"); + // allItemsLabel.AddToClassList("colorSelectionRowLabel"); + // allRow.Add(allItemsLabel); + // + // VisualElement allRowContent = new VisualElement(); + // allRowContent.AddToClassList("colorSelectionRowContent"); + // allRow.Add(allRowContent); + // + // Button btnAllLock = new Button + // { + // style = + // { + // left = 0 + // } + // }; + // allRowContent.Add(btnAllLock); + // Image lockButtonImage = new Image + // { + // image = _currentGlobalLockStatus + // ? EditorGUIUtility.IconContent("Locked").image + // : EditorGUIUtility.IconContent("Unlocked").image, + // scaleMode = ScaleMode.ScaleToFit + // }; + // + // btnAllLock.Add(lockButtonImage); + // + // btnAllLock.clickable.clicked += () => + // { + // foreach (SidekickColorRow colorRow in _visibleColorRows) + // { + // colorRow.IsLocked = !_currentGlobalLockStatus; + // if (colorRow.ButtonImage != null) + // { + // colorRow.ButtonImage.image = + // colorRow.IsLocked + // ? EditorGUIUtility.IconContent("Locked").image + // : EditorGUIUtility.IconContent("Unlocked").image; + // } + // } + // + // _currentGlobalLockStatus = !_currentGlobalLockStatus; + // lockButtonImage.image = _currentGlobalLockStatus + // ? EditorGUIUtility.IconContent("Locked").image + // : EditorGUIUtility.IconContent("Unlocked").image; + // }; + // + // TODO: Uncomment once all colors options are re-enabled + // Button randomAllButton = new Button + // { + // text = "R", + // style = + // { + // right = 0 + // } + // }; + // allRowContent.Add(randomAllButton); + // + // view.Add(allRow); + + _colorSelectionRowView = new VisualElement + { + style = + { + width = Length.Percent(100) + } + }; + + view.Add(_colorSelectionRowView); + + UpdateColorTabContent(); + } + + /// + /// Adds the content to the options tab. + /// + /// The view to add the content to. + private void AddOptionsTabContent(VisualElement view) + { + Label baseAssetLabel = new Label + { + style = + { + marginTop = 5, + marginLeft = 12, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + text = "Base Assets", + tooltip = "These assets are used to construct the character" + }; + + view.Add(baseAssetLabel); + + _baseModelField = new ObjectField + { + style = + { + marginLeft = 15, + marginRight = 15 + }, + tooltip = "The rigged character model used when constructing a character", + objectType = typeof(GameObject), + label = "Model" + }; + + _baseModelField.RegisterCallback>( + changeEvent => + { + // TODO: Check the model has a minimum of 1 SkinnedMeshRenderer as a child. + } + ); + view.Add(_baseModelField); + + _baseModelField.value = Resources.Load(_BASE_MESH_NAME); + + _materialField = new ObjectField + { + tooltip = "The material used when constructing a character", + objectType = typeof(Material), + label = "Material", + style = + { + marginLeft = 15, + marginRight = 15 + } + }; + + view.Add(_materialField); + + _materialField.value = Resources.Load(_BASE_MATERIAL_NAME); + + _animationField = new ObjectField + { + tooltip = "The animation controller applied when constructing a character", + objectType = typeof(AnimatorController), + label = "Animation Controller", + value = _currentAnimationController, + style = + { + marginLeft = 15, + marginRight = 15 + } + }; + + view.Add(_animationField); + + _animationField.RegisterValueChangedCallback( + evt => + { + _currentAnimationController = (AnimatorController) evt.newValue; + _sidekickRuntime.CurrentAnimationController = _currentAnimationController; + } + ); + + VisualElement updateLibraryLayout = new VisualElement + { + style = + { + minHeight = 20, + display = DisplayStyle.Flex, + flexDirection = FlexDirection.Row, + marginBottom = 2, + marginTop = 10, + marginLeft = 15, + marginRight = 2 + } + }; + + Button uploadLibraryButton = new Button() + { + text = "Update Part Library", + tooltip = "Re-scans the project folders to update the parts list" + }; + + uploadLibraryButton.clickable.clicked += async delegate + { + CreateGUI(); + await Task.Run( + async () => + { + await SidekickRuntime.PopulateToolData(_sidekickRuntime); + _callbackQueue.Enqueue(AddAllTabContent); + } + ); + + }; + + updateLibraryLayout.Add(uploadLibraryButton); + updateLibraryLayout.Add(_partCountLabel); + view.Add(updateLibraryLayout); + + Label prefabOptions = new Label + { + style = + { + marginTop = 5, + marginLeft = 12, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + text = "Prefab Options", + tooltip = "Options for how prefabs are created" + }; + + view.Add(prefabOptions); + + Toggle combineToggle = new Toggle("Combine Character Meshes") + { + value = _combineMeshes, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Whether or not to bake all the meshes down to a single mesh in the output model." + }; + + combineToggle.RegisterValueChangedCallback( + evt => + { + _combineMeshes = evt.newValue; + } + ); + + view.Add(combineToggle); + + Toggle bakeBlendsToggle = new Toggle("Combine Body Blend Shapes") + { + value = _bakeBlends, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Whether or not to bake the body blend shapes into the mesh in the output model." + }; + + bakeBlendsToggle.RegisterValueChangedCallback( + evt => + { + _bakeBlends = evt.newValue; + } + ); + + view.Add(bakeBlendsToggle); + + Label toolOptions = new Label + { + style = + { + marginTop = 5, + marginLeft = 12, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + text = "Tool Options", + tooltip = "Options for how the tool behaves" + }; + + view.Add(toolOptions); + + _previewToggle = new Toggle("Auto Build Model") + { + value = true, + style = + { + marginTop = 10, + marginLeft = 15 + } + }; + + //view.Add(_previewToggle); + + Toggle filterColorsToggle = new Toggle("Show all color properties") + { + value = _showAllColourProperties, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Display all color properties in the color tab rather than limited to only what the current character is using" + }; + + filterColorsToggle.RegisterValueChangedCallback( + evt => + { + _showAllColourProperties = evt.newValue; + UpdateVisibleColorSets(); + UpdateColorTabContent(); + } + ); + + view.Add(filterColorsToggle); + + Toggle autoOpenToggle = new Toggle("Open tool on startup") + { + value = _openWindowOnStart, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Opens the Sidekick character tool on Unity startup" + }; + + autoOpenToggle.RegisterValueChangedCallback( + evt => + { + _openWindowOnStart = evt.newValue; + EditorPrefs.SetBool(_AUTO_OPEN_STATE, _openWindowOnStart); + } + ); + + view.Add(autoOpenToggle); + + Toggle autoSaveToggle = new Toggle("Remember character") + { + value = _useAutoSaveAndLoad, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Auto saves and loads character on run/stop and unity or tool open and close." + }; + + autoSaveToggle.RegisterValueChangedCallback( + evt => + { + _useAutoSaveAndLoad = evt.newValue; + EditorPrefs.SetBool(_AUTOSAVE_STATE, _useAutoSaveAndLoad); + } + ); + + view.Add(autoSaveToggle); + + // TODO: Change to showing presets when parts are missing + Toggle showMissingParts = new Toggle("Show missing parts warning") + { + value = _showMissingPartsPopup, + style = + { + marginTop = 10, + marginLeft = 15 + }, + tooltip = "Shows a popup for missing parts when selecting a preset." + }; + + showMissingParts.RegisterValueChangedCallback( + evt => + { + _showMissingPartsPopup = evt.newValue; + EditorPrefs.SetBool(_AUTOSAVE_MISSING_PARTS, _showMissingPartsPopup); + } + ); + + view.Add(showMissingParts); + + VisualElement row = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + alignContent = new StyleEnum(Align.Center), + justifyContent = new StyleEnum(Justify.SpaceAround), + marginTop = 30 + } + }; + + Button documentationButton = new Button + { + text = "Documentation", + style = + { + width = Length.Percent(30) + }, + tooltip = "Open documentation for Sidekick characters" + }; + + documentationButton.clickable.clicked += delegate + { + Application.OpenURL("file:Assets/Synty/SidekickCharacters/Documentation/SidekickCharacters_UserGuide.pdf"); + }; + + Button storeButton = new Button + { + text = "Synty Store", + style = + { + width = Length.Percent(30) + }, + tooltip = "www.syntystore.com" + }; + + storeButton.clickable.clicked += delegate + { + Application.OpenURL("https://syntystore.com"); + }; + + Button tutorialButton = new Button + { + text = "Tutorials", + style = + { + width = Length.Percent(30) + }, + tooltip = "Sidekick Characters - Quick start guide" + }; + + tutorialButton.clickable.clicked += delegate + { + // TODO: Change to direct link to tutorial playlist, when available + Application.OpenURL("https://www.youtube.com/@syntystudios"); + }; + + row.Add(documentationButton); + row.Add(storeButton); + row.Add(tutorialButton); + view.Add(row); + } + + /// + /// Reset the color rows for this color set back to the colors stored on the saved textures. + /// + private void ResetColorSet() + { + PopulateColorRowsFromTextures(); + } + + /// + /// Shows the name field and creation button for creating a new color set. + /// + private void ShowCreateNewColorSet() + { + _newSetNameContainer.style.display = DisplayStyle.Flex; + } + + /// + /// Creates a new color set with the given name. + /// + /// The name for the color set. + private void CreateNewColorSet(string setName) + { + ResetCurrentColorSet(setName); + SaveColorSet(); + } + + /// + /// Sets the current color set to a new, in-memory set of rows independent of the database + /// + /// Name of the new color set + private void ResetCurrentColorSet(string setName = "Custom") + { + _currentColorSet.ID = -1; + _currentColorSet.Species = _currentSpecies; + _currentColorSet.Name = setName; + + foreach (SidekickColorRow row in _allColorRows) + { + row.ID = -1; + row.ColorSet = _currentColorSet; + } + } + + /// + /// Deletes a color set from the database. The color set will still be available in the app until the app is closed. + /// + private void DeleteColorSet() + { + List rowsToDelete = SidekickColorRow.GetAllBySet(_dbManager, _currentColorSet); + foreach (SidekickColorRow row in rowsToDelete) + { + row.Delete(_dbManager); + } + + _currentColorSet.Delete(_dbManager); + UpdateVisibleColorSets(); + ResetCurrentColorSet(); + + } + + /// + /// Saves the current color row to the database. If it is a new color row, it is inserted into the DB; otherwise it is updated in the DB. + /// + private void SaveColorSet() + { + string path = Path.Combine(_BASE_COLOR_SET_PATH, _currentSpecies.Name); + path = Path.Combine(path, _currentColorSet.Name.Replace(" ", "_")); + + SaveTexturesToDisk(path); + + _currentColorSet.Save(_dbManager); + foreach (SidekickColorRow row in _allColorRows) + { + row.Save(_dbManager); + } + + UpdateVisibleColorSets(false); + + // TODO : refresh the project inspector window so the new textures show up + } + + /// + /// Saves texture files to disk at the given path. + /// + /// The path to save the textures to. + private void SaveTexturesToDisk(string path, string additionalNaming = "") + { + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + // if no parts are selected, don't try and save a non-existent material, instead create one + if (_currentMaterial == null) + { + _currentMaterial = (Material) _materialField.value; + } + + string filename = _TEXTURE_PREFIX; + + if (!string.IsNullOrEmpty(additionalNaming)) + { + filename += additionalNaming; + } + + string filePath = Path.Combine(path, filename + _TEXTURE_COLOR_NAME); + Texture2D texture = (Texture2D) _currentMaterial.GetTexture(_COLOR_MAP); + File.WriteAllBytes(filePath, texture.EncodeToPNG()); + _currentColorSet.SourceColorPath = filePath; + // TODO: Hidden due to early access, enable when feature complete + // filePath = Path.Combine(path, filename + _TEXTURE_METALLIC_NAME); + // texture = (Texture2D) _currentMaterial.GetTexture(_METALLIC_MAP); + // File.WriteAllBytes(filePath, texture.EncodeToPNG()); + // _currentColorSet.SourceMetallicPath = filePath; + // filePath = Path.Combine(path, filename + _TEXTURE_SMOOTHNESS_NAME); + // texture = (Texture2D) _currentMaterial.GetTexture(_SMOOTHNESS_MAP); + // File.WriteAllBytes(filePath, texture.EncodeToPNG()); + // _currentColorSet.SourceSmoothnessPath = filePath; + // filePath = Path.Combine(path, filename + _TEXTURE_REFLECTION_NAME); + // texture = (Texture2D) _currentMaterial.GetTexture(_REFLECTION_MAP); + // File.WriteAllBytes(filePath, texture.EncodeToPNG()); + // _currentColorSet.SourceReflectionPath = filePath; + // filePath = Path.Combine(path, filename + _TEXTURE_EMISSION_NAME); + // texture = (Texture2D) _currentMaterial.GetTexture(_EMISSION_MAP); + // File.WriteAllBytes(filePath, texture.EncodeToPNG()); + // _currentColorSet.SourceEmissionPath = filePath; + // filePath = Path.Combine(path, filename + _TEXTURE_OPACITY_NAME); + // texture = (Texture2D) _currentMaterial.GetTexture(_OPACITY_MAP); + // File.WriteAllBytes(filePath, texture.EncodeToPNG()); + // _currentColorSet.SourceOpacityPath = filePath; + } + + /// + /// Updates the color sets that are selectable in the dropdown on the colors tab + /// + /// Whether to set the color sets dropdown value to 'Custom' + private void UpdateVisibleColorSets(bool setDropdownToCustom = true) + { + List sets = SidekickColorSet.GetAllBySpecies(_dbManager, _currentSpecies); + if (sets.Count == 0) + { + sets.Add(SidekickColorSet.GetDefault(_dbManager)); + } + + List setNames = sets.Select(set => set.Name).ToList(); + _colorSetsDropdown.choices = setNames; + _visibleColorSets = sets; + + if (setDropdownToCustom) + { + _colorSetsDropdown.value = "Custom"; + } + } + + /// + /// Updates all the color rows currently visible in the UI. + /// + private void UpdateAllVisibleColors() + { + foreach (SidekickColorRow row in _visibleColorRows) + { + UpdateAllColors(row); + } + } + + /// + /// Updates all the color types for a given color row. + /// + /// The color row to update. + private void UpdateAllColors(SidekickColorRow colorRow) + { + foreach (ColorType colorType in Enum.GetValues(typeof(ColorType))) + { + _sidekickRuntime.UpdateColor(colorType, colorRow); + } + } + + /// + /// Populates the part color rows based on the filter being used. + /// + private void PopulatePartColorRows() + { + List propertiesToShow = new List(); + + switch (_currentPartType) + { + case ColorPartType.Species: + List speciesProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Species); + foreach (SidekickColorProperty property in speciesProperties) + { + Vector2 uv = new Vector2(property.U, property.V); + if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.Outfit: + List outfitProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Outfits); + foreach (SidekickColorProperty property in outfitProperties) + { + Vector2 uv = new Vector2(property.U, property.V); + if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.Attachments: + List attachmentProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Attachments); + foreach (SidekickColorProperty property in attachmentProperties) + { + Vector2 uv = new Vector2(property.U, property.V); + if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.Materials: + List materialProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Materials); + foreach (SidekickColorProperty property in materialProperties) + { + Vector2 uv = new Vector2(property.U, property.V); + if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.Elements: + List elementProperties = SidekickColorProperty.GetAllByGroup(_dbManager, ColorGroup.Elements); + foreach (SidekickColorProperty property in elementProperties) + { + Vector2 uv = new Vector2(property.U, property.V); + if ((_currentUVList.Contains(uv) || _showAllColourProperties == true) && !propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.CharacterHead: + List headProperties = new List(); + foreach (ColorPartType type in ColorPartType.CharacterHead.GetPartTypes()) + { + headProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); + } + + foreach (SidekickColorProperty property in headProperties) + { + if (!propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.CharacterUpperBody: + List upperProperties = new List(); + foreach (ColorPartType type in ColorPartType.CharacterUpperBody.GetPartTypes()) + { + upperProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); + } + + foreach (SidekickColorProperty property in upperProperties) + { + if (!propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.CharacterLowerBody: + List lowerProperties = new List(); + foreach (ColorPartType type in ColorPartType.CharacterLowerBody.GetPartTypes()) + { + lowerProperties.AddRange(SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[type])); + } + + foreach (SidekickColorProperty property in lowerProperties) + { + if (!propertiesToShow.Contains(property)) + { + propertiesToShow.Add(property); + } + } + + break; + case ColorPartType.Head: + case ColorPartType.Hair: + case ColorPartType.EyebrowLeft: + case ColorPartType.EyebrowRight: + case ColorPartType.EyeLeft: + case ColorPartType.EyeRight: + case ColorPartType.EarLeft: + case ColorPartType.EarRight: + case ColorPartType.FacialHair: + case ColorPartType.Torso: + case ColorPartType.ArmUpperLeft: + case ColorPartType.ArmUpperRight: + case ColorPartType.ArmLowerLeft: + case ColorPartType.ArmLowerRight: + case ColorPartType.HandLeft: + case ColorPartType.HandRight: + case ColorPartType.Hips: + case ColorPartType.LegLeft: + case ColorPartType.LegRight: + case ColorPartType.FootLeft: + case ColorPartType.FootRight: + case ColorPartType.AttachmentHead: + case ColorPartType.AttachmentFace: + case ColorPartType.AttachmentBack: + case ColorPartType.AttachmentHipsFront: + case ColorPartType.AttachmentHipsBack: + case ColorPartType.AttachmentHipsLeft: + case ColorPartType.AttachmentHipsRight: + case ColorPartType.AttachmentShoulderLeft: + case ColorPartType.AttachmentShoulderRight: + case ColorPartType.AttachmentElbowLeft: + case ColorPartType.AttachmentElbowRight: + case ColorPartType.AttachmentKneeLeft: + case ColorPartType.AttachmentKneeRight: + case ColorPartType.Nose: + case ColorPartType.Teeth: + case ColorPartType.Tongue: + case ColorPartType.Wrap:/* + case ColorPartType.AttachmentHandLeft: + case ColorPartType.AttachmentHandRight: */ + propertiesToShow = SidekickColorProperty.GetByUVs(_dbManager, _currentUVDictionary[_currentPartType]); + break; + case ColorPartType.AllParts: + default: + propertiesToShow = _showAllColourProperties || _currentUVList == null + ? SidekickColorProperty.GetAll(_dbManager) + : SidekickColorProperty.GetByUVs(_dbManager, _currentUVList); + break; + } + + _visibleColorRows.Clear(); + + // when filtering the view to a specific UV dictionary, we need to reset the property order + propertiesToShow.Sort((a, b) => a.ID.CompareTo(b.ID)); + + foreach (SidekickColorProperty property in propertiesToShow) + { + foreach (SidekickColorRow row in _allColorRows.Where(row => row.ColorProperty.ID == property.ID)) + { + _visibleColorRows.Add(row); + } + } + } + + /// + /// Refreshes the visible color rows in the UI. + /// + private void RefreshVisibleColorRows() + { + _colorSelectionRowView.Clear(); + + foreach (ColorGroup group in Enum.GetValues(typeof(ColorGroup))) + { + List properties = _visibleColorRows + .Select(row => row.ColorProperty) + .Where(prop => prop.Group == group) + .ToList(); + + string tooltipText = ""; + + switch (group) + { + case ColorGroup.Species: + tooltipText = "Species colors make up the character as if it has no outfit on. (for example - skin, teeth, tongue, fingernails etc)"; + break; + case ColorGroup.Outfits: + tooltipText = "Outfit colors make up the clothing on the character. (for example - Torso outfit, arm outfit, hand outfit etc)"; + break; + case ColorGroup.Attachments: + tooltipText = "Attachment colors make up the additional parts attached to a character. (for example - a backpack, shoulder pads, elbow pads, knee pads etc)"; + break; + case ColorGroup.Materials: + tooltipText = "material colors make up a collection of shared standard materials (for example - wood, metal, leather, paper, bone etc)"; + break; + } + + if (properties.Count > 0) + { + Label groupLabel = new Label(group.ToString()) + { + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold), + marginBottom = 4, + marginTop = 6 + }, + tooltip = tooltipText + }; + _colorSelectionRowView.Add(groupLabel); + + VisualElement headerContainer = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + fontSize = 10, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + Label colorHeader = new Label("Color") + { + style = + { + width = 103, + marginLeft = 155 + } + }; + Label metallicHeader = new Label("Metallic") + { + style = + { + width = 66 + } + }; + Label smoothnessHeader = new Label("Smoothness") + { + style = + { + width = 66 + } + }; + Label reflectionHeader = new Label("Reflection") + { + style = + { + width = 66 + } + }; + Label emissionHeader = new Label("Emission") + { + style = + { + width = 66 + } + }; + Label opacityHeader = new Label("Opacity") + { + style = + { + width = 66 + } + }; + + headerContainer.Add(colorHeader); + // headerContainer.Add(metallicHeader); + // headerContainer.Add(smoothnessHeader); + // headerContainer.Add(reflectionHeader); + // headerContainer.Add(emissionHeader); + // headerContainer.Add(opacityHeader); + + _colorSelectionRowView.Add(headerContainer); + + foreach (SidekickColorProperty property in properties) + { + foreach (SidekickColorRow row in _visibleColorRows.Where(row => row.ColorProperty.ID == property.ID)) + { + CreateColorRow(_colorSelectionRowView, row); + } + } + } + } + } + + /// + /// Populates the color rows from texture files on the disk. + /// + private void PopulateColorRowsFromTextures() + { + TextureImporter textureImporter = null; + + Texture2D mainColor = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceColorPath); + if (mainColor != null) + { + mainColor.filterMode = FilterMode.Point; + if (!mainColor.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceColorPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + else + { + Material defaultMaterial = (Material) _materialField.value; + mainColor = (Texture2D) defaultMaterial.mainTexture; + } + + Texture2D metallic = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceMetallicPath); + if (metallic != null) + { + metallic.filterMode = FilterMode.Point; + if (!metallic.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceMetallicPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + + Texture2D smoothness = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceSmoothnessPath); + if (smoothness != null) + { + smoothness.filterMode = FilterMode.Point; + if (!smoothness.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceSmoothnessPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + + Texture2D reflection = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceReflectionPath); + if (reflection != null) + { + reflection.filterMode = FilterMode.Point; + if (!reflection.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceReflectionPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + + Texture2D emission = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceEmissionPath); + if (emission != null) + { + emission.filterMode = FilterMode.Point; + if (!emission.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceEmissionPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + + Texture2D opacity = AssetDatabase.LoadAssetAtPath(_currentColorSet.SourceOpacityPath); + if (opacity != null) + { + opacity.filterMode = FilterMode.Point; + if (!opacity.isReadable) + { + textureImporter = (TextureImporter) AssetImporter.GetAtPath(_currentColorSet.SourceOpacityPath); + textureImporter.isReadable = true; + textureImporter.SaveAndReimport(); + } + } + + List newColorRows = new List(); + + List currentSetColors = SidekickColorRow.GetAllBySet(_dbManager, _currentColorSet); + + // TODO : if textures don't exist BUT color rows exist in DB, ask user if they want to re-save the textures from the DB values, loop back and reimport + // TODO : if textures don't exist AND color rows don't exist in DB, delete the colorset entry in DB/dropdown, advance to next on list and reload + + foreach (SidekickColorProperty property in SidekickColorProperty.GetAll(_dbManager)) + { + SidekickColorRow existingRow = currentSetColors.FirstOrDefault(row => row.ColorProperty.ID == property.ID); + SidekickColorRow newRow = new SidekickColorRow + { + ID = existingRow?.ID ?? -1, + ColorSet = _currentColorSet, + ColorProperty = property, + // TODO remove null checks when we know we have textures + NiceColor = mainColor?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceColor ?? Color.red, + // NiceMetallic = metallic?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceMetallic ?? Color.red, + // NiceSmoothness = smoothness?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceSmoothness ?? Color.red, + // NiceReflection = reflection?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceReflection ?? Color.red, + // NiceEmission = emission?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceEmission ?? Color.red, + // NiceOpacity = opacity?.GetPixel(property.U * 2, property.V * 2) ?? existingRow?.NiceOpacity ?? Color.red + }; + + newRow.Save(_dbManager); + newColorRows.Add(newRow); + } + + _allColorRows = newColorRows; + PopulatePartColorRows(); + RefreshVisibleColorRows(); + } + + /// + /// Adds a color row to the given view. + /// + /// The view to add the color row to. + /// The color row to populate this UI element with. + private void CreateColorRow(VisualElement view, SidekickColorRow colorRow) + { + VisualElement row = new VisualElement(); + row.AddToClassList("colorSelectionRow"); + + Label rowLabel = new Label(colorRow.ColorProperty.Name); + rowLabel.AddToClassList("colorSelectionRowLabel"); + row.Add(rowLabel); + + VisualElement rowContent = new VisualElement(); + rowContent.AddToClassList("colorSelectionRowContent"); + + row.Add(rowContent); + + // TODO: uncomment when locking is required. + // Button btnLock = new Button(); + // + // Image lockImage = new Image + // { + // image = colorRow.IsLocked ? EditorGUIUtility.IconContent("Locked").image : EditorGUIUtility.IconContent("Unlocked").image, + // scaleMode = ScaleMode.ScaleToFit + // }; + // + // btnLock.Add(lockImage); + // colorRow.ButtonImage = lockImage; + // rowContent.Add(btnLock); + // btnLock.clickable.clicked += () => + // { + // colorRow.IsLocked = !colorRow.IsLocked; + // lockImage.image = colorRow.IsLocked + // ? EditorGUIUtility.IconContent("Locked").image + // : EditorGUIUtility.IconContent("Unlocked").image; + // }; + + ColorField colorField = new ColorField + { + value = colorRow.NiceColor, + tooltip = colorRow.ColorProperty.Name + " Color", + style = + { + // TODO: shrink to 50 once all colors options are re-enabled + width = 100 + } + }; + rowContent.Add(colorField); + colorField.RegisterValueChangedCallback( + evt => + { + colorRow.NiceColor = evt.newValue; + _sidekickRuntime.UpdateColor(ColorType.MainColor, colorRow); + } + ); + + // TODO: Uncomment once all colors options are re-enabled + // ColorField metallicField = new ColorField + // { + // value = colorRow.NiceMetallic, + // tooltip = colorRow.ColorProperty.Name + " Metallic", + // style = + // { + // width = 60 + // } + // }; + // rowContent.Add(metallicField); + // metallicField.RegisterValueChangedCallback( + // evt => + // { + // colorRow.NiceMetallic = evt.newValue; + // _sidekickRuntime.UpdateColor(ColorType.Metallic, colorRow); + // } + // ); + // + // ColorField smoothnessField = new ColorField + // { + // value = colorRow.NiceSmoothness, + // tooltip = colorRow.ColorProperty.Name + " Smoothness", + // style = + // { + // width = 60 + // } + // }; + // rowContent.Add(smoothnessField); + // smoothnessField.RegisterValueChangedCallback( + // evt => + // { + // colorRow.NiceSmoothness = evt.newValue; + // _sidekickRuntime.UpdateColor(ColorType.Smoothness, colorRow); + // } + // ); + // + // ColorField reflectionField = new ColorField + // { + // value = colorRow.NiceReflection, + // tooltip = colorRow.ColorProperty.Name + " Reflection", + // style = + // { + // width = 60 + // } + // }; + // rowContent.Add(reflectionField); + // reflectionField.RegisterValueChangedCallback( + // evt => + // { + // colorRow.NiceReflection = evt.newValue; + // _sidekickRuntime.UpdateColor(ColorType.Reflection, colorRow); + // } + // ); + // + // ColorField emissionField = new ColorField + // { + // value = colorRow.NiceEmission, + // tooltip = colorRow.ColorProperty.Name + " Emission", + // style = + // { + // width = 60 + // } + // }; + // rowContent.Add(emissionField); + // emissionField.RegisterValueChangedCallback( + // evt => + // { + // colorRow.NiceEmission = evt.newValue; + // _sidekickRuntime.UpdateColor(ColorType.Emission, colorRow); + // } + // ); + // + // ColorField opacityField = new ColorField + // { + // value = colorRow.NiceOpacity, + // tooltip = colorRow.ColorProperty.Name + " Opacity", + // style = + // { + // width = 60 + // } + // }; + // rowContent.Add(opacityField); + // opacityField.RegisterValueChangedCallback( + // evt => + // { + // colorRow.NiceOpacity = evt.newValue; + // _sidekickRuntime.UpdateColor(ColorType.Opacity, colorRow); + // } + // ); + + // Button randomButton = new Button + // { + // text = "R", + // style = + // { + // right = 0 + // } + // }; + // rowContent.Add(randomButton); + + view.Add(row); + } + + /// + /// Switches the currently visible tab to the given tab. + /// + /// The tab to switch to. + private void SwitchToTab(TabView newTab) + { + if (_currentTab == newTab) + { + return; + } + + _currentTab = newTab; + + _bodyPresetTab.value = _currentTab == TabView.Preset; + _bodyPartsTab.value = _currentTab == TabView.Parts; + _bodyShapeTab.value = _currentTab == TabView.Body; + _colorSelectionTab.value = _currentTab == TabView.Colors; + // _decalSelectionTab.value = _currentTab == TabView.Decals; + _optionTab.value = _currentTab == TabView.Options; + + _presetView.style.display = _bodyPresetTab.value ? DisplayStyle.Flex : DisplayStyle.None; + _partView.style.display = _bodyPartsTab.value ? DisplayStyle.Flex : DisplayStyle.None; + _bodyShapeView.style.display = _bodyShapeTab.value ? DisplayStyle.Flex : DisplayStyle.None; + _colorSelectionView.style.display = _colorSelectionTab.value ? DisplayStyle.Flex : DisplayStyle.None; + //_decalSelectionView.style.display = _decalSelectionTab.value ? DisplayStyle.Flex : DisplayStyle.None; + _optionSelectionView.style.display = _optionTab.value ? DisplayStyle.Flex : DisplayStyle.None; + } + + /// + /// Populate the preset tab content. + /// + private void PopulatePresetUI() + { + _presetView.Clear(); + + Dictionary> dropdowns = new Dictionary>(); + + Foldout speciesFoldout = new Foldout + { + text = "Select - Species", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + }; + + List speciesNames = _allSpecies.Select(species => species.Name).ToList(); + + _speciesPresetField = new DropdownField + { + label = "Species", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) + }, + tooltip = "Select the species of your character" + }; + _speciesPresetField.choices = speciesNames; + _speciesPresetField.RegisterValueChangedCallback( + evt => + { + _speciesField.value = _speciesPresetField.value; + ProcessSpeciesChange(evt.newValue); + } + ); + + _speciesPresetField.index = _currentSpecies != null && speciesNames.Count > 0 ? _speciesPresetField.choices.IndexOf(_currentSpecies.Name) : 0; + speciesFoldout.Add(_speciesPresetField); + _presetView.Add(speciesFoldout); + + List allFilters = SidekickPresetFilter.GetAll(_dbManager); + + allFilters.Sort( + (filterA, filterB) => String.CompareOrdinal(filterA.Term, filterB.Term) + ); + + if (allFilters.Count > 0) + { + Foldout filterFoldout = new Foldout() + { + text = "Select - Preset Part Filter", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + VisualElement filterContent = new VisualElement + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + flexWrap = new StyleEnum(Wrap.Wrap) + } + }; + + Color borderColor = new Color(0.17f, 0.17f, 0.17f); + Color backgroundColor = new Color(0.35f, 0.35f, 0.35f); + List allFilterToggles = new List(); + + foreach (SidekickPresetFilter filter in allFilters) + { + Toggle outfitToggle = new Toggle(filter.Term) + { + value = !_partPresetFilterToggleMap.TryGetValue(filter, out bool toggleValue) || toggleValue, + style = + { + width = 160, + borderBottomWidth = 1, + borderBottomColor = borderColor, + paddingBottom = 2, + borderLeftWidth = 1, + borderLeftColor = borderColor, + paddingLeft = 2, + borderRightWidth = 1, + borderRightColor = borderColor, + paddingRight = 2, + borderTopWidth = 1, + borderTopColor = borderColor, + paddingTop = 2, + borderBottomLeftRadius = 3, + borderBottomRightRadius = 3, + borderTopLeftRadius = 3, + borderTopRightRadius = 3, + backgroundColor = backgroundColor, + textOverflow = new StyleEnum(TextOverflow.Ellipsis) + } + }; + + allFilterToggles.Add(outfitToggle); + + if (outfitToggle.value) + { + _partPresetFilterToggleMap[filter] = outfitToggle.value; + } + + outfitToggle.RegisterValueChangedCallback( + evt => + { + _partPresetFilterToggleMap[filter] = evt.newValue; + PopulatePresetPartDropdowns(dropdowns); + } + ); + + filterContent.Add(outfitToggle); + } + + VisualElement buttonRow = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row) + } + }; + + Button selectAll = new Button( + delegate + { + foreach (Toggle toggle in allFilterToggles) + { + toggle.value = true; + } + } + ) + { + text = "Select All" + }; + + Button selectNone = new Button( + delegate + { + foreach (Toggle toggle in allFilterToggles) + { + toggle.value = false; + } + } + ) + { + text = "Select None" + }; + + buttonRow.Add(selectAll); + buttonRow.Add(selectNone); + + filterFoldout.Add(buttonRow); + filterFoldout.Add(filterContent); + + _presetView.Add(filterFoldout); + } + + _availablePresets = SidekickPartPreset.GetAll(_dbManager); + + Foldout generateFoldout = new Foldout + { + text = "Randomize Character", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + //tooltip = "Create a character based on the selected species" + }; + + Button generateButton = new Button() + { + style = + { + minHeight = 50, + marginRight = 18, + flexDirection = new StyleEnum(FlexDirection.Row), + alignContent = new StyleEnum(Align.Center), + alignItems = new StyleEnum(Align.Center), + unityTextAlign = new StyleEnum(TextAnchor.MiddleCenter), + justifyContent = new StyleEnum(Justify.Center) + }, + tooltip = "Generate a character at the push of a button" + }; + + Texture2D randomImage = Resources.Load("UI/T_Random"); + generateButton.Add( + new Image + { + image = randomImage, + scaleMode = ScaleMode.ScaleToFit, + style = + { + paddingTop = new StyleLength(1), + paddingBottom = new StyleLength(1), + paddingRight = 5, + alignSelf = new StyleEnum(Align.Center) + } + } + ); + generateButton.Add( + new Label + { + text = "Randomize Character", + style = + { + alignSelf = new StyleEnum(Align.Center) + } + } + ); + + generateFoldout.Add(generateButton); + _presetView.Add(generateFoldout); + + Foldout presetsFoldout = new Foldout() + { + text = "Presets", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + //tooltip = "Select from a number of collections of parts, body types and colors" + }; + + Label partTitle = new Label("Parts") + { + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + tooltip = "Collections of character parts ie. Head attachment, Torso, Nose that make up the character" + }; + + string tooltipText = ""; + + presetsFoldout.Add(partTitle); + _presetView.Add(presetsFoldout); + + _presetPartContainer = new VisualElement(); + presetsFoldout.Add(_presetPartContainer); + + PopulatePresetPartDropdowns(dropdowns); + + Label bodyTitle = new Label("Body") + { + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + tooltip = "Preset bodies in a number of types, sizes and musculature" + }; + + presetsFoldout.Add(bodyTitle); + _currentBodyPresetDictionary = new Dictionary(); + List bodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); + List bodyShapeNames = bodyShapes.Select(b => b.Name).ToList(); + for (int i = 0; i < bodyShapeNames.Count; i++) + { + _currentBodyPresetDictionary.Add(bodyShapeNames[i], bodyShapes[i]); + } + + string bodyTypeLabel = "Body Type"; + + string bodyShapeDefaultValue = "Androgynous Medium"; + + if (bodyShapeNames.Count > 0) + { + bodyShapeDefaultValue = _presetDefaultValues.TryGetValue(bodyTypeLabel, out string bodyShapeValue) + ? bodyShapeValue + : bodyShapeDefaultValue; + } + + bodyShapeNames.Sort(); + + tooltipText = "Select a body preset for you character - a body type preset is made up of combinations of body type, size and musculature."; + + dropdowns[bodyTypeLabel] = CreatePresetRow(presetsFoldout, bodyTypeLabel, tooltipText, bodyShapeNames, false, bodyShapeDefaultValue, PresetDropdownType.Body); + + Label colorTitle = new Label("Colors") + { + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + }, + tooltip = "Collections of character colors ie. Skin color, teeth color, eye color, hair color that make up the characters colors" + }; + + SidekickSpecies unrestrictedSpecies = SidekickSpecies.GetByName(_dbManager, "Unrestricted"); + + presetsFoldout.Add(colorTitle); + _currentColorSpeciesPresetDictionary = new Dictionary(); + _currentColorOutfitsPresetDictionary = new Dictionary(); + _currentColorAttachmentsPresetDictionary = new Dictionary(); + _currentColorMaterialsPresetDictionary = new Dictionary(); + _currentColorElementsPresetDictionary = new Dictionary(); + foreach (ColorGroup colorGroup in Enum.GetValues(typeof(ColorGroup))) + { + // TODO: remove when Element colors are re-added + if (colorGroup == ColorGroup.Elements) + { + continue; + } + + List colorPresets = colorGroup is ColorGroup.Species && _currentSpecies.ID != unrestrictedSpecies.ID + ? SidekickColorPreset.GetAllByColorGroupAndSpecies(_dbManager, colorGroup, _currentSpecies) + : SidekickColorPreset.GetAllByColorGroup(_dbManager, colorGroup); + + List colorPresetNames = colorPresets.Select(cp => cp.Name).ToList(); + for (int i = 0; i < colorPresetNames.Count; i++) + { + switch (colorGroup) + { + case ColorGroup.Species: + _currentColorSpeciesPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); + tooltipText = "Select a species color preset for your character - a species color preset is made up of the colors that would make up the character if it had no outfit on. (for example - skin, teeth, tongue, fingernails etc)"; + break; + case ColorGroup.Outfits: + _currentColorOutfitsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); + tooltipText = "Select an outfit color preset for your character - an outfit color preset is made up of the colors that make up the clothing on the character. (for example - torso outfit, arm outfit, hand outfit etc)"; + break; + case ColorGroup.Attachments: + _currentColorAttachmentsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); + tooltipText = "Select an attachments color preset for your character - an attachments color preset is made up of the colors used on additional parts on the character. (for example - shoulder attachments, back attachments, hip attachments etc)"; + break; + case ColorGroup.Materials: + _currentColorMaterialsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); + tooltipText = "Select a materials color preset for your character - a materials color preset is made up of the colors that make up general materials of the outfit and attachments. (for example - metal, wood, leather, plastic, bone etc)"; + break; + case ColorGroup.Elements: + _currentColorElementsPresetDictionary.Add(colorPresetNames[i], colorPresets[i]); + break; + } + } + + string defaultValue = "None"; + + if (colorPresetNames.Count > 0) + { + defaultValue = _presetDefaultValues.TryGetValue(colorGroup.ToString(), out string value) + ? value + : defaultValue; + } + + colorPresetNames.Sort(); + + if (_processingSpeciesChange && colorGroup == ColorGroup.Species && !_loadingCharacter) + { + defaultValue = colorPresetNames.Count > 0 ? colorPresetNames[0] : "None"; + } + + dropdowns[colorGroup.ToString()] = CreatePresetRow(presetsFoldout, colorGroup.ToString(), tooltipText, colorPresetNames, true, defaultValue, PresetDropdownType.Color); + } + + /* TODO: When decals are added (issue 1108), uncomment and update this section + Label textureTitle = new Label("Textures") + { + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + presetsFoldout.Add(textureTitle); + CreatePresetRow(presetsFoldout, "Skin", new List(), true, "None", PresetDropdownType.Texture); + CreatePresetRow(presetsFoldout, "Outfit", new List(), true, "None", PresetDropdownType.Texture); + */ + + generateButton.clickable.clicked += delegate + { + _applyingPreset = true; + foreach (PopupField dropdown in dropdowns.Values) + { + List values = dropdown.choices; + values.Remove("None"); + string newValue = "None"; + if (values.Count > 0) + { + newValue = values[Random.Range(0, values.Count - 1)]; + } + dropdown.value = newValue; + } + + // if (_newModel != null) + // { + // DestroyImmediate(_newModel); + // } + + _newModel = GenerateCharacter(false, true); + UpdatePartUVData(); + _applyingPreset = false; + }; + } + + /// + /// Populates the preset part dropdowns. + /// + /// The list of all preset dropdowns to put the preset part dropdowns into once populated + /// + private void PopulatePresetPartDropdowns(Dictionary> dropdowns) + { + _presetPartContainer.Clear(); + string tooltipText = ""; + _currentHeadPresetDictionary = new Dictionary(); + _currentUpperBodyPresetDictionary = new Dictionary(); + _currentLowerBodyPresetDictionary = new Dictionary(); + HashSet mappedPresets = new HashSet(); + + if (_partPresetFilterToggleMap.Count > 0) + { + foreach (KeyValuePair entry in _partPresetFilterToggleMap) + { + if (entry.Value) + { + if (_sidekickRuntime.MappedPresetFilterDictionary.TryGetValue(entry.Key.Term, out List presets)) + { + mappedPresets.UnionWith(presets); + } + } + } + + if (_sidekickRuntime.MappedBasePresetDictionary.TryGetValue(_currentSpecies, out List basePresets)) + { + mappedPresets.UnionWith(basePresets); + } + } + else + { + mappedPresets.UnionWith(_availablePresets); + } + + List allPresets = mappedPresets.ToList(); + + SidekickSpecies unrestrictedSpecies = SidekickSpecies.GetByName(_dbManager, "Unrestricted"); + + foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) + { + // only filter head part presets by species + List presets = partGroup is PartGroup.Head && _currentSpecies.ID != unrestrictedSpecies?.ID + ? allPresets.Where(preset => preset.Species.ID == _currentSpecies.ID && preset.PartGroup == partGroup).ToList() + : allPresets.Where(preset => preset.PartGroup == partGroup).ToList(); + List presetNames = new List(); + foreach (SidekickPartPreset preset in presets) + { + switch (partGroup) + { + case PartGroup.Head: + _currentHeadPresetDictionary.Add(preset.Name, preset); + tooltipText = "Select a head preset for you character - a head preset is made up of parts like a head, nose, eyes and teeth etc."; + break; + case PartGroup.UpperBody: + _currentUpperBodyPresetDictionary.Add(preset.Name, preset); + tooltipText = "Select an upper body preset for you character - an upper body preset is made up of parts like a torso, arms, hands and a back attachment etc."; + break; + case PartGroup.LowerBody: + _currentLowerBodyPresetDictionary.Add(preset.Name, preset); + tooltipText = "Select a lower body preset for you character - a lower body preset is made up of parts like hips, legs, feet and hip attachments etc."; + break; + } + + presetNames.Add(preset.Name); + } + + string defaultValue = "None"; + + if (presetNames.Count > 0) + { + if (_presetDefaultValues.TryGetValue(partGroup.ToString(), out string value)) + { + defaultValue = presetNames.Contains(value) ? value : "None"; + + if (_processingSpeciesChange && partGroup == PartGroup.Head && value != "None" && defaultValue == "None") + { + defaultValue = presetNames[Random.Range(0, presetNames.Count - 1)]; + } + } + } + + presetNames.Sort(); + + dropdowns[partGroup.ToString()] = CreatePresetRow(_presetPartContainer, partGroup.ToString(), tooltipText, presetNames, true, defaultValue, PresetDropdownType.Part); + } + } + + /// + /// Create a selection row for the preset tab with the given values. + /// + /// The view to add the row to. + /// The label to put in the row. + /// The tooltip to display for this row. + /// The values for the dropdown in the row. + /// Whether to include `None` as a value in the dropdown. + /// The default value to select from the dropdown. + /// What section of the preset UI this dropdown is part of. + /// The dropdown selection UI element. + private PopupField CreatePresetRow( + VisualElement view, + string rowLabel, + string tooltipText, + List dropdownValues, + bool includeNoneValue, + string defaultValue, + PresetDropdownType dropdownType) + { + VisualElement partContainer = new VisualElement + { + style = + { + minHeight = 20, + display = DisplayStyle.Flex, + flexDirection = FlexDirection.Row, + marginBottom = 2, + marginTop = 2, + marginLeft = 15, + marginRight = 2, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) + } + }; + + Label partTypeTitle = new Label(rowLabel.ToString()) + { + style = + { + unityTextAlign = TextAnchor.MiddleLeft, + width = 150 + }, + tooltip = tooltipText + }; + + Button removeButton = new Button() + { + tooltip = "Remove this preset, resets selection to None" + }; + + removeButton.Add( + new Image + { + image = Resources.Load("UI/T_Clear"), + scaleMode = ScaleMode.ScaleToFit + } + ); + + int marginLeft = 0; + if (dropdownType != PresetDropdownType.Part) + { + marginLeft = 36; + } + + Button previousButton = new Button() + { + tooltip = "Select the previous preset", + style = + { + marginLeft = marginLeft + } + }; + + previousButton.Add( + new Image + { + image = EditorGUIUtility.IconContent("tab_prev", "|Previous Preset").image, + scaleMode = ScaleMode.ScaleToFit + } + ); + + Button nextButton = new Button() + { + tooltip = "Select the next preset" + }; + + nextButton.Add( + new Image + { + image = EditorGUIUtility.IconContent("tab_next", "|Next Preset").image, + scaleMode = ScaleMode.ScaleToFit + } + ); + + Button randomButton = new Button() + { + tooltip = "Randomly select a preset" + }; + + Texture2D randomImage = Resources.Load("UI/T_Random"); + randomButton.Add( + new Image + { + image = randomImage, + scaleMode = ScaleMode.ScaleToFit, + style = + { + paddingTop = new StyleLength(1), + paddingBottom = new StyleLength(1) + } + } + ); + + if (!dropdownValues.Contains(defaultValue)) + { + defaultValue = includeNoneValue ? "None" : dropdownValues[0]; + } + + List popupValues = new List(); + if (includeNoneValue) + { + popupValues.Add("None"); + }; + + popupValues.AddRange(dropdownValues); + + PopupField partSelection = new PopupField(popupValues, 0) + { + value = "None", + style = + { + minWidth = 180 + }, + tooltip = tooltipText + }; + + partSelection.RegisterValueChangedCallback( + evt => + { + _presetDefaultValues[rowLabel] = evt.newValue; + + // Correctly enable/disable next and previous buttons based on selection + previousButton.SetEnabled(partSelection.index > 0); + nextButton.SetEnabled(partSelection.index < popupValues.Count - 1); + + switch (dropdownType) + { + case PresetDropdownType.Part: + _applyingPreset = true; + + bool hasErrors = false; + string errorMessage = "The following parts could not be found in your project:\n"; + Enum.TryParse(rowLabel, out PartGroup group); + List partTypesToRemove = group.GetPartTypes(); + SidekickPartPreset currentPartPreset = null; + List presetParts = new List(); + // NOTE : need to ensure evt.newValue is always in the dictionary ahead of this, or change to GetValueOrDefault() + if (evt.newValue != "None") + { + switch (group) + { + case PartGroup.Head: + currentPartPreset = _currentHeadPresetDictionary[evt.newValue]; + break; + case PartGroup.UpperBody: + currentPartPreset = _currentUpperBodyPresetDictionary[evt.newValue]; + break; + case PartGroup.LowerBody: + currentPartPreset = _currentLowerBodyPresetDictionary[evt.newValue]; + break; + } + presetParts = SidekickPartPresetRow.GetAllByPreset(_dbManager, currentPartPreset); + } + + foreach (SidekickPartPresetRow presetPart in presetParts) + { + if (Enum.TryParse(CharacterPartTypeUtils.GetTypeNameFromShortcode(presetPart.PartType), out CharacterPartType partType)) + { + if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls currentField)) + { + if (presetPart.Part != null) + { + _currentCharacter[partType] = presetPart.Part; + } + + UpdateResult result = new UpdateResult(errorMessage, hasErrors); + + if (partType == CharacterPartType.Wrap) + { + if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls wrapSelection)) + { + if (_requiresWrap && _bodyTypeBlendValue > 0) + { + wrapSelection.PartDropdown.SetEnabled(true); + wrapSelection.RandomisePartDropdownValue(); + } + else + { + wrapSelection.PartDropdown.SetEnabled(false); + wrapSelection.SetPartDropdownValue(null); + _currentCharacter.Remove(CharacterPartType.Wrap); + } + } + } + else + { + result = UpdatePartDropdown( + currentField, + presetPart.Part?.Name ?? "None", + errorMessage, + hasErrors + ); + } + + hasErrors = result.HasErrors; + errorMessage = result.ErrorMessage; + partTypesToRemove.Remove(partType); + } + } + } + + foreach (CharacterPartType partType in partTypesToRemove) + { + if (_partSelectionDictionary.TryGetValue(partType, out PartTypeControls currentField)) + { + UpdateResult result = UpdatePartDropdown(currentField, "None", errorMessage, hasErrors); + + hasErrors = result.HasErrors; + errorMessage = result.ErrorMessage; + } + } + + if (hasErrors) + { + EditorUtility.DisplayDialog( + "Assets Missing", + errorMessage, + "OK" + ); + } + + _applyingPreset = false; + + _newModel = GameObject.Find(_OUTPUT_MODEL_NAME); + + // if (_newModel != null) + // { + // DestroyImmediate(_newModel); + // } + + _newModel = GenerateCharacter(false, true); + UpdatePartUVData(); + break; + case PresetDropdownType.Body: + SidekickBodyShapePreset bodyShapePreset = _currentBodyPresetDictionary[evt.newValue]; + if (Math.Abs(_bodyTypeSlider.value - bodyShapePreset.BodyType) < 0.001f) + { + string body = "None"; + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Torso, out PartTypeControls bodySelection)) + { + body = bodySelection.PartDropdown.value; + } + + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) + { + if (body != "None" && _requiresWrap && _bodyTypeBlendValue > 0) + { + wrapSelection.PartDropdown.SetEnabled(true); + wrapSelection.RandomisePartDropdownValue(); + } + else + { + wrapSelection.PartDropdown.SetEnabled(false); + wrapSelection.SetPartDropdownValue(null); + _currentCharacter.Remove(CharacterPartType.Wrap); + } + } + } + + _bodyTypeSlider.value = bodyShapePreset.BodyType; + _bodySizeSlider.value = bodyShapePreset.BodySize; + _musclesSlider.value = bodyShapePreset.Musculature; + break; + case PresetDropdownType.Color: + if (evt.newValue == "None") + { + return; + } + + ResetCurrentColorSet(); + + Enum.TryParse(rowLabel, out ColorGroup colorGroup); + SidekickColorPreset colorPreset = null; + // NOTE : need to ensure evt.newValue is always in the dictionary ahead of this, or change to GetValueOrDefault() + switch (colorGroup) + { + case ColorGroup.Species: + colorPreset = _currentColorSpeciesPresetDictionary[evt.newValue]; + break; + case ColorGroup.Outfits: + colorPreset = _currentColorOutfitsPresetDictionary[evt.newValue]; + break; + case ColorGroup.Attachments: + colorPreset = _currentColorAttachmentsPresetDictionary[evt.newValue]; + break; + case ColorGroup.Materials: + colorPreset = _currentColorMaterialsPresetDictionary[evt.newValue]; + break;/* + case ColorGroup.Elements: + colorPreset = _currentColorElementsPresetDictionary[evt.newValue]; + break;*/ + } + + List presetColorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, colorPreset); + foreach (SidekickColorPresetRow row in presetColorRows) + { + SidekickColorRow existingRow = _allColorRows.Find(r => r.ColorProperty.ID == row.ColorProperty.ID); + if (existingRow == null) + { + existingRow = new SidekickColorRow() + { + ID = -1, + ColorSet = _currentColorSet, + ColorProperty = row.ColorProperty, + NiceColor = row.NiceColor, + NiceMetallic = row.NiceMetallic, + NiceSmoothness = row.NiceSmoothness, + NiceReflection = row.NiceReflection, + NiceEmission = row.NiceEmission, + NiceOpacity = row.NiceOpacity + }; + + _allColorRows.Add(existingRow); + } + else + { + existingRow.NiceColor = row.NiceColor; + existingRow.NiceMetallic = row.NiceMetallic; + existingRow.NiceSmoothness = row.NiceSmoothness; + existingRow.NiceReflection = row.NiceReflection; + existingRow.NiceEmission = row.NiceEmission; + existingRow.NiceOpacity = row.NiceOpacity; + } + + UpdateAllColors(existingRow); + } + + PopulatePartColorRows(); + RefreshVisibleColorRows(); + break; + case PresetDropdownType.Texture: + // TODO: Add texture setting functionality once decal system in place + break; + default: + throw new ArgumentOutOfRangeException(nameof(dropdownType), dropdownType, null); + } + } + ); + + removeButton.clickable.clicked += delegate + { + // TODO: Change to default character when available + partSelection.value = "None"; + }; + + previousButton.clickable.clicked += delegate + { + int newIndex = partSelection.index - 1; + if (newIndex <= 0) + { + newIndex = 0; + } + + partSelection.index = newIndex; + }; + + nextButton.clickable.clicked += delegate + { + int newIndex = partSelection.index + 1; + if (newIndex >= partSelection.choices.Count - 1) + { + newIndex = partSelection.choices.Count - 1; + } + + partSelection.index = newIndex; + }; + + randomButton.clickable.clicked += delegate + { + int currentIndex = partSelection.index; + if (partSelection.choices.Count - 1 > 1) + { + while (partSelection.index == currentIndex) + { + partSelection.index = Random.Range(1, partSelection.choices.Count); + } + } + }; + + partContainer.Add(partTypeTitle); + if (dropdownType == PresetDropdownType.Part) + { + partContainer.Add(removeButton); + } + partContainer.Add(previousButton); + partContainer.Add(nextButton); + partContainer.Add(randomButton); + partContainer.Add(partSelection); + view.Add(partContainer); + + partSelection.value = defaultValue; + + return partSelection; + } + + /// + /// Updates the required parts of the UI on a species change. + /// + /// The name of the species being changed to. + private void ProcessSpeciesChange(string newSpecies) + { + // don't need to re-process if multiple callbacks are triggered + if (_currentSpecies.Name == newSpecies) + { + return; + } + + _currentSpecies = _allSpecies.FirstOrDefault(species => species.Name == newSpecies); + _sidekickRuntime.CurrentSpecies = _currentSpecies; + UpdateVisibleColorSets(); + ResetCurrentColorSet(); + if (_allColorRows.Count == 0) + { + PopulateColorRowsFromTextures(); + } + + _appliedPartFilters.ResetFiltersForSpeciesChange(); + + _processingSpeciesChange = true; + UpdatePartDropdowns(); + PopulatePresetUI(); + _processingSpeciesChange = false; + } + + /// + /// Populates the parts UI. + /// + private void PopulatePartUI() + { + _partView.Clear(); + + _availablePartList = new List(); + _partSelectionDictionary = new Dictionary(); + _partLockMap = new Dictionary, bool>(); + + Foldout speciesFoldout = new Foldout + { + text = "Select - Species", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + List speciesNames = _allSpecies.Select(species => species.Name).ToList(); + + _speciesField = new DropdownField + { + label = "Species", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) + }, + tooltip = "Select the species of your character" + }; + _speciesField.choices = speciesNames; + _speciesField.RegisterValueChangedCallback( + evt => + { + _speciesPresetField.value = _speciesField.value; + ProcessSpeciesChange(evt.newValue); + } + ); + + _speciesField.index = _currentSpecies != null && speciesNames.Count > 0 ? _speciesField.choices.IndexOf(_currentSpecies.Name) : 0; + speciesFoldout.Add(_speciesField); + _partView.Add(speciesFoldout); + + _partsFoldout = new Foldout() + { + text = "Select - Parts", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + List outfitFilters = SidekickPartFilter.GetAllForFilterType(_dbManager, FilterType.Outfit); + List orderedFilters = new List(); + + outfitFilters.Sort( + (filterA, filterB) => String.CompareOrdinal(filterA.Term, filterB.Term) + ); + + orderedFilters.AddRange(outfitFilters); + + Foldout filterFoldout = new Foldout() + { + text = "Select - Outfit Filter", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + _appliedPartFilters = new FilterGroup() + { + Runtime = _sidekickRuntime, + CombineType = FilterCombineType.Or + }; + + VisualElement toggleList = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row), + flexWrap = new StyleEnum(Wrap.Wrap) + } + }; + + List allFilterToggles = new List(); + + Color borderColor = new Color(0.17f, 0.17f, 0.17f); + Color backgroundColor = new Color(0.35f, 0.35f, 0.35f); + + foreach (SidekickPartFilter filter in orderedFilters) + { + Toggle outfitToggle = new Toggle(filter.Term) + { + value = true, + style = + { + width = 160, + borderBottomWidth = 1, + borderBottomColor = borderColor, + paddingBottom = 2, + borderLeftWidth = 1, + borderLeftColor = borderColor, + paddingLeft = 2, + borderRightWidth = 1, + borderRightColor = borderColor, + paddingRight = 2, + borderTopWidth = 1, + borderTopColor = borderColor, + paddingTop = 2, + borderBottomLeftRadius = 3, + borderBottomRightRadius = 3, + borderTopLeftRadius = 3, + borderTopRightRadius = 3, + backgroundColor = backgroundColor, + textOverflow = new StyleEnum(TextOverflow.Ellipsis) + } + }; + + FilterItem filterItem = new FilterItem(_sidekickRuntime, filter, FilterCombineType.Or); + _appliedPartFilters.AddFilterItem(filterItem); + + outfitToggle.RegisterValueChangedCallback( + evt => + { + if (evt.newValue) + { + _appliedPartFilters.AddFilterItem(filterItem); + } + else + { + _appliedPartFilters.RemoveFilterItem(filterItem); + } + UpdatePartDropdowns(); + } + ); + + toggleList.Add(outfitToggle); + allFilterToggles.Add(outfitToggle); + } + + VisualElement buttonRow = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row) + } + }; + + Button selectAll = new Button( + delegate + { + foreach (Toggle toggle in allFilterToggles) + { + toggle.value = true; + } + } + ) + { + text = "Select All" + }; + + Button selectNone = new Button( + delegate + { + foreach (Toggle toggle in allFilterToggles) + { + toggle.value = false; + } + } + ) + { + text = "Select None" + }; + + buttonRow.Add(selectAll); + buttonRow.Add(selectNone); + + filterFoldout.Add(buttonRow); + filterFoldout.Add(toggleList); + + _partView.Add(filterFoldout); + + foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) + { + string labelText = StringUtils.AddSpacesBeforeCapitalLetters(partGroup.ToString()); + Foldout partGroupFoldout = new Foldout + { + text = labelText, + style = + { + marginLeft = 15, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + Button randomiseAllButton = new Button() + { + text = "Randomize " + labelText + }; + + partGroupFoldout.Add(randomiseAllButton); + + foreach (CharacterPartType value in partGroup.GetPartTypes()) + { + VisualElement partContainer = new VisualElement + { + style = + { + minHeight = 20, + display = DisplayStyle.Flex, + flexDirection = FlexDirection.Row, + marginBottom = 2, + marginTop = 2, + marginRight = 2, + unityFontStyleAndWeight = new StyleEnum(FontStyle.Normal) + } + }; + BuildPartDetails(value, partContainer); + partGroupFoldout.Add(partContainer); + } + + _partsFoldout.Add(partGroupFoldout); + + randomiseAllButton.clickable.clicked += delegate + { + foreach (CharacterPartType value in partGroup.GetPartTypes()) + { + PartTypeControls dropdown = _partSelectionDictionary[value]; + bool locked = _partLockMap[dropdown.PartDropdown]; + if (!locked) + { + if (dropdown.PartDropdown.choices.Count > 1) + { + dropdown.RandomisePartDropdownValue(); + } + else + { + dropdown.SetPartDropdownValue("None"); + } + } + } + }; + } + + UpdatePartDropdowns(); + + _partView.Add(_partsFoldout); + } + + /// + /// Builds the UI details for each different part type. + /// + /// The type of the part to build the UI for. + /// The container to add the UI to. + private void BuildPartDetails(CharacterPartType type, VisualElement partContainer) + { + List partsList = new List(); + + foreach (SidekickPart part in _allPartsLibrary[type]) + { + if (_availablePartList.Any(p => p.ID == part.ID)) + { + partsList.Add(part); + } + } + + Label partTypeTitle = new Label(type.ToString()) + { + style = + { + unityTextAlign = TextAnchor.MiddleLeft, + width = 150 + }, + tooltip = type.GetTooltipForPartType() + }; + + Image lockImage = new Image + { + image = EditorGUIUtility.IconContent("LockIcon", "|Lock Part").image, + scaleMode = ScaleMode.ScaleToFit, + style = + { + alignSelf = new StyleEnum(Align.Center), + width = 15, + height = 15, + paddingTop = 2 + } + }; + + Button lockButton = new Button() + { + tooltip = "Remove this part" + }; + + lockButton.Add( + lockImage + ); + + Button removeButton = new Button() + { + tooltip = "Remove this part" + }; + + removeButton.Add( + new Image + { + image = Resources.Load("UI/T_Clear"), + scaleMode = ScaleMode.ScaleToFit + } + ); + + Button previousButton = new Button() + { + tooltip = "Select the previous part" + }; + + previousButton.Add( + new Image + { + image = EditorGUIUtility.IconContent("tab_prev", "|Previous Part").image, + scaleMode = ScaleMode.ScaleToFit + } + ); + + Button nextButton = new Button() + { + tooltip = "Select the next part" + }; + + nextButton.Add( + new Image + { + image = EditorGUIUtility.IconContent("tab_next", "|Next Part").image, + scaleMode = ScaleMode.ScaleToFit + } + ); + + Button randomButton = new Button() + { + tooltip = "Randomly select a part" + }; + + Texture2D randomImage = Resources.Load("UI/T_Random"); + randomButton.Add( + new Image + { + image = randomImage, + scaleMode = ScaleMode.ScaleToFit, + style = + { + paddingTop = new StyleLength(1), + paddingBottom = new StyleLength(1) + } + } + ); + + List popupValues = new List(); + + if (type != CharacterPartType.Wrap) + { + popupValues.Add("None"); + } + + foreach (SidekickPart part in partsList) + { + SidekickPartSpeciesLink link = SidekickPartSpeciesLink.GetForSpeciesAndPart(_dbManager, _currentSpecies, part); + if (link != null) + { + popupValues.Add(part.Name); + } + } + + _currentCharacter.TryGetValue(type, out SidekickPart selectedPart); + string currentSelection = selectedPart?.Name ?? "None"; + if (_processingSpeciesChange) + { + if (popupValues.Count < 1 || (popupValues.Count == 1 && popupValues[0] == "None")) + { + _previousPartSelections[type] = currentSelection; + currentSelection = "None"; + } + else if (PartUtils.IsBaseSpeciesPart(currentSelection)) + { + _previousPartSelections[type] = currentSelection; + currentSelection = popupValues.Find(n => n.Contains("BASE")) ?? "None"; + } + else if (currentSelection == "None" && _previousPartSelections[type] != "None" && popupValues.Count > 1) + { + currentSelection = _previousPartSelections[type]; + _previousPartSelections[type] = "None"; + } + + if (!popupValues.Contains(currentSelection)) + { + _previousPartSelections[type] = currentSelection; + currentSelection = FindClosestPartMatch(popupValues, currentSelection); + } + } + + PopupField partSelection = new PopupField(popupValues, 0) + { + value = currentSelection + }; + + PartTypeControls controls = new PartTypeControls + { + PartType = type, + PartDropdown = partSelection, + ClearButton = removeButton, + NextButton = nextButton, + PreviousButton = previousButton, + RandomButton = randomButton + }; + + partSelection.RegisterCallback>( + changeEvent => + { + PartSelectionChangeEvent(changeEvent, type, controls); + } + ); + + _partLockMap[partSelection] = false; + + lockButton.clickable.clicked += delegate + { + bool newValue = !_partLockMap[partSelection]; + _partLockMap[partSelection] = newValue; + + if (newValue) + { + partSelection.SetEnabled(false); + removeButton.SetEnabled(false); + nextButton.SetEnabled(false); + previousButton.SetEnabled(false); + randomButton.SetEnabled(false); + lockImage.image = EditorGUIUtility.IconContent("LockIcon-On", "|Unlock Part").image; + lockButton.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f); + } + else + { + partSelection.SetEnabled(true); + removeButton.SetEnabled(true); + nextButton.SetEnabled(true); + previousButton.SetEnabled(true); + randomButton.SetEnabled(true); + PartSelectionChangeEvent(new ChangeEvent(), type, controls); + lockImage.image = EditorGUIUtility.IconContent("LockIcon", "|Lock Part").image; + lockButton.style.backgroundColor = new Color(0.345098f, 0.345098f, 0.345098f); + } + }; + + if (_processingSpeciesChange) + { + ChangeEvent changeEvent = ChangeEvent.GetPooled(_previousPartSelections[type], currentSelection); + PartSelectionChangeEvent(changeEvent, type, controls); + changeEvent.Dispose(); + } + + _partSelectionDictionary.Add(type, controls); + + removeButton.clickable.clicked += delegate + { + partSelection.value = "None"; + }; + + previousButton.clickable.clicked += delegate + { + int newIndex = partSelection.index - 1; + if (newIndex <= 0) + { + newIndex = 0; + } + + partSelection.index = newIndex; + }; + + nextButton.clickable.clicked += delegate + { + int newIndex = partSelection.index + 1; + if (newIndex >= partSelection.choices.Count - 1) + { + newIndex = partSelection.choices.Count - 1; + } + + partSelection.index = newIndex; + }; + + randomButton.clickable.clicked += delegate + { + int currentIndex = partSelection.index; + if (partSelection.choices.Count - 1 > 1) + { + while (partSelection.index == currentIndex) + { + partSelection.index = Random.Range(1, partSelection.choices.Count); + } + } + }; + + partContainer.Add(partTypeTitle); + partContainer.Add(lockButton); + partContainer.Add(removeButton); + partContainer.Add(previousButton); + partContainer.Add(nextButton); + partContainer.Add(randomButton); + partContainer.Add(partSelection); + } + + private void UpdatePartDropdowns() + { + Dictionary> filteredParts = _appliedPartFilters.GetFilteredParts(); + Dictionary> baseParts = _sidekickRuntime.MappedBasePartDictionary[_currentSpecies]; + + foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) + { + PartTypeControls controls = _partSelectionDictionary[type]; + HashSet popupItems = new HashSet(); + + if (type != CharacterPartType.Wrap) + { + popupItems.Add("None"); + }; + + HashSet itemList = baseParts.TryGetValue(type, out List items) ? items.ToHashSet() : new HashSet(); + popupItems.UnionWith(itemList); + itemList = filteredParts.TryGetValue(type, out List filteredItems) ? filteredItems.ToHashSet() : new HashSet(); + popupItems.UnionWith(itemList); + + List popupValues = popupItems.ToList(); + + _currentCharacter.TryGetValue(type, out SidekickPart selectedPart); + string currentSelection = selectedPart?.Name ?? "None"; + if (_processingSpeciesChange) + { + if (popupValues.Count < 1 || (popupValues.Count == 1 && popupValues[0] == "None")) + { + _previousPartSelections[type] = currentSelection; + currentSelection = "None"; + } + else if (PartUtils.IsBaseSpeciesPart(currentSelection)) + { + _previousPartSelections[type] = currentSelection; + currentSelection = popupValues.Find(n => n.Contains("BASE")) ?? "None"; + } + else if (currentSelection == "None" && _previousPartSelections[type] != "None" && popupValues.Count > 1) + { + currentSelection = _previousPartSelections[type]; + _previousPartSelections[type] = "None"; + } + + if (!popupValues.Contains(currentSelection)) + { + _previousPartSelections[type] = currentSelection; + currentSelection = FindClosestPartMatch(popupValues, currentSelection); + } + } + + if (type == CharacterPartType.Wrap && currentSelection == "None") + { + currentSelection = null; + } + + controls.UpdateDropdownValues(popupValues); + controls.SetPartDropdownValue(currentSelection); + controls.UpdateControls(); + } + } + + /// + /// Process the change event when a new part is selected. + /// + /// The change event to process. + /// The type of part that has been changed. + /// The UI PopupField the change event is happening for. + private void PartSelectionChangeEvent(ChangeEvent changeEvent, CharacterPartType type, PartTypeControls partSelection) + { + try + { + if (_currentTab == TabView.Parts + && _sidekickRuntime.MappedPartDictionary.ContainsKey(type) + && changeEvent.newValue != null + && _sidekickRuntime.MappedPartDictionary[type].TryGetValue(changeEvent.newValue, out SidekickPart selectedPart)) + { + + GameObject partModel = selectedPart.GetPartModel(); + SkinnedMeshRenderer selectedMesh = partModel.GetComponentInChildren(); + _partDictionary[type] = selectedMesh; + _currentCharacter[type] = selectedPart; + + if (!_processingSpeciesChange) + { + _previousPartSelections[type] = changeEvent.newValue; + } + + if (type == CharacterPartType.Torso) + { + _requiresWrap = selectedPart.UsesWrap; + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) + { + if (_requiresWrap) + { + wrapSelection.PartDropdown.SetEnabled(true); + wrapSelection.RandomisePartDropdownValue(); + ; + } + else + { + wrapSelection.PartDropdown.SetEnabled(false); + wrapSelection.SetPartDropdownValue(null); + } + } + } + } + else if (changeEvent.newValue == "None") + { + _currentCharacter.Remove(type); + _partDictionary.Remove(type); + if (!_processingSpeciesChange) + { + _previousPartSelections[type] = "None"; + } + + if (type == CharacterPartType.Torso) + { + if (_partSelectionDictionary.TryGetValue(CharacterPartType.Wrap, out PartTypeControls wrapSelection)) + { + wrapSelection.PartDropdown.SetEnabled(false); + wrapSelection.SetPartDropdownValue(null); + _currentCharacter.Remove(CharacterPartType.Wrap); + } + } + } + else + { + _partDictionary.Remove(type); + } + + if (!_applyingPreset && _previewToggle.value) + { + // if (_combineMeshes && _newModel != null) + // { + // DestroyImmediate(_newModel); + // } + + _newModel = GenerateCharacter(false, true); + bool switchAnimation = SetupAnimationControllers(); + + if (switchAnimation && (type == CharacterPartType.HandLeft || type == CharacterPartType.HandRight)) + { + SetState("InspectHands"); + } + + UpdatePartUVData(); + } + + partSelection.UpdateControls(); + } + catch (Exception ex) + { + EditorUtility.DisplayDialog("Failed loading part", "Failed to load the following part\n" + changeEvent.newValue, "OK"); + Debug.LogWarning(ex); + } + } + + /// + /// Selects the first match, with the highest number of matching terms from a list of parts. + /// + /// The list of parts. + /// The part to find the closest match for. + /// The part with the closest match to the given part. + private string FindClosestPartMatch(List availableParts, string existingPart) + { + string closestMatch = "None"; + List partSections = existingPart.Split("_").ToList(); + Dictionary matchCounts = new Dictionary(); + foreach (string section in partSections) + { + foreach (string part in availableParts) + { + if (part.Contains(section)) + { + if (matchCounts.TryGetValue(part, out int count)) + { + matchCounts[part] = count + 1; + } + else + { + matchCounts[part] = 1; + } + } + } + } + + int currentMax = 0; + + foreach (KeyValuePair match in matchCounts) + { + if (match.Value > currentMax) + { + closestMatch = match.Key; + currentMax = match.Value; + } + } + + return closestMatch; + } + + /// + /// Generates a character from the current selected parts. + /// + private GameObject GenerateCharacter(bool combineMesh, bool processBoneMovement) + { + List parts = new List(); + foreach (KeyValuePair entry in _currentCharacter) + { + if (entry.Value != null) + { + // Only apply wrap when required + if (entry.Key == CharacterPartType.Wrap && (!_requiresWrap || _bodyTypeBlendValue < 0)) + { + continue; + } + + GameObject partModel = entry.Value.GetPartModel(); + + if (partModel == null) + { + if (_showMissingPartsPopup) + { + EditorUtility.DisplayDialog( + "Error loading part", + "Unable to load part: " + entry.Value.Name + ".", + "Ok" + ); + } + continue; + } + + SkinnedMeshRenderer selectedMesh = partModel.GetComponentInChildren(); + if (selectedMesh != null) + { + parts.Add(selectedMesh); + } + } + } + + GameObject newModel = null; + try + { + newModel = _sidekickRuntime.CreateCharacter( _OUTPUT_MODEL_NAME, parts, combineMesh, processBoneMovement, _newModel); + _currentAnimator = null; + } + catch (Exception ex) + { + EditorUtility.DisplayDialog( + "Error creating character", + "Something went wrong when creating the character.\nPlease try again.", + "Ok" + ); + Debug.LogWarning(ex); + } + + return newModel; + } + + /// + /// Saves a character (Parts and Colors) out to a file which can be imported by the tool into any project. + /// + private void SaveCharacter() + { + try + { + SaveCharacter(null); + } + catch + { + Debug.LogWarning("Failed to save character. Please try again."); + } + } + + /// + /// Saves a character (Parts and Colors) out to a file which can be imported by the tool into any project to a given path. + /// + /// The path to save the character to. + private void SaveCharacter(string savePath) + { + bool showSuccessMessage = false; + + if (string.IsNullOrEmpty(savePath)) + { + savePath = ShowCharacterSaveDialog(); + showSuccessMessage = true; + } + + if (string.IsNullOrEmpty(savePath)) + { + // EditorUtility.DisplayDialog("Save Cancelled", "No save file selected. Saving cancelled.", "OK"); + return; + } + + string filename = Path.GetFileNameWithoutExtension(savePath); + SerializedCharacter savedCharacter = CreateSerializedCharacter(filename); + + Serializer serializer = new Serializer(); + + File.WriteAllBytes(savePath, Encoding.ASCII.GetBytes(serializer.Serialize(savedCharacter))); + if (showSuccessMessage) + { + EditorUtility.DisplayDialog("Save Successful", "Character successfully saved to " + Path.GetFileName(savePath), "OK"); + } + } + + /// + /// Crates a serialized character from the current tool selections. + /// + /// The name to store in the serialized character. + /// A SerializedCharacter from the selections in the tool. + private SerializedCharacter CreateSerializedCharacter(string characterName) + { + SerializedCharacter savedCharacter = new SerializedCharacter + { + Species = _currentSpecies.ID, + Name = characterName + }; + + List usedParts = new List(); + foreach (KeyValuePair entry in _currentCharacter) + { + // TODO: Update the part version to use actual version once the information is available. + usedParts.Add(new SerializedPart(entry.Value.Name, entry.Key, "1")); + } + + savedCharacter.Parts = usedParts; + SerializedColorSet savedSet = new SerializedColorSet(); + savedSet.PopulateFromSidekickColorSet(_currentColorSet, _currentSpecies); + savedCharacter.ColorSet = savedSet; + + savedCharacter.BlendShapes = new SerializedBlendShapeValues() + { + BodyTypeValue = _bodyTypeSlider.value, + BodySizeValue = _bodySizeSlider.value, + MuscleValue = _musclesSlider.value + }; + + List savedColorRows = new List(); + foreach (SidekickColorRow row in _allColorRows) + { + savedColorRows.Add(new SerializedColorRow(row)); + } + + savedCharacter.ColorRows = savedColorRows; + + return savedCharacter; + } + + /// + /// Loads a character (Parts and Colors) into the tool. + /// + private void LoadCharacter() + { + _loadingCharacter = true; + bool showAllColors = _showAllColourProperties; + _showAllColourProperties = true; + + string filePath = EditorUtility.OpenFilePanel("Load Character", "", "sk"); + if (string.IsNullOrEmpty(filePath)) + { + EditorUtility.DisplayDialog("No File Chosen", "No file was chosen to load.", "OK"); + return; + } + + _bodyPartsTab.value = true; + SwitchToTab(TabView.Parts); + + byte[] bytes = File.ReadAllBytes(filePath); + string data = Encoding.ASCII.GetString(bytes); + + Deserializer deserializer = new Deserializer(); + SerializedCharacter savedCharacter = deserializer.Deserialize(data); + + LoadSerializedCharacter(savedCharacter, showAllColors); + _loadingCharacter = false; + } + + /// + /// Loads a character into the tool from a serialized character. + /// + /// The serialized character to load. + /// Whether to show all colors or not. + private void LoadSerializedCharacter(SerializedCharacter serializedCharacter, bool showAllColors) + { + SidekickSpecies species = SidekickSpecies.GetByID(_dbManager, serializedCharacter.Species); + _speciesField.value = species.Name; + ProcessSpeciesChange(species.Name); + + bool hasErrors = false; + string errorMessage = "The following parts could not be found in your project:\n"; + foreach (CharacterPartType currentType in Enum.GetValues(typeof(CharacterPartType))) + { + PartTypeControls currentField = _partSelectionDictionary[currentType]; + SerializedPart part = serializedCharacter.Parts.FirstOrDefault(p => p.PartType == currentType); + SidekickPart skPart = SidekickPart.SearchForByName(_dbManager, part?.Name); + if (skPart != null) + { + UpdateResult result = UpdatePartDropdown(currentField, skPart.Name, errorMessage, hasErrors); + hasErrors = result.HasErrors; + errorMessage = result.ErrorMessage; + } + else + { + currentField.SetPartDropdownValue("None"); + } + } + + if (hasErrors) + { + EditorUtility.DisplayDialog( + "Assets Missing", + errorMessage, + "OK" + ); + } + + + LoadColorSet(serializedCharacter); + + if (serializedCharacter.BlendShapes != null) + { + LoadBlendShapes(serializedCharacter); + } + + _showAllColourProperties = showAllColors; + UpdateColorTabContent(); + + if (_combineMeshes && _newModel != null) + { + DestroyImmediate(_newModel); + } + + _newModel = GenerateCharacter(_combineMeshes, true); + UpdatePartUVData(); + } + + /// + /// Updates a part dropdown to select a new part, if the part is not in the dropdown values, `None` is selected instead. + /// + /// The dropdown field to update. + /// The new part to select. + /// The error message to update if the part is not available. + /// The error flag to update if an error is encountered. + /// A PartUpdateResult with the results of the update. + private UpdateResult UpdatePartDropdown(PartTypeControls currentField, string partName, string errorMessage, bool hasErrors) + { + _partLockMap[currentField.PartDropdown] = false; + + if (partName == "None" || _allParts.Any(part => part.Name == partName)) + { + if (!currentField.PartDropdown.choices.Contains(partName) && PartUtils.IsBaseSpeciesPart(partName)) + { + currentField.SetPartDropdownValue(currentField.PartDropdown.choices.Find(n => n.Contains("BASE")) ?? "None"); + if (currentField.PartDropdown.value == "None") + { + hasErrors = true; + errorMessage += partName + "\n"; + } + } + else + { + currentField.SetPartDropdownValue(partName); + } + } + else if (PartUtils.IsBaseSpeciesPart(partName)) + { + currentField.SetPartDropdownValue(currentField.PartDropdown.choices.Find(n => n.Contains("BASE")) ?? "None"); + if (currentField.PartDropdown.value == "None") + { + hasErrors = true; + errorMessage += partName + "\n"; + } + } + else + { + currentField.SetPartDropdownValue("None"); + hasErrors = true; + errorMessage += partName + "\n"; + } + + return new UpdateResult(errorMessage, hasErrors); + } + + /// + /// Loads the color set for a saved character into memory. + /// + /// The character to load the color set for. + private void LoadColorSet(SerializedCharacter savedCharacter) + { + _currentColorSet = savedCharacter.ColorSet.CreateSidekickColorSet(_dbManager); + _colorSetsDropdown.value = "Custom"; + + List newRows = new List(); + foreach (SerializedColorRow row in savedCharacter.ColorRows) + { + newRows.Add(row.CreateSidekickColorRow(_dbManager, _currentColorSet)); + } + + _allColorRows = newRows; + UpdateColorTabContent(); + } + + /// + /// Updates the content of the Color Tab. + /// + private void UpdateColorTabContent() + { + PopulatePartColorRows(); + UpdateAllVisibleColors(); + RefreshVisibleColorRows(); + } + + /// + /// Loads the blend shapes from a saved character into the tool. + /// + /// The character to load the blend shapes for. + private void LoadBlendShapes(SerializedCharacter savedCharacter) + { + _bodyTypeSlider.value = savedCharacter.BlendShapes.BodyTypeValue; + _bodySizeSlider.value = savedCharacter.BlendShapes.BodySizeValue; + _musclesSlider.value = savedCharacter.BlendShapes.MuscleValue; + } + + /// + /// Shows the dialog box for where to save the character to, and also validates the save location and filename. + /// + /// The default path to save to. + /// The full file path and filename to save the character to. + private string ShowCharacterSaveDialog(string path = "") + { + string defaultName = _currentSpecies.Name + "-" + _currentColorSet.Name + ".sk"; + string defaultDirectory = ""; + if (!string.IsNullOrEmpty(path)) + { + defaultName = Path.GetFileName(path); + defaultDirectory = Path.GetDirectoryName(path); + } + + string savePath = EditorUtility.SaveFilePanel( + "Save New Character", + defaultDirectory, + defaultName, + "sk" + ); + + // if (!string.IsNullOrEmpty(savePath) && File.Exists(savePath)) + // { + // int option = EditorUtility.DisplayDialogComplex( + // "File Already Exists", + // "A file already exists with the same name, are you sure you wish to overwrite it?\nThis cannot be undone.", + // "Overwrite", + // "Rename", + // "Cancel" + // ); + // + // switch (option) + // { + // // Overwrite. + // case 0: + // EditorUtility.DisplayDialog("Overwrite Accepted", "Existing file will be overwritten.", "OK"); + // break; + // + // // Rename. + // case 1: + // savePath = ShowCharacterSaveDialog(savePath); + // break; + // + // // Cancel. + // case 2: + // default: + // savePath = null; + // break; + // } + // } + + return savePath; + } + + /// + /// Saves a created character as a prefab. + /// + private void CreateCharacterPrefab() + { + try + { + string savePath = SelectPrefabSaveLocation(); + + if (string.IsNullOrEmpty(savePath)) + { + // EditorUtility.DisplayDialog("Save Cancelled", "No save file selected. Saving cancelled.", "OK"); + return; + } + + string baseFilename = Path.GetFileNameWithoutExtension(savePath); + string directoryBase = Path.GetDirectoryName(savePath) ?? string.Empty; + string directory = Path.Combine(directoryBase, baseFilename); + savePath = Path.Combine(directory, Path.GetFileName(savePath)); + string textureDirectory = Path.Combine(directory, "Textures"); + string meshDirectory = Path.Combine(directory, "Meshes"); + string materialDirectory = Path.Combine(directory, "Materials"); + + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + if (!Directory.Exists(meshDirectory)) + { + Directory.CreateDirectory(meshDirectory); + } + + if (!Directory.Exists(materialDirectory)) + { + Directory.CreateDirectory(materialDirectory); + } + + string savedCharacterPath = Path.Combine(directory, baseFilename + ".sk"); + SaveCharacter(savedCharacterPath); + + //TODO textures are shared between exports! + SaveTexturesToDisk(textureDirectory, baseFilename); + // Ensure textures are written to disk before proceeding. As it seems this happens outside the main Unity loop, so can't be easily checked + // for. + int cutoff = 0; + while (cutoff < 1000000000 && Directory.GetFiles(textureDirectory).Length <= 0) + { + cutoff++; + } + + AssetDatabase.Refresh(); + + GameObject clonedModel = GenerateCharacter(_combineMeshes, false); + + List allRenderers = clonedModel.GetComponentsInChildren().ToList(); + SkinnedMeshRenderer clonedRenderer = allRenderers[0]; + + if (_bakeBlends) + { + + // Copy mesh, bone weights and bindposes before baking so the mesh can be re-skinned after baking. + foreach (SkinnedMeshRenderer renderer in allRenderers) + { + if (clonedRenderer == null) + { + clonedRenderer = renderer; + } + + Mesh clonedSkinnedMesh = MeshUtils.CopyMesh(renderer.sharedMesh); + BoneWeight[] boneWeights = clonedSkinnedMesh.boneWeights; + Matrix4x4[] bindposes = clonedSkinnedMesh.bindposes; + List blendData = BlendShapeUtils.GetBlendShapeData( + clonedSkinnedMesh, + renderer, + new string[] + { + "defaultHeavy", "defaultBuff", "defaultSkinny", "masculineFeminine" + }, + 0, + new List() + ); + renderer.BakeMesh(clonedSkinnedMesh); + // Re-skin the new baked mesh. + clonedSkinnedMesh.boneWeights = boneWeights; + clonedSkinnedMesh.bindposes = bindposes; + // assign the new mesh to the renderer + renderer.sharedMesh = clonedSkinnedMesh; + + BlendShapeUtils.RestoreBlendShapeData(blendData, clonedSkinnedMesh, renderer); + } + } + + // now do the bone movements! + _sidekickRuntime.ProcessRigMovementOnBlendShapeChange(SidekickBlendShapeRigMovement.GetAllForProcessing(_dbManager)); + _sidekickRuntime.ProcessBoneMovement(clonedModel); + + Material newMaterial = CreateNewMaterialAssetFromSource( + clonedRenderer.sharedMaterial, + textureDirectory, + materialDirectory, + baseFilename, + baseFilename + ); + + foreach (SkinnedMeshRenderer renderer in allRenderers) + { + renderer.sharedMaterial = newMaterial; + } + + CreatePrefab(clonedModel, meshDirectory, savePath, baseFilename); + DestroyImmediate(clonedModel); + } + catch + { + Debug.LogWarning("Failed to create character prefab, please try again."); + } + } + + /// + /// Prompts the user to select a path and prefab name within the project. + /// + /// The path and filename to use to save the prefab to. + private string SelectPrefabSaveLocation() + { + string defaultName = _currentSpecies.Name + "-" + _currentColorSet.Name + ".prefab"; + + string savePath = EditorUtility.SaveFilePanelInProject( + "Save Character Prefab", + defaultName, + "prefab", + "Select where to save the prefab" + ); + + return savePath; + } + + /// + /// Sets the material to use the textures at the given location. + /// + /// The material to set the textures on. + /// The path to set the textures from. + /// Additional naming for the textures, if applicable. + /// The material with the paths set on it. + private Material SetTextureLinkOnMaterial(Material material, string texturePath, string textureName = "") + { + string filename = _TEXTURE_PREFIX; + + if (!string.IsNullOrEmpty(textureName)) + { + filename += textureName; + } + + material.SetTexture(_COLOR_MAP, null); + LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_COLOR_NAME, _COLOR_MAP); + // TODO: Uncomment when the shader has the these properties are enabled again + // material.SetTexture(_METALLIC_MAP, null); + // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_METALLIC_NAME, _METALLIC_MAP); + // material.SetTexture(_SMOOTHNESS_MAP, null); + // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_SMOOTHNESS_NAME, _SMOOTHNESS_MAP); + // material.SetTexture(_REFLECTION_MAP, null); + // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_REFLECTION_NAME, _REFLECTION_MAP); + // material.SetTexture(_EMISSION_MAP, null); + // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_EMISSION_NAME, _EMISSION_MAP); + // material.SetTexture(_OPACITY_MAP, null); + // LoadAndAssignTexture(material, texturePath, filename + _TEXTURE_OPACITY_NAME, _OPACITY_MAP); + + return material; + } + + /// + /// Loads a texture from disk and assigns it to the material in the given texture ID. + /// + /// The material to assign the texture to. + /// The path to load the texture from. + /// The name of the texture to load. + /// The texture ID to load the texture into on the material. + private void LoadAndAssignTexture(Material material, string texturePath, string textureName, int textureID) + { + string filePath = Path.Combine(texturePath, textureName); + while (material.GetTexture(textureID) == null) + { + TextureImporter textureImporter = AssetImporter.GetAtPath(filePath) as TextureImporter; + if (textureImporter != null) + { + textureImporter.wrapMode = TextureWrapMode.Clamp; + textureImporter.filterMode = FilterMode.Point; + textureImporter.mipmapEnabled = false; + textureImporter.SetPlatformTextureSettings(new TextureImporterPlatformSettings + { + maxTextureSize = 32, + resizeAlgorithm = TextureResizeAlgorithm.Bilinear, + format = TextureImporterFormat.RGB24 + }); + EditorUtility.SetDirty(textureImporter); + textureImporter.SaveAndReimport(); + } + + material.SetTexture(textureID, (Texture2D) AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture2D))); + } + } + + /// + /// Creates a new material to assign to the prefab. + /// + /// The existing material from the base model. + /// The directory to save the textures into. + /// The directory to save the material into. + /// The base filename to use for all assets. + /// Additional naming for the textures, if applicable. + /// The new material cloned from sourceMaterial saved to the asset database. + private Material CreateNewMaterialAssetFromSource( + Material sourceMaterial, + string textureDirectory, + string materialDirectory, + string baseFilename, + string textureName = "" + ) + { + Material clonedMaterial = new Material(sourceMaterial.shader); + // NOTE: this is copying the texture slots from oldMaterial, so they need to be null'd afterward in SetTextureLinkOnMaterial() + clonedMaterial.CopyPropertiesFromMaterial(sourceMaterial); + clonedMaterial = SetTextureLinkOnMaterial(clonedMaterial, textureDirectory, textureName); + string materialPath = Path.Combine(materialDirectory, baseFilename + ".mat"); + // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. + if (File.Exists(materialPath)) + { + File.Delete(materialPath); + } + + AssetDatabase.CreateAsset(clonedMaterial, materialPath); + return clonedMaterial; + } + + /// + /// Creates a prefab and the required assets for the model to work as an independent asset. + /// + /// Root game object for the prefab. + /// The directory to save the mesh and avatar assets to. + /// The path to save the prefab to. + /// The base filename to use for all assets. + private void CreatePrefab( + GameObject rootGameObject, + string meshDirectory, + string savePath, + string baseFilename + ) + { + List renderers = rootGameObject.GetComponentsInChildren().ToList(); + foreach (SkinnedMeshRenderer renderer in renderers) + { + string type = null; + if (renderer.name.Contains("_")) + { + type = Enum.GetName(typeof(CharacterPartType), _sidekickRuntime.ExtractPartType(renderer.name)); + } + Mesh sharedMesh = renderer.sharedMesh; + string meshPath = type == null ? Path.Combine(meshDirectory, baseFilename + ".asset") : Path.Combine(meshDirectory, baseFilename + "-" + type + ".asset"); + // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. + if (File.Exists(meshPath)) + { + File.Delete(meshPath); + } + + AssetDatabase.CreateAsset(sharedMesh, meshPath); + } + + Animator animator = rootGameObject.GetComponentInChildren(); + Avatar existingAvatar = animator.avatar; + Avatar newAvatar = Instantiate(existingAvatar); + animator.avatar = newAvatar; + string avatarPath = Path.Combine(meshDirectory, baseFilename + "-avatar.asset"); + // If the user has chosen to overwrite the prefab, delete the existing assets to replace them. + if (File.Exists(avatarPath)) + { + File.Delete(avatarPath); + } + + AssetDatabase.CreateAsset(newAvatar, avatarPath); + AssetDatabase.SaveAssets(); + PrefabUtility.SaveAsPrefabAsset(rootGameObject, savePath); + } + + /// + /// Gets the "outfit" name from the part name. + /// TODO: This will be replaced once parts and outfits have a proper relationship. + /// + /// The part name to parse the "outfit" name from. + /// The "outfit" name. + private string GetOutfitNameFromPartName(string partName) + { + if (string.IsNullOrEmpty(partName)) + { + return "None"; + } + + return string.Join('_', partName.Substring(3).Split('_').Take(2)); + } + + /// + /// Updates the part UV data. + /// + private void UpdatePartUVData() + { + _currentUVDictionary = _sidekickRuntime.CurrentUVDictionary; + _currentUVList = _sidekickRuntime.CurrentUVList; + } + + /// + /// The available tab views + /// + private enum TabView + { + Preset, + Parts, + Body, + Colors, + Decals, + Options + } + + /// + /// The different types of preset dropdown + /// + private enum PresetDropdownType + { + Part, + Body, + Color, + Texture + } + + /// + /// Encapsulates the result from a dropdown update attempt. + /// + private class UpdateResult + { + public string ErrorMessage { get; private set; } + public bool HasErrors { get; private set; } + + public UpdateResult(string errorMessage, bool hasErrors) + { + ErrorMessage = errorMessage; + HasErrors = hasErrors; + } + } + } +} +#endif diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Editor/ModularCharacterWindow.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs b/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs old mode 100644 new mode 100755 index 0601f924..ed26f10a --- a/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -namespace Synty.SidekickCharacters -{ - public class DatabaseUpdateController - { - // This class is no longer required, and will be deleted in the future. - // Included as an empty class to remove code dependencies to allow for deletion without causing project errors. - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +namespace Synty.SidekickCharacters +{ + public class DatabaseUpdateController + { + // This class is no longer required, and will be deleted in the future. + // Included as an empty class to remove code dependencies to allow for deletion without causing project errors. + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Editor/UI/DatabaseUpdateController.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs b/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs old mode 100644 new mode 100755 index c162b780..2d0d8946 --- a/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs @@ -1,396 +1,354 @@ -// Copyright (c) 2025 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using UnityEditor; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Synty.SidekickCharacters -{ - public class ToolDownloader : EditorWindow - { - private const string _GIT_URL = "https://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/download/Sidekicks.unitypackage"; - private const string _GIT_DB_URL = "https://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/download/SidekicksDatabase.unitypackage"; - private const string _PACKAGE_CACHE = "Assets/DownloadCache/Sidekicks.unitypackage"; - private const string _DB_PACKAGE_CACHE = "Assets/DownloadCache/SidekicksDatabase.unitypackage"; - private const string _VERSION_FILE_NAME = "version.txt"; - private const string _VERSION_TAG = "\"tag_name\":"; - private const string _VERSION_KEY = "sk_current_tool_version"; - private const string _SIDEKICK_TOOL_MENU_ITEM = "Synty/Sidekick Character Tool"; - - private string _version = "-"; - private Label _latestVersion; - - public void Awake() - { - BackgroundUpdateCheck(); - } - - public void CreateGUI() - { - VisualElement root = rootVisualElement; - root.Clear(); - Button downloadButton = new Button(DownloadLatestDBVersion) - { - text = "Download and Install", - style = - { - height = 40 - } - }; - - root.Add(downloadButton); - - Label textPrompt = new Label("This tool will download and install the latest version of the Sidekicks Tool."); - Label textPrompt2 = new Label("Or you can manually download from this link:\nhttps://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/"); - - root.Add(textPrompt); - root.Add(textPrompt2); - - string version = LoadCurrentInstalledVersion(); - Label currentVersion = new Label("Currently Installed: " + (string.IsNullOrEmpty(version) ? "N/A" : version)) - { - style = - { - marginTop = 5 - } - }; - - _latestVersion = new Label("Latest Version: " + _version); - - root.Add(currentVersion); - root.Add(_latestVersion); - - Button changeLogButton = new Button() - { - text = "Show Changelog" - }; - - root.Add(changeLogButton); - - changeLogButton.clickable.clicked += delegate - { - Application.OpenURL("https://syntystore.com/pages/sidekicks-changelog"); - }; - } - - public async void BackgroundUpdateCheck() - { - _version = await CheckAvailableVersion(); - - if (_latestVersion != null) - { - _latestVersion.text = "Latest Version: " + _version; - } - if (IsNewVersionAvailable(_version)) - { - DownloaderBackgroundService.ShowToolDownloaderWindow(); - } - } - - private async Task CheckAvailableVersion() - { - HttpClient client = new HttpClient(); - - string uri = "http://api.github.com/repos/SyntyStudios/SidekicksToolRelease/releases/latest"; - - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); - request.Headers.Add("Accept", "application/vnd.github+json"); - request.Headers.Add("X-GitHub-Api-Version", "2022-11-28"); - request.Headers.Add("User-Agent", "Sidekicks Download Tool"); - - HttpResponseMessage response = await client.SendAsync(request); - - response.EnsureSuccessStatusCode(); - - // Read the response content as a string - string responseBody = await response.Content.ReadAsStringAsync(); - - return GetVersionNumber(responseBody); - } - - private string GetVersionNumber(string data) - { - int index = data.IndexOf(_VERSION_TAG, StringComparison.OrdinalIgnoreCase) + _VERSION_TAG.Length; - string portion = data.Substring(index, data.Length - index); - string number = portion.Substring(0, portion.IndexOf(',')).Replace("\"", "").Replace(" ", ""); - return number; - } - - private bool IsNewVersionAvailable(string version) - { - string currentVersion = LoadCurrentInstalledVersion(); - if (string.IsNullOrEmpty(currentVersion)) - { - return true; - } - - if (!currentVersion.Contains('.') || !version.Contains('.')) - { - return false; - } - - string[] currentSplitVersion = currentVersion.Split('.'); - string[] newSplitVersion = version.Split('.'); - - if (currentSplitVersion.Length != newSplitVersion.Length) - { - return false; - } - - for (int i = 0; i < newSplitVersion.Length; i++) - { - if (int.TryParse(currentSplitVersion[i], out int current)) - { - if (int.TryParse(newSplitVersion[i], out int newVersion)) - { - if (newVersion > current) - { - return true; - } - } - } - } - - return false; - } - - private void SaveCurrentInstalledVersion(string version) - { - string versionFilePath = GetVersionFilePath(); - if (string.IsNullOrEmpty(versionFilePath)) - { - Debug.LogWarning("Unable to resolve Sidekick version file path."); - return; - } - - File.WriteAllText(versionFilePath, version); - } - - private string LoadCurrentInstalledVersion() - { - string versionFilePath = GetVersionFilePath(); - if (string.IsNullOrEmpty(versionFilePath)) - { - return null; - } - - if (File.Exists(versionFilePath)) - { - return File.ReadAllText(versionFilePath); - } - - return null; - } - - private string GetVersionFilePath() - { - MonoScript currentScript = MonoScript.FromScriptableObject(this); - if (currentScript == null) - { - return null; - } - - string scriptPath = AssetDatabase.GetAssetPath(currentScript); - if (string.IsNullOrEmpty(scriptPath)) - { - return null; - } - - string utilityDirectory = Path.GetDirectoryName(scriptPath); - if (string.IsNullOrEmpty(utilityDirectory)) - { - return null; - } - - string editorDirectory = Path.GetDirectoryName(utilityDirectory); - if (string.IsNullOrEmpty(editorDirectory)) - { - return null; - } - - return Path.GetFullPath(Path.Combine(editorDirectory, _VERSION_FILE_NAME)); - } - - private void DownloadLatestDBVersion() - { - WebClient client = new WebClient(); - client.DownloadFileCompleted += (sender, e) => - { - if (e.Error == null) - { - CloseOpenToolWindow(); - AssetDatabase.ImportPackage(_DB_PACKAGE_CACHE, false); - AssetDatabase.importPackageCompleted += ProceedWithInstall; - } - else - { - Debug.LogError("Error downloading file: " + e.Error.Message); - } - }; - - // Ensure the directory exists - string directory = Path.GetDirectoryName(_DB_PACKAGE_CACHE); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - - client.DownloadFileAsync(new System.Uri(_GIT_DB_URL), _DB_PACKAGE_CACHE); - } - - private async void DownloadLatestToolVersion() - { - WebClient client = new WebClient(); - _version = await CheckAvailableVersion(); - client.DownloadFileCompleted += (sender, e) => - { - if (e.Error == null) - { - SaveCurrentInstalledVersion(_version); - AssetDatabase.ImportPackage(_PACKAGE_CACHE, false); - AssetDatabase.importPackageCompleted += ProceedWithInstall; - } - else - { - Debug.LogError("Error downloading file: " + e.Error.Message); - } - }; - - // Ensure the directory exists - string directory = Path.GetDirectoryName(_PACKAGE_CACHE); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - - client.DownloadFileAsync(new System.Uri(_GIT_URL), _PACKAGE_CACHE); - } - - private void ProceedWithInstall(string packageName) - { - if (packageName == "SidekicksDatabase") - { - AssetDatabase.importPackageCompleted -= ProceedWithInstall; - DownloadLatestToolVersion(); - } - else if (packageName == "Sidekicks") - { - AssetDatabase.importPackageCompleted -= ProceedWithInstall; - DownloaderBackgroundService.RefreshWindow(); - - if (EditorUtility.DisplayDialog("Installation Finished", "Sidekick Tool installation has completed.", "Re-open Sidekicks Tool", - "Close")) - { - ReopenToolWindow(); - } - } - } - - private bool CloseOpenToolWindow() - { - EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll(); - - // Filter the windows to find the one with the desired type name - EditorWindow foundWindow = allWindows.FirstOrDefault(window => window.GetType().Name == "ModularCharacterWindow"); - - if (foundWindow != null) - { - foundWindow.Close(); - Thread.Sleep(1500); - return true; - } - - return false; - } - - private void ReopenToolWindow() - { - try - { - EditorApplication.ExecuteMenuItem(_SIDEKICK_TOOL_MENU_ITEM); - } - catch (Exception ex) - { - Debug.LogWarning("Sidekicks Tool menu item not found. Please verify installation."); - Debug.LogWarning("Exception details: " + ex.Message); - } - } - } - - /// - /// Creates an instance of the Downloader Tool, to allow checks for new versions on editor startup. - /// - [InitializeOnLoad] - public static class DownloaderBackgroundService - { - private static ToolDownloader _instance; - - static DownloaderBackgroundService() - { - EditorApplication.update += CreateToolInstance; - } - - static void CreateToolInstance() - { - EditorApplication.update -= CreateToolInstance; - EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll(); - - // Filter the windows to find the one with the desired type name - EditorWindow foundWindow = allWindows.FirstOrDefault(window => window.GetType().Name == "ToolDownloader"); - - if (foundWindow != null) - { - _instance = (ToolDownloader) foundWindow; - } - else - { - _instance = ScriptableObject.CreateInstance(); - } - _instance.titleContent.text = "Sidekick Tool Downloader"; - _instance.minSize = new Vector2(600, 150); - } - - /// - /// Refreshes the Tool Downloader window to ensure it shows the latest version. Repaint is unreliable. - /// - public static void RefreshWindow() - { - if (_instance == null) - { - CreateToolInstance(); - } - - _instance.Close(); - - if (_instance == null) - { - CreateToolInstance(); - } - - _instance.Show(); - } - - [MenuItem("Synty/Sidekick Tool Downloader")] - public static void ShowToolDownloaderWindow() - { - if (_instance == null) - { - CreateToolInstance(); - } - - _instance.Show(); - } - } -} +// Copyright (c) 2025 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Synty.SidekickCharacters +{ + public class ToolDownloader : EditorWindow + { + private const string _GIT_URL = "https://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/download/Sidekicks.unitypackage"; + private const string _GIT_DB_URL = "https://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/download/SidekicksDatabase.unitypackage"; + private const string _PACKAGE_CACHE = "Assets/DownloadCache/Sidekicks.unitypackage"; + private const string _DB_PACKAGE_CACHE = "Assets/DownloadCache/SidekicksDatabase.unitypackage"; + private const string _VERSION_FILE = "Assets/External/Models/SidekickCharacters/Scripts/Editor/version.txt"; + private const string _VERSION_TAG = "\"tag_name\":"; + private const string _VERSION_KEY = "sk_current_tool_version"; + private const string _SIDEKICK_TOOL_MENU_ITEM = "Synty/Sidekick Character Tool"; + + private string _version = "-"; + private Label _latestVersion; + + public void Awake() + { + BackgroundUpdateCheck(); + } + + public void CreateGUI() + { + VisualElement root = rootVisualElement; + root.Clear(); + Button downloadButton = new Button(DownloadLatestDBVersion) + { + text = "Download and Install", + style = + { + height = 40 + } + }; + + root.Add(downloadButton); + + Label textPrompt = new Label("This tool will download and install the latest version of the Sidekicks Tool."); + Label textPrompt2 = new Label("Or you can manually download from this link:\nhttps://github.com/SyntyStudios/SidekicksToolRelease/releases/latest/"); + + root.Add(textPrompt); + root.Add(textPrompt2); + + string version = LoadCurrentInstalledVersion(); + Label currentVersion = new Label("Currently Installed: " + (string.IsNullOrEmpty(version) ? "N/A" : version)) + { + style = + { + marginTop = 5 + } + }; + + _latestVersion = new Label("Latest Version: " + _version); + + root.Add(currentVersion); + root.Add(_latestVersion); + + Button changeLogButton = new Button() + { + text = "Show Changelog" + }; + + root.Add(changeLogButton); + + changeLogButton.clickable.clicked += delegate + { + Application.OpenURL("https://syntystore.com/pages/sidekicks-changelog"); + }; + } + + public async void BackgroundUpdateCheck() + { + _version = await CheckAvailableVersion(); + + if (_latestVersion != null) + { + _latestVersion.text = "Latest Version: " + _version; + } + if (IsNewVersionAvailable(_version)) + { + DownloaderBackgroundService.ShowToolDownloaderWindow(); + } + } + + private async Task CheckAvailableVersion() + { + HttpClient client = new HttpClient(); + + string uri = "http://api.github.com/repos/SyntyStudios/SidekicksToolRelease/releases/latest"; + + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); + request.Headers.Add("Accept", "application/vnd.github+json"); + request.Headers.Add("X-GitHub-Api-Version", "2022-11-28"); + request.Headers.Add("User-Agent", "Sidekicks Download Tool"); + + HttpResponseMessage response = await client.SendAsync(request); + + response.EnsureSuccessStatusCode(); + + // Read the response content as a string + string responseBody = await response.Content.ReadAsStringAsync(); + + return GetVersionNumber(responseBody); + } + + private string GetVersionNumber(string data) + { + int index = data.IndexOf(_VERSION_TAG, StringComparison.OrdinalIgnoreCase) + _VERSION_TAG.Length; + string portion = data.Substring(index, data.Length - index); + string number = portion.Substring(0, portion.IndexOf(',')).Replace("\"", "").Replace(" ", ""); + return number; + } + + private bool IsNewVersionAvailable(string version) + { + string currentVersion = LoadCurrentInstalledVersion(); + if (string.IsNullOrEmpty(currentVersion)) + { + return true; + } + + if (!currentVersion.Contains('.') || !version.Contains('.')) + { + return false; + } + + string[] currentSplitVersion = currentVersion.Split('.'); + string[] newSplitVersion = version.Split('.'); + + if (currentSplitVersion.Length != newSplitVersion.Length) + { + return false; + } + + for (int i = 0; i < newSplitVersion.Length; i++) + { + if (int.TryParse(currentSplitVersion[i], out int current)) + { + if (int.TryParse(newSplitVersion[i], out int newVersion)) + { + if (newVersion > current) + { + return true; + } + } + } + } + + return false; + } + + private void SaveCurrentInstalledVersion(string version) + { + File.WriteAllText(_VERSION_FILE, version); + } + + private string LoadCurrentInstalledVersion() + { + if (File.Exists(_VERSION_FILE)) + { + return File.ReadAllText(_VERSION_FILE); + } + + return null; + } + + private void DownloadLatestDBVersion() + { + WebClient client = new WebClient(); + client.DownloadFileCompleted += (sender, e) => + { + if (e.Error == null) + { + CloseOpenToolWindow(); + AssetDatabase.ImportPackage(_DB_PACKAGE_CACHE, false); + AssetDatabase.importPackageCompleted += ProceedWithInstall; + } + else + { + Debug.LogError("Error downloading file: " + e.Error.Message); + } + }; + + // Ensure the directory exists + string directory = Path.GetDirectoryName(_DB_PACKAGE_CACHE); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + client.DownloadFileAsync(new System.Uri(_GIT_DB_URL), _DB_PACKAGE_CACHE); + } + + private async void DownloadLatestToolVersion() + { + WebClient client = new WebClient(); + _version = await CheckAvailableVersion(); + client.DownloadFileCompleted += (sender, e) => + { + if (e.Error == null) + { + SaveCurrentInstalledVersion(_version); + AssetDatabase.ImportPackage(_PACKAGE_CACHE, false); + AssetDatabase.importPackageCompleted += ProceedWithInstall; + } + else + { + Debug.LogError("Error downloading file: " + e.Error.Message); + } + }; + + // Ensure the directory exists + string directory = Path.GetDirectoryName(_PACKAGE_CACHE); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + client.DownloadFileAsync(new System.Uri(_GIT_URL), _PACKAGE_CACHE); + } + + private void ProceedWithInstall(string packageName) + { + if (packageName == "SidekicksDatabase") + { + AssetDatabase.importPackageCompleted -= ProceedWithInstall; + DownloadLatestToolVersion(); + } + else if (packageName == "Sidekicks") + { + AssetDatabase.importPackageCompleted -= ProceedWithInstall; + DownloaderBackgroundService.RefreshWindow(); + + if (EditorUtility.DisplayDialog("Installation Finished", "Sidekick Tool installation has completed.", "Re-open Sidekicks Tool", + "Close")) + { + ReopenToolWindow(); + } + } + } + + private bool CloseOpenToolWindow() + { + EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll(); + + // Filter the windows to find the one with the desired type name + EditorWindow foundWindow = allWindows.FirstOrDefault(window => window.GetType().Name == "ModularCharacterWindow"); + + if (foundWindow != null) + { + foundWindow.Close(); + Thread.Sleep(1500); + return true; + } + + return false; + } + + private void ReopenToolWindow() + { + try + { + EditorApplication.ExecuteMenuItem(_SIDEKICK_TOOL_MENU_ITEM); + } + catch (Exception ex) + { + Debug.LogWarning("Sidekicks Tool menu item not found. Please verify installation."); + Debug.LogWarning("Exception details: " + ex.Message); + } + } + } + + /// + /// Creates an instance of the Downloader Tool, to allow checks for new versions on editor startup. + /// + [InitializeOnLoad] + public static class DownloaderBackgroundService + { + private static ToolDownloader _instance; + + static DownloaderBackgroundService() + { + EditorApplication.update += CreateToolInstance; + } + + static void CreateToolInstance() + { + EditorApplication.update -= CreateToolInstance; + EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll(); + + // Filter the windows to find the one with the desired type name + EditorWindow foundWindow = allWindows.FirstOrDefault(window => window.GetType().Name == "ToolDownloader"); + + if (foundWindow != null) + { + _instance = (ToolDownloader) foundWindow; + } + else + { + _instance = ScriptableObject.CreateInstance(); + } + _instance.titleContent.text = "Sidekick Tool Downloader"; + _instance.minSize = new Vector2(600, 150); + } + + /// + /// Refreshes the Tool Downloader window to ensure it shows the latest version. Repaint is unreliable. + /// + public static void RefreshWindow() + { + if (_instance == null) + { + CreateToolInstance(); + } + + _instance.Close(); + + if (_instance == null) + { + CreateToolInstance(); + } + + _instance.Show(); + } + + [MenuItem("Synty/Sidekick Tool Downloader")] + public static void ShowToolDownloaderWindow() + { + if (_instance == null) + { + CreateToolInstance(); + } + + _instance.Show(); + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Editor/Utility/ToolDownloader.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Editor/version.txt b/Assets/External/Models/SidekickCharacters/Scripts/Editor/version.txt index 314a62ab..9cc0a9d4 100644 --- a/Assets/External/Models/SidekickCharacters/Scripts/Editor/version.txt +++ b/Assets/External/Models/SidekickCharacters/Scripts/Editor/version.txt @@ -1 +1 @@ -1.0.37 \ No newline at end of file +1.0.38 \ No newline at end of file diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs old mode 100644 new mode 100755 index d38b4db0..52b15710 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs @@ -230,42 +230,6 @@ namespace Synty.SidekickCharacters.API await runtime.PopulatePresetLibrary(); } - private static List GetSidekickPartFiles() - { - string packageRootPath = DatabaseManager.GetPackageRootAbsolutePath(); - if (!string.IsNullOrEmpty(packageRootPath)) - { - string meshesRootPath = Path.Combine(packageRootPath, "Resources", "Meshes"); - if (Directory.Exists(meshesRootPath)) - { - return Directory - .GetFiles(meshesRootPath, "SK_*_*_*_*_*.fbx", SearchOption.AllDirectories) - .Select(ToAssetPath) - .ToList(); - } - } - - return Directory.GetFiles("Assets", "SK_*_*_*_*_*.fbx", SearchOption.AllDirectories).ToList(); - } - - private static string ToAssetPath(string fullPath) - { - if (string.IsNullOrWhiteSpace(fullPath)) - { - return fullPath; - } - - string normalizedFullPath = fullPath.Replace('\\', '/'); - string normalizedAssetsPath = Application.dataPath.Replace('\\', '/'); - - if (!normalizedFullPath.StartsWith(normalizedAssetsPath, StringComparison.OrdinalIgnoreCase)) - { - return normalizedFullPath; - } - - return "Assets" + normalizedFullPath.Substring(normalizedAssetsPath.Length); - } - /// /// Takes all the parts selected in the window, and combines them into a single model in the scene. /// @@ -548,7 +512,7 @@ namespace Synty.SidekickCharacters.API _partOutfitToggleMap = new Dictionary(); _partCount = 0; - List files = GetSidekickPartFiles(); + List files = Directory.GetFiles("Assets", "SK_*_*_*_*_*.fbx", SearchOption.AllDirectories).ToList(); foreach (CharacterPartType partType in Enum.GetValues(typeof(CharacterPartType))) { @@ -646,7 +610,7 @@ namespace Synty.SidekickCharacters.API _speciesDictionary = new Dictionary(); _partCount = 0; - List files = GetSidekickPartFiles(); + List files = Directory.GetFiles("Assets", "SK_*_*_*_*_*.fbx", SearchOption.AllDirectories).ToList(); Dictionary filesOnDisk = new Dictionary(); foreach (string file in files) { diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/API/SidekickRuntime.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs old mode 100644 new mode 100755 index b529fb5b..1bdcb5fa --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs @@ -1,3249 +1,3249 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. -#if UNITY_EDITOR - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Synty.SidekickCharacters -{ - [ExecuteInEditMode] - public class FacialController : MonoBehaviour - { - [Range(-1, 1)] - public float _ebrlFrownBlendValue = 0f; - [Range(-1, 1)] - public float _ebrlInnerBlendValue = 0f; - [Range(-1, 1)] - public float _ebrlOuterBlendValue = 0f; - [Range(-1, 1)] - public float _ebrrFrownBlendValue = 0f; - [Range(-1, 1)] - public float _ebrrInnerBlendValue = 0f; - [Range(-1, 1)] - public float _ebrrOuterBlendValue = 0f; - [Range(-1, 1)] - public float _eyelUpDownBlendValue = 0f; - [Range(-1, 1)] - public float _eyelLeftRightBlendValue = 0f; - [Range(0, 1)] - public float _eyelBlinkBlendValue = 0f; - [Range(0, 1)] - public float _eyelSquintBlendValue = 0f; - [Range(0, 1)] - public float _eyelWideBlendValue = 0f; - [Range(-1, 1)] - public float _eyerUpDownBlendValue = 0f; - [Range(-1, 1)] - public float _eyerLeftRightBlendValue = 0f; - [Range(0, 1)] - public float _eyerBlinkBlendValue = 0f; - [Range(0, 1)] - public float _eyerSquintBlendValue = 0f; - [Range(0, 1)] - public float _eyerWideBlendValue = 0f; - [Range(0, 1)] - public float _noslSneerBlendValue = 0f; - [Range(0, 1)] - public float _nosrSneerBlendValue = 0f; - [Range(0, 1)] - public float _chklHollowPuffBlendValue = 0f; - [Range(0, 1)] - public float _chkrHollowPuffBlendValue = 0f; - [Range(-1, 1)] - public float _jawOpenCloseBlendValue = 0f; - [Range(-1, 1)] - public float _jawLeftRightBlendValue = 0f; - [Range(-1, 1)] - public float _jawBackForwardBlendValue = 0f; - [Range(-1, 1)] - public float _mthLeftRightBlendValue = 0f; - [Range(0, 1)] - public float _mthFunnelBlendValue = 0f; - [Range(0, 1)] - public float _mthPuckerBlendValue = 0f; - [Range(0, 1)] - public float _mthShrugUpperBlendValue = 0f; - [Range(0, 1)] - public float _mthShrugLowerBlendValue = 0f; - [Range(0, 1)] - public float _mthRollUpperBlendValue = 0f; - [Range(0, 1)] - public float _mthRollOutUpperBlendValue = 0f; - [Range(0, 1)] - public float _mthRollLowerBlendValue = 0f; - [Range(0, 1)] - public float _mthRollOutLowerBlendValue = 0f; - [Range(0, 1)] - public float _mthCloseBlendValue = 0f; - [Range(0, 1)] - public float _mthlFrownSmileBlendValue = 0f; - [Range(0, 1)] - public float _mthrFrownSmileBlendValue = 0f; - [Range(0, 1)] - public float _mthlPressStretchBlendValue = 0f; - [Range(0, 1)] - public float _mthrPressStretchBlendValue = 0f; - [Range(0, 1)] - public float _mthlUpperUpBlendValue = 0f; - [Range(0, 1)] - public float _mthrUpperUpBlendValue = 0f; - [Range(0, 1)] - public float _mthlLowerDownBlendValue = 0f; - [Range(0, 1)] - public float _mthrLowerDownBlendValue = 0f; - [Range(-1, 1)] - public float _tongDownUpBlendValue = 0f; - [Range(-1, 1)] - public float _tongInOutBlendValue = 0f; - [Range(-1, 1)] - public float _tongLowerRaiseBlendValue = 0f; - [Range(-1, 1)] - public float _tongTwistLeftRightBlendValue = 0f; - [Range(-1, 1)] - public float _tongCurlDownUpBlendValue = 0f; - [Range(-1, 1)] - public float _tongCurlLeftRightBlendValue = 0f; - [Range(-1, 1)] - public float _tongCurlSideDownUpBlendValue = 0f; - - public string _presetDirectory = "Assets"; - public string _saveName; - public List _presetNames; - public string _selectedPreset = "None"; - [NonSerialized] - public Dictionary _presetFileDictionary = new Dictionary(); - - [NonSerialized] - private List _meshRenderers = new List(); - [NonSerialized] - private Dictionary> _blendshapeIndices; - [NonSerialized] - private Transform _eyeLBone; - [NonSerialized] - private Transform _eyeRBone; - - private readonly Vector3 _eyeLOriginalRotation = new Vector3(0.024f, 270f, 90f); - private readonly Vector3 _eyeROriginalRotation = new Vector3(0.024f, 270f, 90f); - - private readonly Vector3 _eyeLDown = new Vector3(13.5f, 270f, 90f); - private readonly Vector3 _eyeLUp = new Vector3(-9.5f, 270f, 90f); - private readonly Vector3 _eyeLLeft = new Vector3(0f, 270f, 68f); - private readonly Vector3 _eyeLRight = new Vector3(0f, 270f, 105f); - private readonly Vector3 _eyeRDown = new Vector3(13.5f, 270f, 90f); - private readonly Vector3 _eyeRUp = new Vector3(-9.5f, 270f, 90f); - private readonly Vector3 _eyeRLeft = new Vector3(0f, 270f, 105f); - private readonly Vector3 _eyeRRight = new Vector3(0f, 270f, 68f); - - private readonly List _variableNames = new List - { - "ebrlFrownBlendValue", - "ebrlInnerBlendValue", - "ebrlOuterBlendValue", - "ebrrFrownBlendValue", - "ebrrInnerBlendValue", - "ebrrOuterBlendValue", - "eyelUpDownBlendValue", - "eyelLeftRightBlendValue", - "eyelBlinkBlendValue", - "eyelSquintBlendValue", - "eyelWideBlendValue", - "eyerUpDownBlendValue", - "eyerLeftRightBlendValue", - "eyerBlinkBlendValue", - "eyerSquintBlendValue", - "eyerWideBlendValue", - "noslSneerBlendValue", - "nosrSneerBlendValue", - "chklHollowPuffBlendValue", - "chkrHollowPuffBlendValue", - "jawOpenCloseBlendValue", - "jawLeftRightBlendValue", - "jawBackForwardBlendValue", - "mthLeftRightBlendValue", - "mthFunnelBlendValue", - "mthPuckerBlendValue", - "mthShrugUpperBlendValue", - "mthShrugLowerBlendValue", - "mthRollUpperBlendValue", - "mthRollOutUpperBlendValue", - "mthRollLowerBlendValue", - "mthRollOutLowerBlendValue", - "mthCloseBlendValue", - "mthlFrownSmileBlendValue", - "mthrFrownSmileBlendValue", - "mthlPressStretchBlendValue", - "mthrPressStretchBlendValue", - "mthlUpperUpBlendValue", - "mthrUpperUpBlendValue", - "mthlLowerDownBlendValue", - "mthrLowerDownBlendValue", - "tongDownUpBlendValue", - "tongInOutBlendValue", - "tongLowerRaiseBlendValue", - "tongTwistLeftRightBlendValue", - "tongCurlDownUpBlendValue", - "tongCurlLeftRightBlendValue", - "tongCurlSideDownUpBlendValue" - }; - - public FacialController() {} - - private void OnEnable() - { - UpdateMeshReference(); - CacheBlendshapeIndices(); - ReadBlendshapeValues(); - } - - public void UpdateMeshReference() - { - _meshRenderers = gameObject.GetComponentsInChildren().ToList(); - _eyeLBone = gameObject.GetComponentsInChildren().First(t => t.name == "eye_l"); - _eyeRBone = gameObject.GetComponentsInChildren().First(t => t.name == "eye_r"); - } - - private void OnValidate() - { - ApplyBlendshapes(); - } - - public void CacheBlendshapeIndices() - { - _blendshapeIndices = new Dictionary>(); - if (_meshRenderers.Count < 1) - { - return; - } - - foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) - { - if (meshRenderer == null || meshRenderer.sharedMesh == null) - { - continue; - } - - Dictionary currentIndices = new Dictionary(); - - Mesh mesh = meshRenderer.sharedMesh; - for (int i = 0; i < mesh.blendShapeCount; i++) - { - string blendName = mesh.GetBlendShapeName(i); - currentIndices[blendName] = i; - } - - _blendshapeIndices[meshRenderer] = currentIndices; - } - } - - public void SetBlendValue(string blendName, float value) - { - foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) - { - if (_blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) - { - if (currentIndices.TryGetValue(blendName, out int index)) - { - meshRenderer.SetBlendShapeWeight(index, Mathf.Clamp01(value) * 100f); - } - } - } - } - - public void ApplyBlendshapes() - { - Vector3 eyeLeftRotation = _eyeLOriginalRotation; - Vector3 eyeRightRotation = _eyeROriginalRotation; - - foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) - { - if (meshRenderer == null) - { - continue; - } - - if (_blendshapeIndices == null || _eyeLBone == null || _eyeRBone == null) - { - UpdateMeshReference(); - CacheBlendshapeIndices(); - } - - if (_blendshapeIndices != null && _blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) - { - foreach (KeyValuePair pair in currentIndices) - { - string blendName = pair.Key; - int index = blendName.LastIndexOf('.'); - string blendEnd = blendName.Substring(index, blendName.Length - index); - float weight = meshRenderer.GetBlendShapeWeight(pair.Value); - bool applyBlendChange = false; - - #region BLEND_ACTIONS - switch (blendEnd) - { - case ".browFrownLeft": - weight = _ebrlFrownBlendValue < 0 ? -_ebrlFrownBlendValue : 0; - applyBlendChange = true; - break; - case ".browRaiseLeft": - weight = _ebrlFrownBlendValue > 0 ? _ebrlFrownBlendValue : 0; - applyBlendChange = true; - break; - case ".browInnerDownLeft": - weight = _ebrlInnerBlendValue < 0 ? -_ebrlInnerBlendValue : 0; - applyBlendChange = true; - break; - case ".browInnerUpLeft": - weight = _ebrlInnerBlendValue > 0 ? _ebrlInnerBlendValue : 0; - applyBlendChange = true; - break; - case ".browOuterDownLeft": - weight = _ebrlOuterBlendValue < 0 ? -_ebrlOuterBlendValue : 0; - applyBlendChange = true; - break; - case ".browOuterUpLeft": - weight = _ebrlOuterBlendValue > 0 ? _ebrlOuterBlendValue : 0; - applyBlendChange = true; - break; - case ".browFrownRight": - weight = _ebrrFrownBlendValue < 0 ? -_ebrrFrownBlendValue : 0; - applyBlendChange = true; - break; - case ".browRaiseRight": - weight = _ebrrFrownBlendValue > 0 ? _ebrrFrownBlendValue : 0; - applyBlendChange = true; - break; - case ".browInnerDownRight": - weight = _ebrrInnerBlendValue < 0 ? -_ebrrInnerBlendValue : 0; - applyBlendChange = true; - break; - case ".browInnerUpRight": - weight = _ebrrInnerBlendValue > 0 ? _ebrrInnerBlendValue : 0; - applyBlendChange = true; - break; - case ".browOuterDownRight": - weight = _ebrrOuterBlendValue < 0 ? -_ebrrOuterBlendValue : 0; - applyBlendChange = true; - break; - case ".browOuterUpRight": - weight = _ebrrOuterBlendValue > 0 ? _ebrrOuterBlendValue : 0; - applyBlendChange = true; - break; - case ".eyeLookDownLeft": - weight = _eyelUpDownBlendValue < 0 ? -_eyelUpDownBlendValue : 0; - if (_eyelUpDownBlendValue <= 0) - { - eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLDown, weight) - _eyeLOriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookUpLeft": - weight = _eyelUpDownBlendValue > 0 ? _eyelUpDownBlendValue : 0; - if (_eyelUpDownBlendValue > 0) - { - eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLUp, weight) - _eyeLOriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookOutLeft": - weight = _eyelLeftRightBlendValue < 0 ? -_eyelLeftRightBlendValue : 0; - if (_eyelLeftRightBlendValue <= 0) - { - eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLLeft, weight) - _eyeLOriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookInLeft": - weight = _eyelLeftRightBlendValue > 0 ? _eyelLeftRightBlendValue : 0; - if (_eyelLeftRightBlendValue > 0) - { - eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLRight, weight) - _eyeLOriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeBlinkUpperLeft": - weight = _eyelBlinkBlendValue; - applyBlendChange = true; - break; - case ".eyeBlinkLowerLeft": - weight = _eyelBlinkBlendValue; - applyBlendChange = true; - break; - case ".eyeSquintLeft": - weight = _eyelSquintBlendValue; - applyBlendChange = true; - break; - case ".cheekSquintLeft": - weight = _eyelSquintBlendValue; - applyBlendChange = true; - break; - case ".eyeWideUpperLeft": - weight = _eyelWideBlendValue; - applyBlendChange = true; - break; - case ".eyeWideLowerLeft": - weight = _eyelWideBlendValue; - applyBlendChange = true; - break; - case ".eyeLookDownRight": - weight = _eyerUpDownBlendValue < 0 ? -_eyerUpDownBlendValue : 0; - if (_eyerUpDownBlendValue <= 0) - { - eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRDown, weight) - _eyeROriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookUpRight": - weight = _eyerUpDownBlendValue > 0 ? _eyerUpDownBlendValue : 0; - if (_eyerUpDownBlendValue > 0) - { - eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRUp, weight) - _eyeROriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookOutRight": - weight = _eyerLeftRightBlendValue > 0 ? _eyerLeftRightBlendValue : 0; - if (_eyerLeftRightBlendValue > 0) - { - eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRLeft, weight) - _eyeROriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeLookInRight": - weight = _eyerLeftRightBlendValue < 0 ? -_eyerLeftRightBlendValue : 0; - if (_eyerLeftRightBlendValue <= 0) - { - eyeRightRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeRRight, weight) - _eyeROriginalRotation; - } - applyBlendChange = true; - break; - case ".eyeBlinkUpperRight": - weight = _eyerBlinkBlendValue; - applyBlendChange = true; - break; - case ".eyeBlinkLowerRight": - weight = _eyerBlinkBlendValue; - applyBlendChange = true; - break; - case ".eyeSquintRight": - weight = _eyerSquintBlendValue; - applyBlendChange = true; - break; - case ".cheekSquintRight": - weight = _eyerSquintBlendValue; - applyBlendChange = true; - break; - case ".eyeWideUpperRight": - weight = _eyerWideBlendValue; - applyBlendChange = true; - break; - case ".eyeWideLowerRight": - weight = _eyerWideBlendValue; - applyBlendChange = true; - break; - case ".noseSneerLeft": - weight = _noslSneerBlendValue; - applyBlendChange = true; - break; - case ".noseSneerRight": - weight = _nosrSneerBlendValue; - applyBlendChange = true; - break; - case ".cheekHollowLeft": - weight = _chklHollowPuffBlendValue < 0 ? -_chklHollowPuffBlendValue : 0; - applyBlendChange = true; - break; - case ".cheekPuffLeft": - weight = _chklHollowPuffBlendValue > 0 ? _chklHollowPuffBlendValue : 0; - applyBlendChange = true; - break; - case ".cheekHollowRight": - weight = _chkrHollowPuffBlendValue < 0 ? -_chkrHollowPuffBlendValue : 0; - applyBlendChange = true; - break; - case ".cheekPuffRight": - weight = _chkrHollowPuffBlendValue > 0 ? _chkrHollowPuffBlendValue : 0;; - applyBlendChange = true; - break; - case ".jawClose": - weight = _jawOpenCloseBlendValue < 0 ? -_jawOpenCloseBlendValue : 0; - applyBlendChange = true; - break; - case ".jawOpen": - weight = _jawOpenCloseBlendValue > 0 ? _jawOpenCloseBlendValue : 0; - applyBlendChange = true; - break; - case ".jawLeft": - weight = _jawLeftRightBlendValue < 0 ? -_jawLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".jawRight": - weight = _jawLeftRightBlendValue > 0 ? _jawLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".jawBackward": - weight = _jawBackForwardBlendValue < 0 ? -_jawBackForwardBlendValue : 0; - applyBlendChange = true; - break; - case ".jawForward": - weight = _jawBackForwardBlendValue > 0 ? _jawBackForwardBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthLeft": - weight = _mthLeftRightBlendValue < 0 ? -_mthLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthRight": - weight = _mthLeftRightBlendValue > 0 ? _mthLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthFunnel": - weight = _mthFunnelBlendValue; - applyBlendChange = true; - break; - case ".mouthPucker": - weight = _mthPuckerBlendValue; - applyBlendChange = true; - break; - case ".mouthShrugUpper": - weight = _mthShrugUpperBlendValue; - applyBlendChange = true; - break; - case ".mouthShrugLower": - weight = _mthShrugLowerBlendValue; - applyBlendChange = true; - break; - case ".mouthRollUpper": - weight = _mthRollUpperBlendValue; - applyBlendChange = true; - break; - case ".mouthRollOutUpper": - weight = _mthRollOutUpperBlendValue; - applyBlendChange = true; - break; - case ".mouthRollLower": - weight = _mthRollLowerBlendValue; - applyBlendChange = true; - break; - case ".mouthRollOutLower": - weight = _mthRollOutLowerBlendValue; - applyBlendChange = true; - break; - case ".mouthClose": - weight = _mthCloseBlendValue; - applyBlendChange = true; - break; - case ".mouthFrownLeft": - weight = _mthlFrownSmileBlendValue < 0 ? -_mthlFrownSmileBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthSmileLeft": - weight = _mthlFrownSmileBlendValue > 0 ? _mthlFrownSmileBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthPressLeft": - weight = _mthlPressStretchBlendValue < 0 ? -_mthlPressStretchBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthStretchLeft": - weight = _mthlPressStretchBlendValue > 0 ? _mthlPressStretchBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthUpperUpLeft": - weight = _mthlUpperUpBlendValue; - applyBlendChange = true; - break; - case ".mouthLowerDownLeft": - weight = _mthlLowerDownBlendValue; - applyBlendChange = true; - break; - case ".mouthFrownRight": - weight = _mthrFrownSmileBlendValue < 0 ? -_mthrFrownSmileBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthSmileRight": - weight = _mthrFrownSmileBlendValue > 0 ? _mthrFrownSmileBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthPressRight": - weight = _mthrPressStretchBlendValue < 0 ? -_mthrPressStretchBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthStretchRight": - weight = _mthrPressStretchBlendValue > 0 ? _mthrPressStretchBlendValue : 0; - applyBlendChange = true; - break; - case ".mouthUpperUpRight": - weight = _mthrUpperUpBlendValue; - applyBlendChange = true; - break; - case ".mouthLowerDownRight": - weight = _mthrLowerDownBlendValue; - applyBlendChange = true; - break; - case ".tongueDown": - weight = _tongDownUpBlendValue < 0 ? -_tongDownUpBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueUp": - weight = _tongDownUpBlendValue > 0 ? _tongDownUpBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueIn": - weight = _tongInOutBlendValue < 0 ? -_tongInOutBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueOut": - weight = _tongInOutBlendValue > 0 ? _tongInOutBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueLower": - weight = _tongLowerRaiseBlendValue < 0 ? -_tongLowerRaiseBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueRaise": - weight = _tongLowerRaiseBlendValue > 0 ? _tongLowerRaiseBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueTwistLeft": - weight = _tongTwistLeftRightBlendValue < 0 ? -_tongTwistLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueTwistRight": - weight = _tongTwistLeftRightBlendValue > 0 ? _tongTwistLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueCurlDown": - weight = _tongCurlDownUpBlendValue < 0 ? -_tongCurlDownUpBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueCurlUp": - weight = _tongCurlDownUpBlendValue > 0 ? _tongCurlDownUpBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueCurlLeft": - weight = _tongCurlLeftRightBlendValue < 0 ? -_tongCurlLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueCurlRight": - weight = _tongCurlLeftRightBlendValue > 0 ? _tongCurlLeftRightBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueSideCurlDown": - weight = _tongCurlSideDownUpBlendValue < 0 ? -_tongCurlSideDownUpBlendValue : 0; - applyBlendChange = true; - break; - case ".tongueSideCurlUp": - weight = _tongCurlSideDownUpBlendValue > 0 ? _tongCurlSideDownUpBlendValue : 0; - applyBlendChange = true; - break; - } - #endregion - - if (applyBlendChange) - { - SetBlendValue(blendName, weight); - } - } - } - } - - if (_eyeLBone != null) - { - _eyeLBone.localRotation = Quaternion.Euler(eyeLeftRotation); - } - - if (_eyeRBone != null) - { - _eyeRBone.localRotation = Quaternion.Euler(eyeRightRotation); - } - } - - public void ReadBlendshapeValues() - { - ResetAllSliders(); - - foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) - { - if (meshRenderer == null) - { - continue; - } - - if (_blendshapeIndices == null || _eyeLBone == null || _eyeRBone == null) - { - UpdateMeshReference(); - CacheBlendshapeIndices(); - } - - if (_blendshapeIndices != null && _blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) - { - foreach (KeyValuePair pair in currentIndices) - { - string blendName = pair.Key; - int index = blendName.LastIndexOf('.'); - string blendEnd = blendName.Substring(index, blendName.Length - index); - float weight = meshRenderer.GetBlendShapeWeight(pair.Value) / 100f; - - #region BLEND_ACTIONS - - switch (blendEnd) - { - case ".browFrownLeft": - if (weight > 0) - { - if (_ebrlFrownBlendValue != 0) - { - float newWeight = (_ebrlFrownBlendValue + -weight) / 2f; - _ebrlFrownBlendValue = newWeight; - } - else - { - _ebrlFrownBlendValue = -weight; - } - } - - break; - case ".browRaiseLeft": - if (weight > 0) - { - if (_ebrlFrownBlendValue != 0) - { - float newWeight = (_ebrlFrownBlendValue + weight) / 2f; - _ebrlFrownBlendValue = newWeight; - } - else - { - _ebrlFrownBlendValue = weight; - } - } - - break; - case ".browInnerDownLeft": - if (weight > 0) - { - if (_ebrlInnerBlendValue != 0) - { - float newWeight = (_ebrlInnerBlendValue + -weight) / 2f; - _ebrlInnerBlendValue = newWeight; - } - else - { - _ebrlInnerBlendValue = -weight; - } - } - - break; - case ".browInnerUpLeft": - if (weight > 0) - { - if (_ebrlInnerBlendValue != 0) - { - float newWeight = (_ebrlInnerBlendValue + weight) / 2f; - _ebrlInnerBlendValue = newWeight; - } - else - { - _ebrlInnerBlendValue = weight; - } - } - - break; - case ".browOuterDownLeft": - if (weight > 0) - { - if (_ebrlOuterBlendValue != 0) - { - float newWeight = (_ebrlOuterBlendValue + -weight) / 2f; - _ebrlOuterBlendValue = newWeight; - } - else - { - _ebrlOuterBlendValue = -weight; - } - } - - break; - case ".browOuterUpLeft": - if (weight > 0) - { - if (_ebrlOuterBlendValue != 0) - { - float newWeight = (_ebrlOuterBlendValue + weight) / 2f; - _ebrlOuterBlendValue = newWeight; - } - else - { - _ebrlOuterBlendValue = weight; - } - } - - break; - case ".browFrownRight": - if (weight > 0) - { - if (_ebrrFrownBlendValue != 0) - { - float newWeight = (_ebrrFrownBlendValue + -weight) / 2f; - _ebrrFrownBlendValue = newWeight; - } - else - { - _ebrrFrownBlendValue = -weight; - } - } - - break; - case ".browRaiseRight": - if (weight > 0) - { - if (_ebrrFrownBlendValue != 0) - { - float newWeight = (_ebrrFrownBlendValue + weight) / 2f; - _ebrrFrownBlendValue = newWeight; - } - else - { - _ebrrFrownBlendValue = weight; - } - } - - break; - case ".browInnerDownRight": - if (weight > 0) - { - if (_ebrrInnerBlendValue != 0) - { - float newWeight = (_ebrrInnerBlendValue + -weight) / 2f; - _ebrrInnerBlendValue = newWeight; - } - else - { - _ebrrInnerBlendValue = -weight; - } - } - - break; - case ".browInnerUpRight": - if (weight > 0) - { - if (_ebrrInnerBlendValue != 0) - { - float newWeight = (_ebrrInnerBlendValue + weight) / 2f; - _ebrrInnerBlendValue = newWeight; - } - else - { - _ebrrInnerBlendValue = weight; - } - } - - break; - case ".browOuterDownRight": - if (weight > 0) - { - if (_ebrrOuterBlendValue != 0) - { - float newWeight = (_ebrrOuterBlendValue + -weight) / 2f; - _ebrrOuterBlendValue = newWeight; - } - else - { - _ebrrOuterBlendValue = -weight; - } - } - - break; - case ".browOuterUpRight": - if (weight > 0) - { - if (_ebrrOuterBlendValue != 0) - { - float newWeight = (_ebrrOuterBlendValue + weight) / 2f; - _ebrrOuterBlendValue = newWeight; - } - else - { - _ebrrOuterBlendValue = weight; - } - } - - break; - case ".eyeLookDownLeft": - if (weight > 0) - { - if (_eyelUpDownBlendValue != 0) - { - float newWeight = (_eyelUpDownBlendValue + -weight) / 2f; - _eyelUpDownBlendValue = newWeight; - } - else - { - _eyelUpDownBlendValue = -weight; - } - } - - break; - case ".eyeLookUpLeft": - if (weight > 0) - { - if (_eyelUpDownBlendValue != 0) - { - float newWeight = (_eyelUpDownBlendValue + weight) / 2f; - _eyelUpDownBlendValue = newWeight; - } - else - { - _eyelUpDownBlendValue = weight; - } - } - - break; - case ".eyeLookOutLeft": - if (weight > 0) - { - if (_eyelLeftRightBlendValue != 0) - { - float newWeight = (_eyelLeftRightBlendValue + -weight) / 2f; - _eyelLeftRightBlendValue = newWeight; - } - else - { - _eyelLeftRightBlendValue = -weight; - } - } - - break; - case ".eyeLookInLeft": - if (weight > 0) - { - if (_eyelLeftRightBlendValue != 0) - { - float newWeight = (_eyelLeftRightBlendValue + weight) / 2f; - _eyelLeftRightBlendValue = newWeight; - } - else - { - _eyelLeftRightBlendValue = weight; - } - } - - break; - case ".eyeBlinkUpperLeft": - if (weight > 0) - { - if (_eyelBlinkBlendValue != 0) - { - float newWeight = (_eyelBlinkBlendValue + weight) / 2f; - _eyelBlinkBlendValue = newWeight; - } - else - { - _eyelBlinkBlendValue = weight; - } - } - - break; - case ".eyeBlinkLowerLeft": - if (weight > 0) - { - if (_eyelBlinkBlendValue != 0) - { - float newWeight = (_eyelBlinkBlendValue + weight) / 2f; - _eyelBlinkBlendValue = newWeight; - } - else - { - _eyelBlinkBlendValue = weight; - } - } - - break; - case ".eyeSquintLeft": - if (weight > 0) - { - if (_eyelSquintBlendValue != 0) - { - float newWeight = (_eyelSquintBlendValue + weight) / 2f; - _eyelSquintBlendValue = newWeight; - } - else - { - _eyelSquintBlendValue = weight; - } - } - - break; - case ".cheekSquintLeft": - if (weight > 0) - { - if (_eyelSquintBlendValue != 0) - { - float newWeight = (_eyelSquintBlendValue + weight) / 2f; - _eyelSquintBlendValue = newWeight; - } - else - { - _eyelSquintBlendValue = weight; - } - } - - break; - case ".eyeWideUpperLeft": - if (weight > 0) - { - if (_eyelWideBlendValue != 0) - { - float newWeight = (_eyelWideBlendValue + weight) / 2f; - _eyelWideBlendValue = newWeight; - } - else - { - _eyelWideBlendValue = weight; - } - } - - break; - case ".eyeWideLowerLeft": - if (weight > 0) - { - if (_eyelWideBlendValue != 0) - { - float newWeight = (_eyelWideBlendValue + weight) / 2f; - _eyelWideBlendValue = newWeight; - } - else - { - _eyelWideBlendValue = weight; - } - } - - break; - case ".eyeLookDownRight": - if (weight > 0) - { - if (_eyerUpDownBlendValue != 0) - { - float newWeight = (_eyerUpDownBlendValue + -weight) / 2f; - _eyerUpDownBlendValue = newWeight; - } - else - { - _eyerUpDownBlendValue = -weight; - } - } - - break; - case ".eyeLookUpRight": - if (weight > 0) - { - if (_eyerUpDownBlendValue != 0) - { - float newWeight = (_eyerUpDownBlendValue + weight) / 2f; - _eyerUpDownBlendValue = newWeight; - } - else - { - _eyerUpDownBlendValue = weight; - } - } - - break; - case ".eyeLookOutRight": - if (weight > 0) - { - if (_eyerLeftRightBlendValue != 0) - { - float newWeight = (_eyerLeftRightBlendValue + weight) / 2f; - _eyerLeftRightBlendValue = newWeight; - } - else - { - _eyerLeftRightBlendValue = weight; - } - } - - break; - case ".eyeLookInRight": - if (weight > 0) - { - if (_eyerLeftRightBlendValue != 0) - { - float newWeight = (_eyerLeftRightBlendValue + -weight) / 2f; - _eyerLeftRightBlendValue = newWeight; - } - else - { - _eyerLeftRightBlendValue = -weight; - } - } - - break; - case ".eyeBlinkUpperRight": - if (weight > 0) - { - if (_eyerBlinkBlendValue != 0) - { - float newWeight = (_eyerBlinkBlendValue + weight) / 2f; - _eyerBlinkBlendValue = newWeight; - } - else - { - _eyerBlinkBlendValue = weight; - } - } - - break; - case ".eyeBlinkLowerRight": - if (weight > 0) - { - if (_eyerBlinkBlendValue != 0) - { - float newWeight = (_eyerBlinkBlendValue + weight) / 2f; - _eyerBlinkBlendValue = newWeight; - } - else - { - _eyerBlinkBlendValue = weight; - } - } - - break; - case ".eyeSquintRight": - if (weight > 0) - { - if (_eyerSquintBlendValue != 0) - { - float newWeight = (_eyerSquintBlendValue + weight) / 2f; - _eyerSquintBlendValue = newWeight; - } - else - { - _eyerSquintBlendValue = weight; - } - } - - break; - case ".cheekSquintRight": - if (weight > 0) - { - if (_eyerSquintBlendValue != 0) - { - float newWeight = (_eyerSquintBlendValue + weight) / 2f; - _eyerSquintBlendValue = newWeight; - } - else - { - _eyerSquintBlendValue = weight; - } - } - - break; - case ".eyeWideUpperRight": - if (weight > 0) - { - if (_eyerWideBlendValue != 0) - { - float newWeight = (_eyerWideBlendValue + weight) / 2f; - _eyerWideBlendValue = newWeight; - } - else - { - _eyerWideBlendValue = weight; - } - } - - break; - case ".eyeWideLowerRight": - if (weight > 0) - { - if (_eyerWideBlendValue != 0) - { - float newWeight = (_eyerWideBlendValue + weight) / 2f; - _eyerWideBlendValue = newWeight; - } - else - { - _eyerWideBlendValue = weight; - } - } - - break; - case ".noseSneerLeft": - if (weight > 0) - { - if (_noslSneerBlendValue != 0) - { - float newWeight = (_noslSneerBlendValue + weight) / 2f; - _noslSneerBlendValue = newWeight; - } - else - { - _noslSneerBlendValue = weight; - } - } - - break; - case ".noseSneerRight": - if (weight > 0) - { - if (_nosrSneerBlendValue != 0) - { - float newWeight = (_nosrSneerBlendValue + weight) / 2f; - _nosrSneerBlendValue = newWeight; - } - else - { - _nosrSneerBlendValue = weight; - } - } - - break; - case ".cheekHollowLeft": - if (weight > 0) - { - if (_chklHollowPuffBlendValue != 0) - { - float newWeight = (_chklHollowPuffBlendValue + -weight) / 2f; - _chklHollowPuffBlendValue = newWeight; - } - else - { - _chklHollowPuffBlendValue = -weight; - } - } - - break; - case ".cheekPuffLeft": - if (weight > 0) - { - if (_chklHollowPuffBlendValue != 0) - { - float newWeight = (_chklHollowPuffBlendValue + weight) / 2f; - _chklHollowPuffBlendValue = newWeight; - } - else - { - _chklHollowPuffBlendValue = weight; - } - } - - break; - case ".cheekHollowRight": - if (weight > 0) - { - if (_chkrHollowPuffBlendValue != 0) - { - float newWeight = (_chkrHollowPuffBlendValue + -weight) / 2f; - _chkrHollowPuffBlendValue = newWeight; - } - else - { - _chkrHollowPuffBlendValue = -weight; - } - } - - break; - case ".cheekPuffRight": - if (weight > 0) - { - if (_chkrHollowPuffBlendValue != 0) - { - float newWeight = (_chkrHollowPuffBlendValue + weight) / 2f; - _chkrHollowPuffBlendValue = newWeight; - } - else - { - _chkrHollowPuffBlendValue = weight; - } - } - - break; - case ".jawClose": - if (weight > 0) - { - if (_jawOpenCloseBlendValue != 0) - { - float newWeight = (_jawOpenCloseBlendValue + -weight) / 2f; - _jawOpenCloseBlendValue = newWeight; - } - else - { - _jawOpenCloseBlendValue = -weight; - } - } - - break; - case ".jawOpen": - if (weight > 0) - { - if (_jawOpenCloseBlendValue != 0) - { - float newWeight = (_jawOpenCloseBlendValue + weight) / 2f; - _jawOpenCloseBlendValue = newWeight; - } - else - { - _jawOpenCloseBlendValue = weight; - } - } - - break; - case ".jawLeft": - if (weight > 0) - { - if (_jawLeftRightBlendValue != 0) - { - float newWeight = (_jawLeftRightBlendValue + -weight) / 2f; - _jawLeftRightBlendValue = newWeight; - } - else - { - _jawLeftRightBlendValue = -weight; - } - } - - break; - case ".jawRight": - if (weight > 0) - { - if (_jawLeftRightBlendValue != 0) - { - float newWeight = (_jawLeftRightBlendValue + weight) / 2f; - _jawLeftRightBlendValue = newWeight; - } - else - { - _jawLeftRightBlendValue = weight; - } - } - - break; - case ".jawBackward": - if (weight > 0) - { - if (_jawBackForwardBlendValue != 0) - { - float newWeight = (_jawBackForwardBlendValue + -weight) / 2f; - _jawBackForwardBlendValue = newWeight; - } - else - { - _jawBackForwardBlendValue = -weight; - } - } - - break; - case ".jawForward": - if (weight > 0) - { - if (_jawBackForwardBlendValue != 0) - { - float newWeight = (_jawBackForwardBlendValue + weight) / 2f; - _jawBackForwardBlendValue = newWeight; - } - else - { - _jawBackForwardBlendValue = weight; - } - } - - break; - case ".mouthLeft": - if (weight > 0) - { - if (_mthLeftRightBlendValue != 0) - { - float newWeight = (_mthLeftRightBlendValue + -weight) / 2f; - _mthLeftRightBlendValue = newWeight; - } - else - { - _mthLeftRightBlendValue = -weight; - } - } - - break; - case ".mouthRight": - if (weight > 0) - { - if (_mthLeftRightBlendValue != 0) - { - float newWeight = (_mthLeftRightBlendValue + weight) / 2f; - _mthLeftRightBlendValue = newWeight; - } - else - { - _mthLeftRightBlendValue = weight; - } - } - - break; - case ".mouthFunnel": - if (weight > 0) - { - if (_mthFunnelBlendValue != 0) - { - float newWeight = (_mthFunnelBlendValue + weight) / 2f; - _mthFunnelBlendValue = newWeight; - } - else - { - _mthFunnelBlendValue = weight; - } - } - - break; - case ".mouthPucker": - if (weight > 0) - { - if (_mthPuckerBlendValue != 0) - { - float newWeight = (_mthPuckerBlendValue + weight) / 2f; - _mthPuckerBlendValue = newWeight; - } - else - { - _mthPuckerBlendValue = weight; - } - } - - break; - case ".mouthShrugUpper": - if (weight > 0) - { - if (_mthShrugUpperBlendValue != 0) - { - float newWeight = (_mthShrugUpperBlendValue + weight) / 2f; - _mthShrugUpperBlendValue = newWeight; - } - else - { - _mthShrugUpperBlendValue = weight; - } - } - - break; - case ".mouthShrugLower": - if (weight > 0) - { - if (_mthShrugLowerBlendValue != 0) - { - float newWeight = (_mthShrugLowerBlendValue + weight) / 2f; - _mthShrugLowerBlendValue = newWeight; - } - else - { - _mthShrugLowerBlendValue = weight; - } - } - - break; - case ".mouthRollUpper": - if (weight > 0) - { - if (_mthRollUpperBlendValue != 0) - { - float newWeight = (_mthRollUpperBlendValue + weight) / 2f; - _mthRollUpperBlendValue = newWeight; - } - else - { - _mthRollUpperBlendValue = weight; - } - } - - break; - case ".mouthRollOutUpper": - if (weight > 0) - { - if (_mthRollOutUpperBlendValue != 0) - { - float newWeight = (_mthRollOutUpperBlendValue + weight) / 2f; - _mthRollOutUpperBlendValue = newWeight; - } - else - { - _mthRollOutUpperBlendValue = weight; - } - } - - break; - case ".mouthRollLower": - if (weight > 0) - { - if (_mthRollLowerBlendValue != 0) - { - float newWeight = (_mthRollLowerBlendValue + weight) / 2f; - _mthRollLowerBlendValue = newWeight; - } - else - { - _mthRollLowerBlendValue = weight; - } - } - - break; - case ".mouthRollOutLower": - if (weight > 0) - { - if (_mthRollOutLowerBlendValue != 0) - { - float newWeight = (_mthRollOutLowerBlendValue + weight) / 2f; - _mthRollOutLowerBlendValue = newWeight; - } - else - { - _mthRollOutLowerBlendValue = weight; - } - } - - break; - case ".mouthClose": - if (weight > 0) - { - if (_mthCloseBlendValue != 0) - { - float newWeight = (_mthCloseBlendValue + weight) / 2f; - _mthCloseBlendValue = newWeight; - } - else - { - _mthCloseBlendValue = weight; - } - } - - break; - case ".mouthFrownLeft": - if (weight > 0) - { - if (_mthlFrownSmileBlendValue != 0) - { - float newWeight = (_mthlFrownSmileBlendValue + -weight) / 2f; - _mthlFrownSmileBlendValue = newWeight; - } - else - { - _mthlFrownSmileBlendValue = -weight; - } - } - - break; - case ".mouthSmileLeft": - if (weight > 0) - { - if (_mthlFrownSmileBlendValue != 0) - { - float newWeight = (_mthlFrownSmileBlendValue + weight) / 2f; - _mthlFrownSmileBlendValue = newWeight; - } - else - { - _mthlFrownSmileBlendValue = weight; - } - } - - break; - case ".mouthPressLeft": - if (weight > 0) - { - if (_mthlPressStretchBlendValue != 0) - { - float newWeight = (_mthlPressStretchBlendValue + -weight) / 2f; - _mthlPressStretchBlendValue = newWeight; - } - else - { - _mthlPressStretchBlendValue = -weight; - } - } - - break; - case ".mouthStretchLeft": - if (weight > 0) - { - if (_mthlPressStretchBlendValue != 0) - { - float newWeight = (_mthlPressStretchBlendValue + weight) / 2f; - _mthlPressStretchBlendValue = newWeight; - } - else - { - _mthlPressStretchBlendValue = weight; - } - } - - break; - case ".mouthUpperUpLeft": - if (weight > 0) - { - if (_mthlUpperUpBlendValue != 0) - { - float newWeight = (_mthlUpperUpBlendValue + weight) / 2f; - _mthlUpperUpBlendValue = newWeight; - } - else - { - _mthlUpperUpBlendValue = weight; - } - } - - break; - case ".mouthLowerDownLeft": - if (weight > 0) - { - if (_mthlLowerDownBlendValue != 0) - { - float newWeight = (_mthlLowerDownBlendValue + weight) / 2f; - _mthlLowerDownBlendValue = newWeight; - } - else - { - _mthlLowerDownBlendValue = weight; - } - } - - break; - case ".mouthFrownRight": - if (weight > 0) - { - if (_mthrFrownSmileBlendValue != 0) - { - float newWeight = (_mthrFrownSmileBlendValue + -weight) / 2f; - _mthrFrownSmileBlendValue = newWeight; - } - else - { - _mthrFrownSmileBlendValue = -weight; - } - } - - break; - case ".mouthSmileRight": - if (weight > 0) - { - if (_mthrFrownSmileBlendValue != 0) - { - float newWeight = (_mthrFrownSmileBlendValue + weight) / 2f; - _mthrFrownSmileBlendValue = newWeight; - } - else - { - _mthrFrownSmileBlendValue = weight; - } - } - - break; - case ".mouthPressRight": - if (weight > 0) - { - if (_mthrPressStretchBlendValue != 0) - { - float newWeight = (_mthrPressStretchBlendValue + -weight) / 2f; - _mthrPressStretchBlendValue = newWeight; - } - else - { - _mthrPressStretchBlendValue = -weight; - } - } - - break; - case ".mouthStretchRight": - if (weight > 0) - { - if (_mthrPressStretchBlendValue != 0) - { - float newWeight = (_mthrPressStretchBlendValue + weight) / 2f; - _mthrPressStretchBlendValue = newWeight; - } - else - { - _mthrPressStretchBlendValue = weight; - } - } - - break; - case ".mouthUpperUpRight": - if (weight > 0) - { - if (_mthrUpperUpBlendValue != 0) - { - float newWeight = (_mthrUpperUpBlendValue + weight) / 2f; - _mthrUpperUpBlendValue = newWeight; - } - else - { - _mthrUpperUpBlendValue = weight; - } - } - - break; - case ".mouthLowerDownRight": - if (weight > 0) - { - if (_mthrLowerDownBlendValue != 0) - { - float newWeight = (_mthrLowerDownBlendValue + weight) / 2f; - _mthrLowerDownBlendValue = newWeight; - } - else - { - _mthrLowerDownBlendValue = weight; - } - } - - break; - case ".tongueDown": - if (weight > 0) - { - if (_tongDownUpBlendValue != 0) - { - float newWeight = (_tongDownUpBlendValue + -weight) / 2f; - _tongDownUpBlendValue = newWeight; - } - else - { - _tongDownUpBlendValue = -weight; - } - } - - break; - case ".tongueUp": - if (weight > 0) - { - if (_tongDownUpBlendValue != 0) - { - float newWeight = (_tongDownUpBlendValue + weight) / 2f; - _tongDownUpBlendValue = newWeight; - } - else - { - _tongDownUpBlendValue = weight; - } - } - - break; - case ".tongueIn": - if (weight > 0) - { - if (_tongInOutBlendValue != 0) - { - float newWeight = (_tongInOutBlendValue + -weight) / 2f; - _tongInOutBlendValue = newWeight; - } - else - { - _tongInOutBlendValue = -weight; - } - } - - break; - case ".tongueOut": - if (weight > 0) - { - if (_tongInOutBlendValue != 0) - { - float newWeight = (_tongInOutBlendValue + weight) / 2f; - _tongInOutBlendValue = newWeight; - } - else - { - _tongInOutBlendValue = weight; - } - } - - break; - case ".tongueLower": - if (weight > 0) - { - if (_tongLowerRaiseBlendValue != 0) - { - float newWeight = (_tongLowerRaiseBlendValue + -weight) / 2f; - _tongLowerRaiseBlendValue = newWeight; - } - else - { - _tongLowerRaiseBlendValue = -weight; - } - } - - break; - case ".tongueRaise": - if (weight > 0) - { - if (_tongLowerRaiseBlendValue != 0) - { - float newWeight = (_tongLowerRaiseBlendValue + weight) / 2f; - _tongLowerRaiseBlendValue = newWeight; - } - else - { - _tongLowerRaiseBlendValue = weight; - } - } - - break; - case ".tongueTwistLeft": - if (weight > 0) - { - if (_tongTwistLeftRightBlendValue != 0) - { - float newWeight = (_tongTwistLeftRightBlendValue + -weight) / 2f; - _tongTwistLeftRightBlendValue = newWeight; - } - else - { - _tongTwistLeftRightBlendValue = -weight; - } - } - - break; - case ".tongueTwistRight": - if (weight > 0) - { - if (_tongTwistLeftRightBlendValue != 0) - { - float newWeight = (_tongTwistLeftRightBlendValue + weight) / 2f; - _tongTwistLeftRightBlendValue = newWeight; - } - else - { - _tongTwistLeftRightBlendValue = weight; - } - } - - break; - case ".tongueCurlDown": - if (weight > 0) - { - if (_tongCurlDownUpBlendValue != 0) - { - float newWeight = (_tongCurlDownUpBlendValue + -weight) / 2f; - _tongCurlDownUpBlendValue = newWeight; - } - else - { - _tongCurlDownUpBlendValue = -weight; - } - } - - break; - case ".tongueCurlUp": - if (weight > 0) - { - if (_tongCurlDownUpBlendValue != 0) - { - float newWeight = (_tongCurlDownUpBlendValue + weight) / 2f; - _tongCurlDownUpBlendValue = newWeight; - } - else - { - _tongCurlDownUpBlendValue = weight; - } - } - - break; - case ".tongueCurlLeft": - if (weight > 0) - { - if (_tongCurlLeftRightBlendValue != 0) - { - float newWeight = (_tongCurlLeftRightBlendValue + -weight) / 2f; - _tongCurlLeftRightBlendValue = newWeight; - } - else - { - _tongCurlLeftRightBlendValue = -weight; - } - } - - break; - case ".tongueCurlRight": - if (weight > 0) - { - if (_tongCurlLeftRightBlendValue != 0) - { - float newWeight = (_tongCurlLeftRightBlendValue + weight) / 2f; - _tongCurlLeftRightBlendValue = newWeight; - } - else - { - _tongCurlLeftRightBlendValue = weight; - } - } - - break; - case ".tongueSideCurlDown": - if (weight > 0) - { - if (_tongCurlSideDownUpBlendValue != 0) - { - float newWeight = (_tongCurlSideDownUpBlendValue + -weight) / 2f; - _tongCurlSideDownUpBlendValue = newWeight; - } - else - { - _tongCurlSideDownUpBlendValue = -weight; - } - } - - break; - case ".tongueSideCurlUp": - if (weight > 0) - { - if (_tongCurlSideDownUpBlendValue != 0) - { - float newWeight = (_tongCurlSideDownUpBlendValue + weight) / 2f; - _tongCurlSideDownUpBlendValue = newWeight; - } - else - { - _tongCurlSideDownUpBlendValue = weight; - } - } - - break; - } - - #endregion - } - } - } - } - - public void SavePreset() - { - if (string.IsNullOrEmpty(_saveName)) - { - EditorUtility.DisplayDialog("Unable to Save Preset", "No preset name was provided to save the preset to.", "Ok"); - return; - } - - List serializedData = SerializeValues(); - string outputFileName = Path.Combine(_presetDirectory, _saveName + ".fcp"); - File.WriteAllLines(outputFileName, serializedData); - } - - public List SerializeValues() - { - List serialisedValues = new List(); - foreach (string field in _variableNames) - { - switch (field) - { - case "ebrlFrownBlendValue": - serialisedValues.Add(field + ":" + _ebrlFrownBlendValue); - break; - case "ebrlInnerBlendValue": - serialisedValues.Add(field + ":" + _ebrlInnerBlendValue); - break; - case "ebrlOuterBlendValue": - serialisedValues.Add(field + ":" + _ebrlOuterBlendValue); - break; - case "ebrrFrownBlendValue": - serialisedValues.Add(field + ":" + _ebrrFrownBlendValue); - break; - case "ebrrInnerBlendValue": - serialisedValues.Add(field + ":" + _ebrrInnerBlendValue); - break; - case "ebrrOuterBlendValue": - serialisedValues.Add(field + ":" + _ebrrOuterBlendValue); - break; - case "eyelUpDownBlendValue": - serialisedValues.Add(field + ":" + _eyelUpDownBlendValue); - break; - case "eyelLeftRightBlendValue": - serialisedValues.Add(field + ":" + _eyelLeftRightBlendValue); - break; - case "eyelBlinkBlendValue": - serialisedValues.Add(field + ":" + _eyelBlinkBlendValue); - break; - case "eyelSquintBlendValue": - serialisedValues.Add(field + ":" + _eyelSquintBlendValue); - break; - case "eyelWideBlendValue": - serialisedValues.Add(field + ":" + _eyelWideBlendValue); - break; - case "eyerUpDownBlendValue": - serialisedValues.Add(field + ":" + _eyerUpDownBlendValue); - break; - case "eyerLeftRightBlendValue": - serialisedValues.Add(field + ":" + _eyerLeftRightBlendValue); - break; - case "eyerBlinkBlendValue": - serialisedValues.Add(field + ":" + _eyerBlinkBlendValue); - break; - case "eyerSquintBlendValue": - serialisedValues.Add(field + ":" + _eyerSquintBlendValue); - break; - case "eyerWideBlendValue": - serialisedValues.Add(field + ":" + _eyerWideBlendValue); - break; - case "noslSneerBlendValue": - serialisedValues.Add(field + ":" + _noslSneerBlendValue); - break; - case "nosrSneerBlendValue": - serialisedValues.Add(field + ":" + _nosrSneerBlendValue); - break; - case "chklHollowPuffBlendValue": - serialisedValues.Add(field + ":" + _chklHollowPuffBlendValue); - break; - case "chkrHollowPuffBlendValue": - serialisedValues.Add(field + ":" + _chkrHollowPuffBlendValue); - break; - case "jawOpenCloseBlendValue": - serialisedValues.Add(field + ":" + _jawOpenCloseBlendValue); - break; - case "jawLeftRightBlendValue": - serialisedValues.Add(field + ":" + _jawLeftRightBlendValue); - break; - case "jawBackForwardBlendValue": - serialisedValues.Add(field + ":" + _jawBackForwardBlendValue); - break; - case "mthLeftRightBlendValue": - serialisedValues.Add(field + ":" + _mthLeftRightBlendValue); - break; - case "mthFunnelBlendValue": - serialisedValues.Add(field + ":" + _mthFunnelBlendValue); - break; - case "mthPuckerBlendValue": - serialisedValues.Add(field + ":" + _mthPuckerBlendValue); - break; - case "mthShrugUpperBlendValue": - serialisedValues.Add(field + ":" + _mthShrugUpperBlendValue); - break; - case "mthShrugLowerBlendValue": - serialisedValues.Add(field + ":" + _mthShrugLowerBlendValue); - break; - case "mthRollUpperBlendValue": - serialisedValues.Add(field + ":" + _mthRollUpperBlendValue); - break; - case "mthRollOutUpperBlendValue": - serialisedValues.Add(field + ":" + _mthRollOutUpperBlendValue); - break; - case "mthRollLowerBlendValue": - serialisedValues.Add(field + ":" + _mthRollLowerBlendValue); - break; - case "mthRollOutLowerBlendValue": - serialisedValues.Add(field + ":" + _mthRollOutLowerBlendValue); - break; - case "mthCloseBlendValue": - serialisedValues.Add(field + ":" + _mthCloseBlendValue); - break; - case "mthlFrownSmileBlendValue": - serialisedValues.Add(field + ":" + _mthlFrownSmileBlendValue); - break; - case "mthrFrownSmileBlendValue": - serialisedValues.Add(field + ":" + _mthrFrownSmileBlendValue); - break; - case "mthlPressStretchBlendValue": - serialisedValues.Add(field + ":" + _mthlPressStretchBlendValue); - break; - case "mthrPressStretchBlendValue": - serialisedValues.Add(field + ":" + _mthrPressStretchBlendValue); - break; - case "mthlUpperUpBlendValue": - serialisedValues.Add(field + ":" + _mthlUpperUpBlendValue); - break; - case "mthrUpperUpBlendValue": - serialisedValues.Add(field + ":" + _mthrUpperUpBlendValue); - break; - case "mthlLowerDownBlendValue": - serialisedValues.Add(field + ":" + _mthlLowerDownBlendValue); - break; - case "mthrLowerDownBlendValue": - serialisedValues.Add(field + ":" + _mthrLowerDownBlendValue); - break; - case "tongDownUpBlendValue": - serialisedValues.Add(field + ":" + _tongDownUpBlendValue); - break; - case "tongInOutBlendValue": - serialisedValues.Add(field + ":" + _tongInOutBlendValue); - break; - case "tongLowerRaiseBlendValue": - serialisedValues.Add(field + ":" + _tongLowerRaiseBlendValue); - break; - case "tongTwistLeftRightBlendValue": - serialisedValues.Add(field + ":" + _tongTwistLeftRightBlendValue); - break; - case "tongCurlDownUpBlendValue": - serialisedValues.Add(field + ":" + _tongCurlDownUpBlendValue); - break; - case "tongCurlLeftRightBlendValue": - serialisedValues.Add(field + ":" + _tongCurlLeftRightBlendValue); - break; - case "tongCurlSideDownUpBlendValue": - serialisedValues.Add(field + ":" + _tongCurlSideDownUpBlendValue); - break; - } - } - - return serialisedValues; - } - - public void LoadPreset(string presetName) - { - if (presetName == "None") - { - return; - } - - string fileLocation = _presetFileDictionary[presetName]; - List serializedData = File.ReadAllLines(fileLocation).ToList(); - string line; - foreach (string field in _variableNames) - { - switch (field) - { - case "ebrlFrownBlendValue": - line = serializedData.Find(data => data.Contains("ebrlFrownBlendValue")); - _ebrlFrownBlendValue = GetValue(line); - break; - case "ebrlInnerBlendValue": - line = serializedData.Find(data => data.Contains("ebrlInnerBlendValue")); - _ebrlInnerBlendValue = GetValue(line); - break; - case "ebrlOuterBlendValue": - line = serializedData.Find(data => data.Contains("ebrlOuterBlendValue")); - _ebrlOuterBlendValue = GetValue(line); - break; - case "ebrrFrownBlendValue": - line = serializedData.Find(data => data.Contains("ebrrFrownBlendValue")); - _ebrrFrownBlendValue = GetValue(line); - break; - case "ebrrInnerBlendValue": - line = serializedData.Find(data => data.Contains("ebrrInnerBlendValue")); - _ebrrInnerBlendValue = GetValue(line); - break; - case "ebrrOuterBlendValue": - line = serializedData.Find(data => data.Contains("ebrrOuterBlendValue")); - _ebrrOuterBlendValue = GetValue(line); - break; - case "eyelUpDownBlendValue": - line = serializedData.Find(data => data.Contains("eyelUpDownBlendValue")); - _eyelUpDownBlendValue = GetValue(line); - break; - case "eyelLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("eyelLeftRightBlendValue")); - _eyelLeftRightBlendValue = GetValue(line); - break; - case "eyelBlinkBlendValue": - line = serializedData.Find(data => data.Contains("eyelBlinkBlendValue")); - _eyelBlinkBlendValue = GetValue(line); - break; - case "eyelSquintBlendValue": - line = serializedData.Find(data => data.Contains("eyelSquintBlendValue")); - _eyelSquintBlendValue = GetValue(line); - break; - case "eyelWideBlendValue": - line = serializedData.Find(data => data.Contains("eyelWideBlendValue")); - _eyelWideBlendValue = GetValue(line); - break; - case "eyerUpDownBlendValue": - line = serializedData.Find(data => data.Contains("eyerUpDownBlendValue")); - _eyerUpDownBlendValue = GetValue(line); - break; - case "eyerLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("eyerLeftRightBlendValue")); - _eyerLeftRightBlendValue = GetValue(line); - break; - case "eyerBlinkBlendValue": - line = serializedData.Find(data => data.Contains("eyerBlinkBlendValue")); - _eyerBlinkBlendValue = GetValue(line); - break; - case "eyerSquintBlendValue": - line = serializedData.Find(data => data.Contains("eyerSquintBlendValue")); - _eyerSquintBlendValue = GetValue(line); - break; - case "eyerWideBlendValue": - line = serializedData.Find(data => data.Contains("eyerWideBlendValue")); - _eyerWideBlendValue = GetValue(line); - break; - case "noslSneerBlendValue": - line = serializedData.Find(data => data.Contains("noslSneerBlendValue")); - _noslSneerBlendValue = GetValue(line); - break; - case "nosrSneerBlendValue": - line = serializedData.Find(data => data.Contains("nosrSneerBlendValue")); - _nosrSneerBlendValue = GetValue(line); - break; - case "chklHollowPuffBlendValue": - line = serializedData.Find(data => data.Contains("chklHollowPuffBlendValue")); - _chklHollowPuffBlendValue = GetValue(line); - break; - case "chkrHollowPuffBlendValue": - line = serializedData.Find(data => data.Contains("chkrHollowPuffBlendValue")); - _chkrHollowPuffBlendValue = GetValue(line); - break; - case "jawOpenCloseBlendValue": - line = serializedData.Find(data => data.Contains("jawOpenCloseBlendValue")); - _jawOpenCloseBlendValue = GetValue(line); - break; - case "jawLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("jawLeftRightBlendValue")); - _jawLeftRightBlendValue = GetValue(line); - break; - case "jawBackForwardBlendValue": - line = serializedData.Find(data => data.Contains("jawBackForwardBlendValue")); - _jawBackForwardBlendValue = GetValue(line); - break; - case "mthLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("mthLeftRightBlendValue")); - _mthLeftRightBlendValue = GetValue(line); - break; - case "mthFunnelBlendValue": - line = serializedData.Find(data => data.Contains("mthFunnelBlendValue")); - _mthFunnelBlendValue = GetValue(line); - break; - case "mthPuckerBlendValue": - line = serializedData.Find(data => data.Contains("mthPuckerBlendValue")); - _mthPuckerBlendValue = GetValue(line); - break; - case "mthShrugUpperBlendValue": - line = serializedData.Find(data => data.Contains("mthShrugUpperBlendValue")); - _mthShrugUpperBlendValue = GetValue(line); - break; - case "mthShrugLowerBlendValue": - line = serializedData.Find(data => data.Contains("mthShrugLowerBlendValue")); - _mthShrugLowerBlendValue = GetValue(line); - break; - case "mthRollUpperBlendValue": - line = serializedData.Find(data => data.Contains("mthRollUpperBlendValue")); - _mthRollUpperBlendValue = GetValue(line); - break; - case "mthRollOutUpperBlendValue": - line = serializedData.Find(data => data.Contains("mthRollOutUpperBlendValue")); - _mthRollOutUpperBlendValue = GetValue(line); - break; - case "mthRollLowerBlendValue": - line = serializedData.Find(data => data.Contains("mthRollLowerBlendValue")); - _mthRollLowerBlendValue = GetValue(line); - break; - case "mthRollOutLowerBlendValue": - line = serializedData.Find(data => data.Contains("mthRollOutLowerBlendValue")); - _mthRollOutLowerBlendValue = GetValue(line); - break; - case "mthCloseBlendValue": - line = serializedData.Find(data => data.Contains("mthCloseBlendValue")); - _mthCloseBlendValue = GetValue(line); - break; - case "mthlFrownSmileBlendValue": - line = serializedData.Find(data => data.Contains("mthlFrownSmileBlendValue")); - _mthlFrownSmileBlendValue = GetValue(line); - break; - case "mthrFrownSmileBlendValue": - line = serializedData.Find(data => data.Contains("mthrFrownSmileBlendValue")); - _mthrFrownSmileBlendValue = GetValue(line); - break; - case "mthlPressStretchBlendValue": - line = serializedData.Find(data => data.Contains("mthlPressStretchBlendValue")); - _mthlPressStretchBlendValue = GetValue(line); - break; - case "mthrPressStretchBlendValue": - line = serializedData.Find(data => data.Contains("mthrPressStretchBlendValue")); - _mthrPressStretchBlendValue = GetValue(line); - break; - case "mthlUpperUpBlendValue": - line = serializedData.Find(data => data.Contains("mthlUpperUpBlendValue")); - _mthlUpperUpBlendValue = GetValue(line); - break; - case "mthrUpperUpBlendValue": - line = serializedData.Find(data => data.Contains("mthrUpperUpBlendValue")); - _mthrUpperUpBlendValue = GetValue(line); - break; - case "mthlLowerDownBlendValue": - line = serializedData.Find(data => data.Contains("mthlLowerDownBlendValue")); - _mthlLowerDownBlendValue = GetValue(line); - break; - case "mthrLowerDownBlendValue": - line = serializedData.Find(data => data.Contains("mthrLowerDownBlendValue")); - _mthrLowerDownBlendValue = GetValue(line); - break; - case "tongDownUpBlendValue": - line = serializedData.Find(data => data.Contains("tongDownUpBlendValue")); - _tongDownUpBlendValue = GetValue(line); - break; - case "tongInOutBlendValue": - line = serializedData.Find(data => data.Contains("tongInOutBlendValue")); - _tongInOutBlendValue = GetValue(line); - break; - case "tongLowerRaiseBlendValue": - line = serializedData.Find(data => data.Contains("tongLowerRaiseBlendValue")); - _tongLowerRaiseBlendValue = GetValue(line); - break; - case "tongTwistLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("tongTwistLeftRightBlendValue")); - _tongTwistLeftRightBlendValue = GetValue(line); - break; - case "tongCurlDownUpBlendValue": - line = serializedData.Find(data => data.Contains("tongCurlDownUpBlendValue")); - _tongCurlDownUpBlendValue = GetValue(line); - break; - case "tongCurlLeftRightBlendValue": - line = serializedData.Find(data => data.Contains("tongCurlLeftRightBlendValue")); - _tongCurlLeftRightBlendValue = GetValue(line); - break; - case "tongCurlSideDownUpBlendValue": - line = serializedData.Find(data => data.Contains("tongCurlSideDownUpBlendValue")); - _tongCurlSideDownUpBlendValue = GetValue(line); - break; - } - } - - ApplyBlendshapes(); - } - - public float GetValue(string line) - { - int index = line.IndexOf(":", StringComparison.Ordinal) + 1; - if (float.TryParse(line.Substring(index, line.Length - index), out float value)) - { - return value; - } - - return 0f; - } - - public void ResetAllSliders() - { - #region RESET_BLENDS - foreach (string field in _variableNames) - { - switch (field) - { - case "ebrlFrownBlendValue": - _ebrlFrownBlendValue = 0; - break; - case "ebrlInnerBlendValue": - _ebrlInnerBlendValue = 0; - break; - case "ebrlOuterBlendValue": - _ebrlOuterBlendValue = 0; - break; - case "ebrrFrownBlendValue": - _ebrrFrownBlendValue = 0; - break; - case "ebrrInnerBlendValue": - _ebrrInnerBlendValue = 0; - break; - case "ebrrOuterBlendValue": - _ebrrOuterBlendValue = 0; - break; - case "eyelUpDownBlendValue": - _eyelUpDownBlendValue = 0; - break; - case "eyelLeftRightBlendValue": - _eyelLeftRightBlendValue = 0; - break; - case "eyelBlinkBlendValue": - _eyelBlinkBlendValue = 0; - break; - case "eyelSquintBlendValue": - _eyelSquintBlendValue = 0; - break; - case "eyelWideBlendValue": - _eyelWideBlendValue = 0; - break; - case "eyerUpDownBlendValue": - _eyerUpDownBlendValue = 0; - break; - case "eyerLeftRightBlendValue": - _eyerLeftRightBlendValue = 0; - break; - case "eyerBlinkBlendValue": - _eyerBlinkBlendValue = 0; - break; - case "eyerSquintBlendValue": - _eyerSquintBlendValue = 0; - break; - case "eyerWideBlendValue": - _eyerWideBlendValue = 0; - break; - case "noslSneerBlendValue": - _noslSneerBlendValue = 0; - break; - case "nosrSneerBlendValue": - _nosrSneerBlendValue = 0; - break; - case "chklHollowPuffBlendValue": - _chklHollowPuffBlendValue = 0; - break; - case "chkrHollowPuffBlendValue": - _chkrHollowPuffBlendValue = 0; - break; - case "jawOpenCloseBlendValue": - _jawOpenCloseBlendValue = 0; - break; - case "jawLeftRightBlendValue": - _jawLeftRightBlendValue = 0; - break; - case "jawBackForwardBlendValue": - _jawBackForwardBlendValue = 0; - break; - case "mthLeftRightBlendValue": - _mthLeftRightBlendValue = 0; - break; - case "mthFunnelBlendValue": - _mthFunnelBlendValue = 0; - break; - case "mthPuckerBlendValue": - _mthPuckerBlendValue = 0; - break; - case "mthShrugUpperBlendValue": - _mthShrugUpperBlendValue = 0; - break; - case "mthShrugLowerBlendValue": - _mthShrugLowerBlendValue = 0; - break; - case "mthRollUpperBlendValue": - _mthRollUpperBlendValue = 0; - break; - case "mthRollOutUpperBlendValue": - _mthRollOutUpperBlendValue = 0; - break; - case "mthRollLowerBlendValue": - _mthRollLowerBlendValue = 0; - break; - case "mthRollOutLowerBlendValue": - _mthRollOutLowerBlendValue = 0; - break; - case "mthCloseBlendValue": - _mthCloseBlendValue = 0; - break; - case "mthlFrownSmileBlendValue": - _mthlFrownSmileBlendValue = 0; - break; - case "mthrFrownSmileBlendValue": - _mthrFrownSmileBlendValue = 0; - break; - case "mthlPressStretchBlendValue": - _mthlPressStretchBlendValue = 0; - break; - case "mthrPressStretchBlendValue": - _mthrPressStretchBlendValue = 0; - break; - case "mthlUpperUpBlendValue": - _mthlUpperUpBlendValue = 0; - break; - case "mthrUpperUpBlendValue": - _mthrUpperUpBlendValue = 0; - break; - case "mthlLowerDownBlendValue": - _mthlLowerDownBlendValue = 0; - break; - case "mthrLowerDownBlendValue": - _mthrLowerDownBlendValue = 0; - break; - case "tongDownUpBlendValue": - _tongDownUpBlendValue = 0; - break; - case "tongInOutBlendValue": - _tongInOutBlendValue = 0; - break; - case "tongLowerRaiseBlendValue": - _tongLowerRaiseBlendValue = 0; - break; - case "tongTwistLeftRightBlendValue": - _tongTwistLeftRightBlendValue = 0; - break; - case "tongCurlDownUpBlendValue": - _tongCurlDownUpBlendValue = 0; - break; - case "tongCurlLeftRightBlendValue": - _tongCurlLeftRightBlendValue = 0; - break; - case "tongCurlSideDownUpBlendValue": - _tongCurlSideDownUpBlendValue = 0; - break; - } - } - #endregion - } - - public void PopulatePresetList() - { - _presetNames = new List(); - if (!string.IsNullOrEmpty(_presetDirectory)) - { - List files = Directory.GetFiles(_presetDirectory, "*.fcp", SearchOption.AllDirectories).ToList(); - foreach (string file in files) - { - FileInfo info = new FileInfo(file); - string fileName = info.Name.Substring(0, info.Name.IndexOf(".fcp", StringComparison.Ordinal)); - _presetNames.Add(fileName); - _presetFileDictionary.TryAdd(fileName, file); - } - } - } - } - - [CustomEditor(typeof(FacialController))] - public class FacialControllerInspector : Editor - { - public override VisualElement CreateInspectorGUI() - { - FacialController controller = (FacialController) target; - VisualElement root = new VisualElement(); - - #region PRESETS - Foldout presets = new Foldout() - { - text = "Presets", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - Label presetFolderTitle = new Label("Preset Directory"); - - presets.Add(presetFolderTitle); - - VisualElement directoryLayout = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row) - } - }; - - TextField directoryField = new TextField() - { - style = - { - width = Length.Percent(85), - }, - isReadOnly = true, - bindingPath = "_presetDirectory" - }; - - Button directoryPickerButton = new Button( - delegate - { - string directory = EditorUtility.OpenFolderPanel("Select Directory", "Assets", ""); - if (!string.IsNullOrEmpty(directory) && directory.Contains("Assets")) - { - int index = directory.IndexOf("Assets", StringComparison.Ordinal); - directoryField.value = directory.Substring(index, directory.Length - index); - } - } - ) - { - text = "Browse", - style = - { - width = Length.Percent(12), - }, - }; - - directoryLayout.Add(directoryPickerButton); - directoryLayout.Add(directoryField); - - presets.Add(directoryLayout); - - Label loadPreset = new Label("Load Preset"); - presets.Add(loadPreset); - - VisualElement presetLayout = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row) - } - }; - - List popupValues = new List - { - "None" - }; - - controller.PopulatePresetList(); - popupValues.AddRange(controller._presetNames); - - PopupField presetPopup = new PopupField() - { - bindingPath = "_selectedPreset", - choices = popupValues, - value = popupValues[0] - }; - - Button prevButton = new Button(delegate { presetPopup.index--; }) - { - text = "Prev", - }; - - Button nextButton = new Button(delegate { presetPopup.index++; }) - { - text = "Next" - }; - - prevButton.SetEnabled(presetPopup.index > 0); - nextButton.SetEnabled(presetPopup.index < presetPopup.choices.Count - 1); - - presetPopup.RegisterValueChangedCallback( - evt => - { - controller.LoadPreset(evt.newValue); - prevButton.SetEnabled(presetPopup.index > 0); - nextButton.SetEnabled(presetPopup.index < presetPopup.choices.Count - 1); - } - ); - - presetLayout.Add(prevButton); - presetLayout.Add(nextButton); - presetLayout.Add(presetPopup); - - presets.Add(presetLayout); - - Label savePresetLabel = new Label("Save Preset"); - presets.Add(savePresetLabel); - - VisualElement saveLayout = new VisualElement() - { - style = - { - flexDirection = new StyleEnum(FlexDirection.Row) - } - }; - - TextField saveNameField = new TextField() - { - style = - { - width = Length.Percent(85), - }, - bindingPath = "_saveName" - }; - - Button saveButton = new Button( - delegate - { - controller.SavePreset(); - } - ) - { - text = "Save", - style = - { - width = Length.Percent(12), - }, - }; - - saveLayout.Add(saveNameField); - saveLayout.Add(saveButton); - - presets.Add(saveLayout); - - root.Add(presets); - - #endregion - - Foldout controls = new Foldout() - { - text = "Controls", - style = - { - unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) - } - }; - - #region EYEBROWS - Foldout eyebrowFoldout = new Foldout - { - text = "EYEBROWS" - }; - - Label leftEyebrowLabel = new Label("LEFT"); - - Slider ebrlFrownRaise = new Slider - { - bindingPath = "_ebrlFrownBlendValue", - label = "Frown/Raise", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider ebrlInnerDownUp = new Slider - { - bindingPath = "_ebrlInnerBlendValue", - label = "Inner Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider ebrlOuterDownUp = new Slider - { - bindingPath = "_ebrlOuterBlendValue", - label = "Outer Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - eyebrowFoldout.Add(leftEyebrowLabel); - eyebrowFoldout.Add(ebrlFrownRaise); - eyebrowFoldout.Add(ebrlInnerDownUp); - eyebrowFoldout.Add(ebrlOuterDownUp); - - Label rightEyebrowLabel = new Label("RIGHT"); - - Slider ebrrFrownRaise = new Slider - { - bindingPath = "_ebrrFrownBlendValue", - label = "Frown/Raise", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider ebrrInnerDownUp = new Slider - { - bindingPath = "_ebrrInnerBlendValue", - label = "Inner Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider ebrrOuterDownUp = new Slider - { - bindingPath = "_ebrrOuterBlendValue", - label = "Outer Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - eyebrowFoldout.Add(rightEyebrowLabel); - eyebrowFoldout.Add(ebrrFrownRaise); - eyebrowFoldout.Add(ebrrInnerDownUp); - eyebrowFoldout.Add(ebrrOuterDownUp); - - controls.Add(eyebrowFoldout); - #endregion - - #region EYES - Foldout eyeFoldout = new Foldout - { - text = "EYES" - }; - - Label leftEyeLabel = new Label("LEFT"); - - Slider eyelLookUpDown = new Slider - { - bindingPath = "_eyelUpDownBlendValue", - label = "Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider eyelLookLeftRight = new Slider - { - bindingPath = "_eyelLeftRightBlendValue", - label = "Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider eyelBlink = new Slider - { - bindingPath = "_eyelBlinkBlendValue", - label = "Blink", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider eyelSquint = new Slider - { - bindingPath = "_eyelSquintBlendValue", - label = "Squint", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider eyelWide = new Slider - { - bindingPath = "_eyelWideBlendValue", - label = "Wide", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - eyeFoldout.Add(leftEyeLabel); - eyeFoldout.Add(eyelLookUpDown); - eyeFoldout.Add(eyelLookLeftRight); - eyeFoldout.Add(eyelBlink); - eyeFoldout.Add(eyelSquint); - eyeFoldout.Add(eyelWide); - - Label rightEyeLabel = new Label("RIGHT"); - - Slider eyerLookUpDown = new Slider - { - bindingPath = "_eyerUpDownBlendValue", - label = "Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider eyerLookLeftRight = new Slider - { - bindingPath = "_eyerLeftRightBlendValue", - label = "Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider eyerBlink = new Slider - { - bindingPath = "_eyerBlinkBlendValue", - label = "Blink", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider eyerSquint = new Slider - { - bindingPath = "_eyerSquintBlendValue", - label = "Squint", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider eyerWide = new Slider - { - bindingPath = "_eyerWideBlendValue", - label = "Wide", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - eyeFoldout.Add(rightEyeLabel); - eyeFoldout.Add(eyerLookUpDown); - eyeFoldout.Add(eyerLookLeftRight); - eyeFoldout.Add(eyerBlink); - eyeFoldout.Add(eyerSquint); - eyeFoldout.Add(eyerWide); - - controls.Add(eyeFoldout); - #endregion - - #region NOSE - Foldout noseFoldout = new Foldout - { - text = "NOSE" - }; - - Label sneerLeft = new Label("LEFT"); - - Slider noseSneerLeft = new Slider - { - bindingPath = "_noslSneerBlendValue", - label = "Sneer", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Label sneerRight = new Label("RIGHT"); - - Slider noseSneerRight = new Slider - { - bindingPath = "_nosrSneerBlendValue", - label = "Sneer", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - noseFoldout.Add(sneerLeft); - noseFoldout.Add(noseSneerLeft); - noseFoldout.Add(sneerRight); - noseFoldout.Add(noseSneerRight); - - controls.Add(noseFoldout); - #endregion - - #region CHEEKS - Foldout cheeksFoldout = new Foldout - { - text = "CHEEKS" - }; - - Label cheekLeft = new Label("LEFT"); - - Slider cheekHollowPuffLeft = new Slider - { - bindingPath = "_chklHollowPuffBlendValue", - label = "Hollow/Puff", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Label cheekRight = new Label("Right"); - - Slider cheekHollowPuffRight = new Slider - { - bindingPath = "_chkrHollowPuffBlendValue", - label = "Hollow/Puff", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - cheeksFoldout.Add(cheekLeft); - cheeksFoldout.Add(cheekHollowPuffLeft); - cheeksFoldout.Add(cheekRight); - cheeksFoldout.Add(cheekHollowPuffRight); - - controls.Add(cheeksFoldout); - #endregion - - #region JAW - Foldout jawFoldout = new Foldout - { - text = "JAW" - }; - - Slider jawCloseOpen = new Slider - { - bindingPath = "_jawOpenCloseBlendValue", - label = "Close/Open", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider jawLeftRight = new Slider - { - bindingPath = "_jawLeftRightBlendValue", - label = "Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider jawBackwardForward = new Slider - { - bindingPath = "_jawBackForwardBlendValue", - label = "Backward/Forward", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - jawFoldout.Add(jawCloseOpen); - jawFoldout.Add(jawLeftRight); - jawFoldout.Add(jawBackwardForward); - - controls.Add(jawFoldout); - #endregion - - #region MOUTH - Foldout mouthFoldout = new Foldout - { - text = "MOUTH" - }; - - Slider mouthLeftRight = new Slider - { - bindingPath = "_mthLeftRightBlendValue", - label = "Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider mouthFunnel = new Slider - { - bindingPath = "_mthFunnelBlendValue", - label = "Funnel", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthPucker = new Slider - { - bindingPath = "_mthPuckerBlendValue", - label = "Pucker", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthShrugUpper = new Slider - { - bindingPath = "_mthShrugUpperBlendValue", - label = "Shrug Upper", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthShrugLower = new Slider - { - bindingPath = "_mthShrugLowerBlendValue", - label = "Shrug Lower", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthRollUpper = new Slider - { - bindingPath = "_mthRollUpperBlendValue", - label = "Roll Upper", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthRollOutUpper = new Slider - { - bindingPath = "_mthRollOutUpperBlendValue", - label = "Roll Out Upper", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthRollLower = new Slider - { - bindingPath = "_mthRollLowerBlendValue", - label = "Roll Lower", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthRollOutLower = new Slider - { - bindingPath = "_mthRollOutLowerBlendValue", - label = "Roll Out Lower", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthClose = new Slider - { - bindingPath = "_mthCloseBlendValue", - label = "Close", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Label mouthLeft = new Label("LEFT"); - - Slider mouthFrownSmileLeft = new Slider - { - bindingPath = "_mthlFrownSmileBlendValue", - label = "Frown/Smile", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider mouthPressStretchLeft = new Slider - { - bindingPath = "_mthlPressStretchBlendValue", - label = "PressStretch", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider mouthUpperUpLeft = new Slider - { - bindingPath = "_mthlUpperUpBlendValue", - label = "Upper Up", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthLowerDownLeft = new Slider - { - bindingPath = "_mthlLowerDownBlendValue", - label = "Lower Down", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Label mouthRight = new Label("RIGHT"); - - Slider mouthFrownSmileRight = new Slider - { - bindingPath = "_mthrFrownSmileBlendValue", - label = "Frown/Smile", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider mouthPressStretchRight = new Slider - { - bindingPath = "_mthrPressStretchBlendValue", - label = "PressStretch", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider mouthUpperUpRight = new Slider - { - bindingPath = "_mthrUpperUpBlendValue", - label = "Upper Up", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - Slider mouthLowerDownRight = new Slider - { - bindingPath = "_mthrLowerDownBlendValue", - label = "Lower Down", - showInputField = true, - lowValue = 0, - highValue = 1 - }; - - mouthFoldout.Add(mouthLeftRight); - mouthFoldout.Add(mouthFunnel); - mouthFoldout.Add(mouthPucker); - mouthFoldout.Add(mouthShrugUpper); - mouthFoldout.Add(mouthShrugLower); - mouthFoldout.Add(mouthRollUpper); - mouthFoldout.Add(mouthRollOutUpper); - mouthFoldout.Add(mouthRollLower); - mouthFoldout.Add(mouthRollOutLower); - mouthFoldout.Add(mouthClose); - mouthFoldout.Add(mouthLeft); - mouthFoldout.Add(mouthFrownSmileLeft); - mouthFoldout.Add(mouthPressStretchLeft); - mouthFoldout.Add(mouthUpperUpLeft); - mouthFoldout.Add(mouthLowerDownLeft); - mouthFoldout.Add(mouthRight); - mouthFoldout.Add(mouthFrownSmileRight); - mouthFoldout.Add(mouthPressStretchRight); - mouthFoldout.Add(mouthUpperUpRight); - mouthFoldout.Add(mouthLowerDownRight); - - controls.Add(mouthFoldout); - #endregion - - #region TONGUE - Foldout tongueFoldout = new Foldout - { - text = "TONGUE" - }; - - Slider tongueDownUp = new Slider - { - bindingPath = "_tongDownUpBlendValue", - label = "Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueInOut = new Slider - { - bindingPath = "_tongInOutBlendValue", - label = "In/Out", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueLowerRaise = new Slider - { - bindingPath = "_tongLowerRaiseBlendValue", - label = "Lower/Raise", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueTwistLeftRight = new Slider - { - bindingPath = "_tongTwistLeftRightBlendValue", - label = "Twist Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueCurlDownUp = new Slider - { - bindingPath = "_tongCurlDownUpBlendValue", - label = "Curl Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueCurlLeftRight = new Slider - { - bindingPath = "_tongCurlLeftRightBlendValue", - label = "Curl Left/Right", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - Slider tongueCurlSideDownUp = new Slider - { - bindingPath = "_tongCurlSideDownUpBlendValue", - label = "Curl Side Down/Up", - showInputField = true, - lowValue = -1, - highValue = 1 - }; - - tongueFoldout.Add(tongueDownUp); - tongueFoldout.Add(tongueInOut); - tongueFoldout.Add(tongueLowerRaise); - tongueFoldout.Add(tongueTwistLeftRight); - tongueFoldout.Add(tongueCurlDownUp); - tongueFoldout.Add(tongueCurlLeftRight); - tongueFoldout.Add(tongueCurlSideDownUp); - - controls.Add(tongueFoldout); - #endregion - - root.Add(controls); - - return root; - } - } -} -#endif +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. +#if UNITY_EDITOR + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Synty.SidekickCharacters +{ + [ExecuteInEditMode] + public class FacialController : MonoBehaviour + { + [Range(-1, 1)] + public float _ebrlFrownBlendValue = 0f; + [Range(-1, 1)] + public float _ebrlInnerBlendValue = 0f; + [Range(-1, 1)] + public float _ebrlOuterBlendValue = 0f; + [Range(-1, 1)] + public float _ebrrFrownBlendValue = 0f; + [Range(-1, 1)] + public float _ebrrInnerBlendValue = 0f; + [Range(-1, 1)] + public float _ebrrOuterBlendValue = 0f; + [Range(-1, 1)] + public float _eyelUpDownBlendValue = 0f; + [Range(-1, 1)] + public float _eyelLeftRightBlendValue = 0f; + [Range(0, 1)] + public float _eyelBlinkBlendValue = 0f; + [Range(0, 1)] + public float _eyelSquintBlendValue = 0f; + [Range(0, 1)] + public float _eyelWideBlendValue = 0f; + [Range(-1, 1)] + public float _eyerUpDownBlendValue = 0f; + [Range(-1, 1)] + public float _eyerLeftRightBlendValue = 0f; + [Range(0, 1)] + public float _eyerBlinkBlendValue = 0f; + [Range(0, 1)] + public float _eyerSquintBlendValue = 0f; + [Range(0, 1)] + public float _eyerWideBlendValue = 0f; + [Range(0, 1)] + public float _noslSneerBlendValue = 0f; + [Range(0, 1)] + public float _nosrSneerBlendValue = 0f; + [Range(0, 1)] + public float _chklHollowPuffBlendValue = 0f; + [Range(0, 1)] + public float _chkrHollowPuffBlendValue = 0f; + [Range(-1, 1)] + public float _jawOpenCloseBlendValue = 0f; + [Range(-1, 1)] + public float _jawLeftRightBlendValue = 0f; + [Range(-1, 1)] + public float _jawBackForwardBlendValue = 0f; + [Range(-1, 1)] + public float _mthLeftRightBlendValue = 0f; + [Range(0, 1)] + public float _mthFunnelBlendValue = 0f; + [Range(0, 1)] + public float _mthPuckerBlendValue = 0f; + [Range(0, 1)] + public float _mthShrugUpperBlendValue = 0f; + [Range(0, 1)] + public float _mthShrugLowerBlendValue = 0f; + [Range(0, 1)] + public float _mthRollUpperBlendValue = 0f; + [Range(0, 1)] + public float _mthRollOutUpperBlendValue = 0f; + [Range(0, 1)] + public float _mthRollLowerBlendValue = 0f; + [Range(0, 1)] + public float _mthRollOutLowerBlendValue = 0f; + [Range(0, 1)] + public float _mthCloseBlendValue = 0f; + [Range(0, 1)] + public float _mthlFrownSmileBlendValue = 0f; + [Range(0, 1)] + public float _mthrFrownSmileBlendValue = 0f; + [Range(0, 1)] + public float _mthlPressStretchBlendValue = 0f; + [Range(0, 1)] + public float _mthrPressStretchBlendValue = 0f; + [Range(0, 1)] + public float _mthlUpperUpBlendValue = 0f; + [Range(0, 1)] + public float _mthrUpperUpBlendValue = 0f; + [Range(0, 1)] + public float _mthlLowerDownBlendValue = 0f; + [Range(0, 1)] + public float _mthrLowerDownBlendValue = 0f; + [Range(-1, 1)] + public float _tongDownUpBlendValue = 0f; + [Range(-1, 1)] + public float _tongInOutBlendValue = 0f; + [Range(-1, 1)] + public float _tongLowerRaiseBlendValue = 0f; + [Range(-1, 1)] + public float _tongTwistLeftRightBlendValue = 0f; + [Range(-1, 1)] + public float _tongCurlDownUpBlendValue = 0f; + [Range(-1, 1)] + public float _tongCurlLeftRightBlendValue = 0f; + [Range(-1, 1)] + public float _tongCurlSideDownUpBlendValue = 0f; + + public string _presetDirectory = "Assets"; + public string _saveName; + public List _presetNames; + public string _selectedPreset = "None"; + [NonSerialized] + public Dictionary _presetFileDictionary = new Dictionary(); + + [NonSerialized] + private List _meshRenderers = new List(); + [NonSerialized] + private Dictionary> _blendshapeIndices; + [NonSerialized] + private Transform _eyeLBone; + [NonSerialized] + private Transform _eyeRBone; + + private readonly Vector3 _eyeLOriginalRotation = new Vector3(0.024f, 270f, 90f); + private readonly Vector3 _eyeROriginalRotation = new Vector3(0.024f, 270f, 90f); + + private readonly Vector3 _eyeLDown = new Vector3(13.5f, 270f, 90f); + private readonly Vector3 _eyeLUp = new Vector3(-9.5f, 270f, 90f); + private readonly Vector3 _eyeLLeft = new Vector3(0f, 270f, 68f); + private readonly Vector3 _eyeLRight = new Vector3(0f, 270f, 105f); + private readonly Vector3 _eyeRDown = new Vector3(13.5f, 270f, 90f); + private readonly Vector3 _eyeRUp = new Vector3(-9.5f, 270f, 90f); + private readonly Vector3 _eyeRLeft = new Vector3(0f, 270f, 105f); + private readonly Vector3 _eyeRRight = new Vector3(0f, 270f, 68f); + + private readonly List _variableNames = new List + { + "ebrlFrownBlendValue", + "ebrlInnerBlendValue", + "ebrlOuterBlendValue", + "ebrrFrownBlendValue", + "ebrrInnerBlendValue", + "ebrrOuterBlendValue", + "eyelUpDownBlendValue", + "eyelLeftRightBlendValue", + "eyelBlinkBlendValue", + "eyelSquintBlendValue", + "eyelWideBlendValue", + "eyerUpDownBlendValue", + "eyerLeftRightBlendValue", + "eyerBlinkBlendValue", + "eyerSquintBlendValue", + "eyerWideBlendValue", + "noslSneerBlendValue", + "nosrSneerBlendValue", + "chklHollowPuffBlendValue", + "chkrHollowPuffBlendValue", + "jawOpenCloseBlendValue", + "jawLeftRightBlendValue", + "jawBackForwardBlendValue", + "mthLeftRightBlendValue", + "mthFunnelBlendValue", + "mthPuckerBlendValue", + "mthShrugUpperBlendValue", + "mthShrugLowerBlendValue", + "mthRollUpperBlendValue", + "mthRollOutUpperBlendValue", + "mthRollLowerBlendValue", + "mthRollOutLowerBlendValue", + "mthCloseBlendValue", + "mthlFrownSmileBlendValue", + "mthrFrownSmileBlendValue", + "mthlPressStretchBlendValue", + "mthrPressStretchBlendValue", + "mthlUpperUpBlendValue", + "mthrUpperUpBlendValue", + "mthlLowerDownBlendValue", + "mthrLowerDownBlendValue", + "tongDownUpBlendValue", + "tongInOutBlendValue", + "tongLowerRaiseBlendValue", + "tongTwistLeftRightBlendValue", + "tongCurlDownUpBlendValue", + "tongCurlLeftRightBlendValue", + "tongCurlSideDownUpBlendValue" + }; + + public FacialController() {} + + private void OnEnable() + { + UpdateMeshReference(); + CacheBlendshapeIndices(); + ReadBlendshapeValues(); + } + + public void UpdateMeshReference() + { + _meshRenderers = gameObject.GetComponentsInChildren().ToList(); + _eyeLBone = gameObject.GetComponentsInChildren().First(t => t.name == "eye_l"); + _eyeRBone = gameObject.GetComponentsInChildren().First(t => t.name == "eye_r"); + } + + private void OnValidate() + { + ApplyBlendshapes(); + } + + public void CacheBlendshapeIndices() + { + _blendshapeIndices = new Dictionary>(); + if (_meshRenderers.Count < 1) + { + return; + } + + foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) + { + if (meshRenderer == null || meshRenderer.sharedMesh == null) + { + continue; + } + + Dictionary currentIndices = new Dictionary(); + + Mesh mesh = meshRenderer.sharedMesh; + for (int i = 0; i < mesh.blendShapeCount; i++) + { + string blendName = mesh.GetBlendShapeName(i); + currentIndices[blendName] = i; + } + + _blendshapeIndices[meshRenderer] = currentIndices; + } + } + + public void SetBlendValue(string blendName, float value) + { + foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) + { + if (_blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) + { + if (currentIndices.TryGetValue(blendName, out int index)) + { + meshRenderer.SetBlendShapeWeight(index, Mathf.Clamp01(value) * 100f); + } + } + } + } + + public void ApplyBlendshapes() + { + Vector3 eyeLeftRotation = _eyeLOriginalRotation; + Vector3 eyeRightRotation = _eyeROriginalRotation; + + foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) + { + if (meshRenderer == null) + { + continue; + } + + if (_blendshapeIndices == null || _eyeLBone == null || _eyeRBone == null) + { + UpdateMeshReference(); + CacheBlendshapeIndices(); + } + + if (_blendshapeIndices != null && _blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) + { + foreach (KeyValuePair pair in currentIndices) + { + string blendName = pair.Key; + int index = blendName.LastIndexOf('.'); + string blendEnd = blendName.Substring(index, blendName.Length - index); + float weight = meshRenderer.GetBlendShapeWeight(pair.Value); + bool applyBlendChange = false; + + #region BLEND_ACTIONS + switch (blendEnd) + { + case ".browFrownLeft": + weight = _ebrlFrownBlendValue < 0 ? -_ebrlFrownBlendValue : 0; + applyBlendChange = true; + break; + case ".browRaiseLeft": + weight = _ebrlFrownBlendValue > 0 ? _ebrlFrownBlendValue : 0; + applyBlendChange = true; + break; + case ".browInnerDownLeft": + weight = _ebrlInnerBlendValue < 0 ? -_ebrlInnerBlendValue : 0; + applyBlendChange = true; + break; + case ".browInnerUpLeft": + weight = _ebrlInnerBlendValue > 0 ? _ebrlInnerBlendValue : 0; + applyBlendChange = true; + break; + case ".browOuterDownLeft": + weight = _ebrlOuterBlendValue < 0 ? -_ebrlOuterBlendValue : 0; + applyBlendChange = true; + break; + case ".browOuterUpLeft": + weight = _ebrlOuterBlendValue > 0 ? _ebrlOuterBlendValue : 0; + applyBlendChange = true; + break; + case ".browFrownRight": + weight = _ebrrFrownBlendValue < 0 ? -_ebrrFrownBlendValue : 0; + applyBlendChange = true; + break; + case ".browRaiseRight": + weight = _ebrrFrownBlendValue > 0 ? _ebrrFrownBlendValue : 0; + applyBlendChange = true; + break; + case ".browInnerDownRight": + weight = _ebrrInnerBlendValue < 0 ? -_ebrrInnerBlendValue : 0; + applyBlendChange = true; + break; + case ".browInnerUpRight": + weight = _ebrrInnerBlendValue > 0 ? _ebrrInnerBlendValue : 0; + applyBlendChange = true; + break; + case ".browOuterDownRight": + weight = _ebrrOuterBlendValue < 0 ? -_ebrrOuterBlendValue : 0; + applyBlendChange = true; + break; + case ".browOuterUpRight": + weight = _ebrrOuterBlendValue > 0 ? _ebrrOuterBlendValue : 0; + applyBlendChange = true; + break; + case ".eyeLookDownLeft": + weight = _eyelUpDownBlendValue < 0 ? -_eyelUpDownBlendValue : 0; + if (_eyelUpDownBlendValue <= 0) + { + eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLDown, weight) - _eyeLOriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookUpLeft": + weight = _eyelUpDownBlendValue > 0 ? _eyelUpDownBlendValue : 0; + if (_eyelUpDownBlendValue > 0) + { + eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLUp, weight) - _eyeLOriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookOutLeft": + weight = _eyelLeftRightBlendValue < 0 ? -_eyelLeftRightBlendValue : 0; + if (_eyelLeftRightBlendValue <= 0) + { + eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLLeft, weight) - _eyeLOriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookInLeft": + weight = _eyelLeftRightBlendValue > 0 ? _eyelLeftRightBlendValue : 0; + if (_eyelLeftRightBlendValue > 0) + { + eyeLeftRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeLRight, weight) - _eyeLOriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeBlinkUpperLeft": + weight = _eyelBlinkBlendValue; + applyBlendChange = true; + break; + case ".eyeBlinkLowerLeft": + weight = _eyelBlinkBlendValue; + applyBlendChange = true; + break; + case ".eyeSquintLeft": + weight = _eyelSquintBlendValue; + applyBlendChange = true; + break; + case ".cheekSquintLeft": + weight = _eyelSquintBlendValue; + applyBlendChange = true; + break; + case ".eyeWideUpperLeft": + weight = _eyelWideBlendValue; + applyBlendChange = true; + break; + case ".eyeWideLowerLeft": + weight = _eyelWideBlendValue; + applyBlendChange = true; + break; + case ".eyeLookDownRight": + weight = _eyerUpDownBlendValue < 0 ? -_eyerUpDownBlendValue : 0; + if (_eyerUpDownBlendValue <= 0) + { + eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRDown, weight) - _eyeROriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookUpRight": + weight = _eyerUpDownBlendValue > 0 ? _eyerUpDownBlendValue : 0; + if (_eyerUpDownBlendValue > 0) + { + eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRUp, weight) - _eyeROriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookOutRight": + weight = _eyerLeftRightBlendValue > 0 ? _eyerLeftRightBlendValue : 0; + if (_eyerLeftRightBlendValue > 0) + { + eyeRightRotation += Vector3.Lerp(_eyeROriginalRotation, _eyeRLeft, weight) - _eyeROriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeLookInRight": + weight = _eyerLeftRightBlendValue < 0 ? -_eyerLeftRightBlendValue : 0; + if (_eyerLeftRightBlendValue <= 0) + { + eyeRightRotation += Vector3.Lerp(_eyeLOriginalRotation, _eyeRRight, weight) - _eyeROriginalRotation; + } + applyBlendChange = true; + break; + case ".eyeBlinkUpperRight": + weight = _eyerBlinkBlendValue; + applyBlendChange = true; + break; + case ".eyeBlinkLowerRight": + weight = _eyerBlinkBlendValue; + applyBlendChange = true; + break; + case ".eyeSquintRight": + weight = _eyerSquintBlendValue; + applyBlendChange = true; + break; + case ".cheekSquintRight": + weight = _eyerSquintBlendValue; + applyBlendChange = true; + break; + case ".eyeWideUpperRight": + weight = _eyerWideBlendValue; + applyBlendChange = true; + break; + case ".eyeWideLowerRight": + weight = _eyerWideBlendValue; + applyBlendChange = true; + break; + case ".noseSneerLeft": + weight = _noslSneerBlendValue; + applyBlendChange = true; + break; + case ".noseSneerRight": + weight = _nosrSneerBlendValue; + applyBlendChange = true; + break; + case ".cheekHollowLeft": + weight = _chklHollowPuffBlendValue < 0 ? -_chklHollowPuffBlendValue : 0; + applyBlendChange = true; + break; + case ".cheekPuffLeft": + weight = _chklHollowPuffBlendValue > 0 ? _chklHollowPuffBlendValue : 0; + applyBlendChange = true; + break; + case ".cheekHollowRight": + weight = _chkrHollowPuffBlendValue < 0 ? -_chkrHollowPuffBlendValue : 0; + applyBlendChange = true; + break; + case ".cheekPuffRight": + weight = _chkrHollowPuffBlendValue > 0 ? _chkrHollowPuffBlendValue : 0;; + applyBlendChange = true; + break; + case ".jawClose": + weight = _jawOpenCloseBlendValue < 0 ? -_jawOpenCloseBlendValue : 0; + applyBlendChange = true; + break; + case ".jawOpen": + weight = _jawOpenCloseBlendValue > 0 ? _jawOpenCloseBlendValue : 0; + applyBlendChange = true; + break; + case ".jawLeft": + weight = _jawLeftRightBlendValue < 0 ? -_jawLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".jawRight": + weight = _jawLeftRightBlendValue > 0 ? _jawLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".jawBackward": + weight = _jawBackForwardBlendValue < 0 ? -_jawBackForwardBlendValue : 0; + applyBlendChange = true; + break; + case ".jawForward": + weight = _jawBackForwardBlendValue > 0 ? _jawBackForwardBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthLeft": + weight = _mthLeftRightBlendValue < 0 ? -_mthLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthRight": + weight = _mthLeftRightBlendValue > 0 ? _mthLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthFunnel": + weight = _mthFunnelBlendValue; + applyBlendChange = true; + break; + case ".mouthPucker": + weight = _mthPuckerBlendValue; + applyBlendChange = true; + break; + case ".mouthShrugUpper": + weight = _mthShrugUpperBlendValue; + applyBlendChange = true; + break; + case ".mouthShrugLower": + weight = _mthShrugLowerBlendValue; + applyBlendChange = true; + break; + case ".mouthRollUpper": + weight = _mthRollUpperBlendValue; + applyBlendChange = true; + break; + case ".mouthRollOutUpper": + weight = _mthRollOutUpperBlendValue; + applyBlendChange = true; + break; + case ".mouthRollLower": + weight = _mthRollLowerBlendValue; + applyBlendChange = true; + break; + case ".mouthRollOutLower": + weight = _mthRollOutLowerBlendValue; + applyBlendChange = true; + break; + case ".mouthClose": + weight = _mthCloseBlendValue; + applyBlendChange = true; + break; + case ".mouthFrownLeft": + weight = _mthlFrownSmileBlendValue < 0 ? -_mthlFrownSmileBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthSmileLeft": + weight = _mthlFrownSmileBlendValue > 0 ? _mthlFrownSmileBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthPressLeft": + weight = _mthlPressStretchBlendValue < 0 ? -_mthlPressStretchBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthStretchLeft": + weight = _mthlPressStretchBlendValue > 0 ? _mthlPressStretchBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthUpperUpLeft": + weight = _mthlUpperUpBlendValue; + applyBlendChange = true; + break; + case ".mouthLowerDownLeft": + weight = _mthlLowerDownBlendValue; + applyBlendChange = true; + break; + case ".mouthFrownRight": + weight = _mthrFrownSmileBlendValue < 0 ? -_mthrFrownSmileBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthSmileRight": + weight = _mthrFrownSmileBlendValue > 0 ? _mthrFrownSmileBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthPressRight": + weight = _mthrPressStretchBlendValue < 0 ? -_mthrPressStretchBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthStretchRight": + weight = _mthrPressStretchBlendValue > 0 ? _mthrPressStretchBlendValue : 0; + applyBlendChange = true; + break; + case ".mouthUpperUpRight": + weight = _mthrUpperUpBlendValue; + applyBlendChange = true; + break; + case ".mouthLowerDownRight": + weight = _mthrLowerDownBlendValue; + applyBlendChange = true; + break; + case ".tongueDown": + weight = _tongDownUpBlendValue < 0 ? -_tongDownUpBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueUp": + weight = _tongDownUpBlendValue > 0 ? _tongDownUpBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueIn": + weight = _tongInOutBlendValue < 0 ? -_tongInOutBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueOut": + weight = _tongInOutBlendValue > 0 ? _tongInOutBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueLower": + weight = _tongLowerRaiseBlendValue < 0 ? -_tongLowerRaiseBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueRaise": + weight = _tongLowerRaiseBlendValue > 0 ? _tongLowerRaiseBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueTwistLeft": + weight = _tongTwistLeftRightBlendValue < 0 ? -_tongTwistLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueTwistRight": + weight = _tongTwistLeftRightBlendValue > 0 ? _tongTwistLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueCurlDown": + weight = _tongCurlDownUpBlendValue < 0 ? -_tongCurlDownUpBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueCurlUp": + weight = _tongCurlDownUpBlendValue > 0 ? _tongCurlDownUpBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueCurlLeft": + weight = _tongCurlLeftRightBlendValue < 0 ? -_tongCurlLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueCurlRight": + weight = _tongCurlLeftRightBlendValue > 0 ? _tongCurlLeftRightBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueSideCurlDown": + weight = _tongCurlSideDownUpBlendValue < 0 ? -_tongCurlSideDownUpBlendValue : 0; + applyBlendChange = true; + break; + case ".tongueSideCurlUp": + weight = _tongCurlSideDownUpBlendValue > 0 ? _tongCurlSideDownUpBlendValue : 0; + applyBlendChange = true; + break; + } + #endregion + + if (applyBlendChange) + { + SetBlendValue(blendName, weight); + } + } + } + } + + if (_eyeLBone != null) + { + _eyeLBone.localRotation = Quaternion.Euler(eyeLeftRotation); + } + + if (_eyeRBone != null) + { + _eyeRBone.localRotation = Quaternion.Euler(eyeRightRotation); + } + } + + public void ReadBlendshapeValues() + { + ResetAllSliders(); + + foreach (SkinnedMeshRenderer meshRenderer in _meshRenderers) + { + if (meshRenderer == null) + { + continue; + } + + if (_blendshapeIndices == null || _eyeLBone == null || _eyeRBone == null) + { + UpdateMeshReference(); + CacheBlendshapeIndices(); + } + + if (_blendshapeIndices != null && _blendshapeIndices.TryGetValue(meshRenderer, out Dictionary currentIndices)) + { + foreach (KeyValuePair pair in currentIndices) + { + string blendName = pair.Key; + int index = blendName.LastIndexOf('.'); + string blendEnd = blendName.Substring(index, blendName.Length - index); + float weight = meshRenderer.GetBlendShapeWeight(pair.Value) / 100f; + + #region BLEND_ACTIONS + + switch (blendEnd) + { + case ".browFrownLeft": + if (weight > 0) + { + if (_ebrlFrownBlendValue != 0) + { + float newWeight = (_ebrlFrownBlendValue + -weight) / 2f; + _ebrlFrownBlendValue = newWeight; + } + else + { + _ebrlFrownBlendValue = -weight; + } + } + + break; + case ".browRaiseLeft": + if (weight > 0) + { + if (_ebrlFrownBlendValue != 0) + { + float newWeight = (_ebrlFrownBlendValue + weight) / 2f; + _ebrlFrownBlendValue = newWeight; + } + else + { + _ebrlFrownBlendValue = weight; + } + } + + break; + case ".browInnerDownLeft": + if (weight > 0) + { + if (_ebrlInnerBlendValue != 0) + { + float newWeight = (_ebrlInnerBlendValue + -weight) / 2f; + _ebrlInnerBlendValue = newWeight; + } + else + { + _ebrlInnerBlendValue = -weight; + } + } + + break; + case ".browInnerUpLeft": + if (weight > 0) + { + if (_ebrlInnerBlendValue != 0) + { + float newWeight = (_ebrlInnerBlendValue + weight) / 2f; + _ebrlInnerBlendValue = newWeight; + } + else + { + _ebrlInnerBlendValue = weight; + } + } + + break; + case ".browOuterDownLeft": + if (weight > 0) + { + if (_ebrlOuterBlendValue != 0) + { + float newWeight = (_ebrlOuterBlendValue + -weight) / 2f; + _ebrlOuterBlendValue = newWeight; + } + else + { + _ebrlOuterBlendValue = -weight; + } + } + + break; + case ".browOuterUpLeft": + if (weight > 0) + { + if (_ebrlOuterBlendValue != 0) + { + float newWeight = (_ebrlOuterBlendValue + weight) / 2f; + _ebrlOuterBlendValue = newWeight; + } + else + { + _ebrlOuterBlendValue = weight; + } + } + + break; + case ".browFrownRight": + if (weight > 0) + { + if (_ebrrFrownBlendValue != 0) + { + float newWeight = (_ebrrFrownBlendValue + -weight) / 2f; + _ebrrFrownBlendValue = newWeight; + } + else + { + _ebrrFrownBlendValue = -weight; + } + } + + break; + case ".browRaiseRight": + if (weight > 0) + { + if (_ebrrFrownBlendValue != 0) + { + float newWeight = (_ebrrFrownBlendValue + weight) / 2f; + _ebrrFrownBlendValue = newWeight; + } + else + { + _ebrrFrownBlendValue = weight; + } + } + + break; + case ".browInnerDownRight": + if (weight > 0) + { + if (_ebrrInnerBlendValue != 0) + { + float newWeight = (_ebrrInnerBlendValue + -weight) / 2f; + _ebrrInnerBlendValue = newWeight; + } + else + { + _ebrrInnerBlendValue = -weight; + } + } + + break; + case ".browInnerUpRight": + if (weight > 0) + { + if (_ebrrInnerBlendValue != 0) + { + float newWeight = (_ebrrInnerBlendValue + weight) / 2f; + _ebrrInnerBlendValue = newWeight; + } + else + { + _ebrrInnerBlendValue = weight; + } + } + + break; + case ".browOuterDownRight": + if (weight > 0) + { + if (_ebrrOuterBlendValue != 0) + { + float newWeight = (_ebrrOuterBlendValue + -weight) / 2f; + _ebrrOuterBlendValue = newWeight; + } + else + { + _ebrrOuterBlendValue = -weight; + } + } + + break; + case ".browOuterUpRight": + if (weight > 0) + { + if (_ebrrOuterBlendValue != 0) + { + float newWeight = (_ebrrOuterBlendValue + weight) / 2f; + _ebrrOuterBlendValue = newWeight; + } + else + { + _ebrrOuterBlendValue = weight; + } + } + + break; + case ".eyeLookDownLeft": + if (weight > 0) + { + if (_eyelUpDownBlendValue != 0) + { + float newWeight = (_eyelUpDownBlendValue + -weight) / 2f; + _eyelUpDownBlendValue = newWeight; + } + else + { + _eyelUpDownBlendValue = -weight; + } + } + + break; + case ".eyeLookUpLeft": + if (weight > 0) + { + if (_eyelUpDownBlendValue != 0) + { + float newWeight = (_eyelUpDownBlendValue + weight) / 2f; + _eyelUpDownBlendValue = newWeight; + } + else + { + _eyelUpDownBlendValue = weight; + } + } + + break; + case ".eyeLookOutLeft": + if (weight > 0) + { + if (_eyelLeftRightBlendValue != 0) + { + float newWeight = (_eyelLeftRightBlendValue + -weight) / 2f; + _eyelLeftRightBlendValue = newWeight; + } + else + { + _eyelLeftRightBlendValue = -weight; + } + } + + break; + case ".eyeLookInLeft": + if (weight > 0) + { + if (_eyelLeftRightBlendValue != 0) + { + float newWeight = (_eyelLeftRightBlendValue + weight) / 2f; + _eyelLeftRightBlendValue = newWeight; + } + else + { + _eyelLeftRightBlendValue = weight; + } + } + + break; + case ".eyeBlinkUpperLeft": + if (weight > 0) + { + if (_eyelBlinkBlendValue != 0) + { + float newWeight = (_eyelBlinkBlendValue + weight) / 2f; + _eyelBlinkBlendValue = newWeight; + } + else + { + _eyelBlinkBlendValue = weight; + } + } + + break; + case ".eyeBlinkLowerLeft": + if (weight > 0) + { + if (_eyelBlinkBlendValue != 0) + { + float newWeight = (_eyelBlinkBlendValue + weight) / 2f; + _eyelBlinkBlendValue = newWeight; + } + else + { + _eyelBlinkBlendValue = weight; + } + } + + break; + case ".eyeSquintLeft": + if (weight > 0) + { + if (_eyelSquintBlendValue != 0) + { + float newWeight = (_eyelSquintBlendValue + weight) / 2f; + _eyelSquintBlendValue = newWeight; + } + else + { + _eyelSquintBlendValue = weight; + } + } + + break; + case ".cheekSquintLeft": + if (weight > 0) + { + if (_eyelSquintBlendValue != 0) + { + float newWeight = (_eyelSquintBlendValue + weight) / 2f; + _eyelSquintBlendValue = newWeight; + } + else + { + _eyelSquintBlendValue = weight; + } + } + + break; + case ".eyeWideUpperLeft": + if (weight > 0) + { + if (_eyelWideBlendValue != 0) + { + float newWeight = (_eyelWideBlendValue + weight) / 2f; + _eyelWideBlendValue = newWeight; + } + else + { + _eyelWideBlendValue = weight; + } + } + + break; + case ".eyeWideLowerLeft": + if (weight > 0) + { + if (_eyelWideBlendValue != 0) + { + float newWeight = (_eyelWideBlendValue + weight) / 2f; + _eyelWideBlendValue = newWeight; + } + else + { + _eyelWideBlendValue = weight; + } + } + + break; + case ".eyeLookDownRight": + if (weight > 0) + { + if (_eyerUpDownBlendValue != 0) + { + float newWeight = (_eyerUpDownBlendValue + -weight) / 2f; + _eyerUpDownBlendValue = newWeight; + } + else + { + _eyerUpDownBlendValue = -weight; + } + } + + break; + case ".eyeLookUpRight": + if (weight > 0) + { + if (_eyerUpDownBlendValue != 0) + { + float newWeight = (_eyerUpDownBlendValue + weight) / 2f; + _eyerUpDownBlendValue = newWeight; + } + else + { + _eyerUpDownBlendValue = weight; + } + } + + break; + case ".eyeLookOutRight": + if (weight > 0) + { + if (_eyerLeftRightBlendValue != 0) + { + float newWeight = (_eyerLeftRightBlendValue + weight) / 2f; + _eyerLeftRightBlendValue = newWeight; + } + else + { + _eyerLeftRightBlendValue = weight; + } + } + + break; + case ".eyeLookInRight": + if (weight > 0) + { + if (_eyerLeftRightBlendValue != 0) + { + float newWeight = (_eyerLeftRightBlendValue + -weight) / 2f; + _eyerLeftRightBlendValue = newWeight; + } + else + { + _eyerLeftRightBlendValue = -weight; + } + } + + break; + case ".eyeBlinkUpperRight": + if (weight > 0) + { + if (_eyerBlinkBlendValue != 0) + { + float newWeight = (_eyerBlinkBlendValue + weight) / 2f; + _eyerBlinkBlendValue = newWeight; + } + else + { + _eyerBlinkBlendValue = weight; + } + } + + break; + case ".eyeBlinkLowerRight": + if (weight > 0) + { + if (_eyerBlinkBlendValue != 0) + { + float newWeight = (_eyerBlinkBlendValue + weight) / 2f; + _eyerBlinkBlendValue = newWeight; + } + else + { + _eyerBlinkBlendValue = weight; + } + } + + break; + case ".eyeSquintRight": + if (weight > 0) + { + if (_eyerSquintBlendValue != 0) + { + float newWeight = (_eyerSquintBlendValue + weight) / 2f; + _eyerSquintBlendValue = newWeight; + } + else + { + _eyerSquintBlendValue = weight; + } + } + + break; + case ".cheekSquintRight": + if (weight > 0) + { + if (_eyerSquintBlendValue != 0) + { + float newWeight = (_eyerSquintBlendValue + weight) / 2f; + _eyerSquintBlendValue = newWeight; + } + else + { + _eyerSquintBlendValue = weight; + } + } + + break; + case ".eyeWideUpperRight": + if (weight > 0) + { + if (_eyerWideBlendValue != 0) + { + float newWeight = (_eyerWideBlendValue + weight) / 2f; + _eyerWideBlendValue = newWeight; + } + else + { + _eyerWideBlendValue = weight; + } + } + + break; + case ".eyeWideLowerRight": + if (weight > 0) + { + if (_eyerWideBlendValue != 0) + { + float newWeight = (_eyerWideBlendValue + weight) / 2f; + _eyerWideBlendValue = newWeight; + } + else + { + _eyerWideBlendValue = weight; + } + } + + break; + case ".noseSneerLeft": + if (weight > 0) + { + if (_noslSneerBlendValue != 0) + { + float newWeight = (_noslSneerBlendValue + weight) / 2f; + _noslSneerBlendValue = newWeight; + } + else + { + _noslSneerBlendValue = weight; + } + } + + break; + case ".noseSneerRight": + if (weight > 0) + { + if (_nosrSneerBlendValue != 0) + { + float newWeight = (_nosrSneerBlendValue + weight) / 2f; + _nosrSneerBlendValue = newWeight; + } + else + { + _nosrSneerBlendValue = weight; + } + } + + break; + case ".cheekHollowLeft": + if (weight > 0) + { + if (_chklHollowPuffBlendValue != 0) + { + float newWeight = (_chklHollowPuffBlendValue + -weight) / 2f; + _chklHollowPuffBlendValue = newWeight; + } + else + { + _chklHollowPuffBlendValue = -weight; + } + } + + break; + case ".cheekPuffLeft": + if (weight > 0) + { + if (_chklHollowPuffBlendValue != 0) + { + float newWeight = (_chklHollowPuffBlendValue + weight) / 2f; + _chklHollowPuffBlendValue = newWeight; + } + else + { + _chklHollowPuffBlendValue = weight; + } + } + + break; + case ".cheekHollowRight": + if (weight > 0) + { + if (_chkrHollowPuffBlendValue != 0) + { + float newWeight = (_chkrHollowPuffBlendValue + -weight) / 2f; + _chkrHollowPuffBlendValue = newWeight; + } + else + { + _chkrHollowPuffBlendValue = -weight; + } + } + + break; + case ".cheekPuffRight": + if (weight > 0) + { + if (_chkrHollowPuffBlendValue != 0) + { + float newWeight = (_chkrHollowPuffBlendValue + weight) / 2f; + _chkrHollowPuffBlendValue = newWeight; + } + else + { + _chkrHollowPuffBlendValue = weight; + } + } + + break; + case ".jawClose": + if (weight > 0) + { + if (_jawOpenCloseBlendValue != 0) + { + float newWeight = (_jawOpenCloseBlendValue + -weight) / 2f; + _jawOpenCloseBlendValue = newWeight; + } + else + { + _jawOpenCloseBlendValue = -weight; + } + } + + break; + case ".jawOpen": + if (weight > 0) + { + if (_jawOpenCloseBlendValue != 0) + { + float newWeight = (_jawOpenCloseBlendValue + weight) / 2f; + _jawOpenCloseBlendValue = newWeight; + } + else + { + _jawOpenCloseBlendValue = weight; + } + } + + break; + case ".jawLeft": + if (weight > 0) + { + if (_jawLeftRightBlendValue != 0) + { + float newWeight = (_jawLeftRightBlendValue + -weight) / 2f; + _jawLeftRightBlendValue = newWeight; + } + else + { + _jawLeftRightBlendValue = -weight; + } + } + + break; + case ".jawRight": + if (weight > 0) + { + if (_jawLeftRightBlendValue != 0) + { + float newWeight = (_jawLeftRightBlendValue + weight) / 2f; + _jawLeftRightBlendValue = newWeight; + } + else + { + _jawLeftRightBlendValue = weight; + } + } + + break; + case ".jawBackward": + if (weight > 0) + { + if (_jawBackForwardBlendValue != 0) + { + float newWeight = (_jawBackForwardBlendValue + -weight) / 2f; + _jawBackForwardBlendValue = newWeight; + } + else + { + _jawBackForwardBlendValue = -weight; + } + } + + break; + case ".jawForward": + if (weight > 0) + { + if (_jawBackForwardBlendValue != 0) + { + float newWeight = (_jawBackForwardBlendValue + weight) / 2f; + _jawBackForwardBlendValue = newWeight; + } + else + { + _jawBackForwardBlendValue = weight; + } + } + + break; + case ".mouthLeft": + if (weight > 0) + { + if (_mthLeftRightBlendValue != 0) + { + float newWeight = (_mthLeftRightBlendValue + -weight) / 2f; + _mthLeftRightBlendValue = newWeight; + } + else + { + _mthLeftRightBlendValue = -weight; + } + } + + break; + case ".mouthRight": + if (weight > 0) + { + if (_mthLeftRightBlendValue != 0) + { + float newWeight = (_mthLeftRightBlendValue + weight) / 2f; + _mthLeftRightBlendValue = newWeight; + } + else + { + _mthLeftRightBlendValue = weight; + } + } + + break; + case ".mouthFunnel": + if (weight > 0) + { + if (_mthFunnelBlendValue != 0) + { + float newWeight = (_mthFunnelBlendValue + weight) / 2f; + _mthFunnelBlendValue = newWeight; + } + else + { + _mthFunnelBlendValue = weight; + } + } + + break; + case ".mouthPucker": + if (weight > 0) + { + if (_mthPuckerBlendValue != 0) + { + float newWeight = (_mthPuckerBlendValue + weight) / 2f; + _mthPuckerBlendValue = newWeight; + } + else + { + _mthPuckerBlendValue = weight; + } + } + + break; + case ".mouthShrugUpper": + if (weight > 0) + { + if (_mthShrugUpperBlendValue != 0) + { + float newWeight = (_mthShrugUpperBlendValue + weight) / 2f; + _mthShrugUpperBlendValue = newWeight; + } + else + { + _mthShrugUpperBlendValue = weight; + } + } + + break; + case ".mouthShrugLower": + if (weight > 0) + { + if (_mthShrugLowerBlendValue != 0) + { + float newWeight = (_mthShrugLowerBlendValue + weight) / 2f; + _mthShrugLowerBlendValue = newWeight; + } + else + { + _mthShrugLowerBlendValue = weight; + } + } + + break; + case ".mouthRollUpper": + if (weight > 0) + { + if (_mthRollUpperBlendValue != 0) + { + float newWeight = (_mthRollUpperBlendValue + weight) / 2f; + _mthRollUpperBlendValue = newWeight; + } + else + { + _mthRollUpperBlendValue = weight; + } + } + + break; + case ".mouthRollOutUpper": + if (weight > 0) + { + if (_mthRollOutUpperBlendValue != 0) + { + float newWeight = (_mthRollOutUpperBlendValue + weight) / 2f; + _mthRollOutUpperBlendValue = newWeight; + } + else + { + _mthRollOutUpperBlendValue = weight; + } + } + + break; + case ".mouthRollLower": + if (weight > 0) + { + if (_mthRollLowerBlendValue != 0) + { + float newWeight = (_mthRollLowerBlendValue + weight) / 2f; + _mthRollLowerBlendValue = newWeight; + } + else + { + _mthRollLowerBlendValue = weight; + } + } + + break; + case ".mouthRollOutLower": + if (weight > 0) + { + if (_mthRollOutLowerBlendValue != 0) + { + float newWeight = (_mthRollOutLowerBlendValue + weight) / 2f; + _mthRollOutLowerBlendValue = newWeight; + } + else + { + _mthRollOutLowerBlendValue = weight; + } + } + + break; + case ".mouthClose": + if (weight > 0) + { + if (_mthCloseBlendValue != 0) + { + float newWeight = (_mthCloseBlendValue + weight) / 2f; + _mthCloseBlendValue = newWeight; + } + else + { + _mthCloseBlendValue = weight; + } + } + + break; + case ".mouthFrownLeft": + if (weight > 0) + { + if (_mthlFrownSmileBlendValue != 0) + { + float newWeight = (_mthlFrownSmileBlendValue + -weight) / 2f; + _mthlFrownSmileBlendValue = newWeight; + } + else + { + _mthlFrownSmileBlendValue = -weight; + } + } + + break; + case ".mouthSmileLeft": + if (weight > 0) + { + if (_mthlFrownSmileBlendValue != 0) + { + float newWeight = (_mthlFrownSmileBlendValue + weight) / 2f; + _mthlFrownSmileBlendValue = newWeight; + } + else + { + _mthlFrownSmileBlendValue = weight; + } + } + + break; + case ".mouthPressLeft": + if (weight > 0) + { + if (_mthlPressStretchBlendValue != 0) + { + float newWeight = (_mthlPressStretchBlendValue + -weight) / 2f; + _mthlPressStretchBlendValue = newWeight; + } + else + { + _mthlPressStretchBlendValue = -weight; + } + } + + break; + case ".mouthStretchLeft": + if (weight > 0) + { + if (_mthlPressStretchBlendValue != 0) + { + float newWeight = (_mthlPressStretchBlendValue + weight) / 2f; + _mthlPressStretchBlendValue = newWeight; + } + else + { + _mthlPressStretchBlendValue = weight; + } + } + + break; + case ".mouthUpperUpLeft": + if (weight > 0) + { + if (_mthlUpperUpBlendValue != 0) + { + float newWeight = (_mthlUpperUpBlendValue + weight) / 2f; + _mthlUpperUpBlendValue = newWeight; + } + else + { + _mthlUpperUpBlendValue = weight; + } + } + + break; + case ".mouthLowerDownLeft": + if (weight > 0) + { + if (_mthlLowerDownBlendValue != 0) + { + float newWeight = (_mthlLowerDownBlendValue + weight) / 2f; + _mthlLowerDownBlendValue = newWeight; + } + else + { + _mthlLowerDownBlendValue = weight; + } + } + + break; + case ".mouthFrownRight": + if (weight > 0) + { + if (_mthrFrownSmileBlendValue != 0) + { + float newWeight = (_mthrFrownSmileBlendValue + -weight) / 2f; + _mthrFrownSmileBlendValue = newWeight; + } + else + { + _mthrFrownSmileBlendValue = -weight; + } + } + + break; + case ".mouthSmileRight": + if (weight > 0) + { + if (_mthrFrownSmileBlendValue != 0) + { + float newWeight = (_mthrFrownSmileBlendValue + weight) / 2f; + _mthrFrownSmileBlendValue = newWeight; + } + else + { + _mthrFrownSmileBlendValue = weight; + } + } + + break; + case ".mouthPressRight": + if (weight > 0) + { + if (_mthrPressStretchBlendValue != 0) + { + float newWeight = (_mthrPressStretchBlendValue + -weight) / 2f; + _mthrPressStretchBlendValue = newWeight; + } + else + { + _mthrPressStretchBlendValue = -weight; + } + } + + break; + case ".mouthStretchRight": + if (weight > 0) + { + if (_mthrPressStretchBlendValue != 0) + { + float newWeight = (_mthrPressStretchBlendValue + weight) / 2f; + _mthrPressStretchBlendValue = newWeight; + } + else + { + _mthrPressStretchBlendValue = weight; + } + } + + break; + case ".mouthUpperUpRight": + if (weight > 0) + { + if (_mthrUpperUpBlendValue != 0) + { + float newWeight = (_mthrUpperUpBlendValue + weight) / 2f; + _mthrUpperUpBlendValue = newWeight; + } + else + { + _mthrUpperUpBlendValue = weight; + } + } + + break; + case ".mouthLowerDownRight": + if (weight > 0) + { + if (_mthrLowerDownBlendValue != 0) + { + float newWeight = (_mthrLowerDownBlendValue + weight) / 2f; + _mthrLowerDownBlendValue = newWeight; + } + else + { + _mthrLowerDownBlendValue = weight; + } + } + + break; + case ".tongueDown": + if (weight > 0) + { + if (_tongDownUpBlendValue != 0) + { + float newWeight = (_tongDownUpBlendValue + -weight) / 2f; + _tongDownUpBlendValue = newWeight; + } + else + { + _tongDownUpBlendValue = -weight; + } + } + + break; + case ".tongueUp": + if (weight > 0) + { + if (_tongDownUpBlendValue != 0) + { + float newWeight = (_tongDownUpBlendValue + weight) / 2f; + _tongDownUpBlendValue = newWeight; + } + else + { + _tongDownUpBlendValue = weight; + } + } + + break; + case ".tongueIn": + if (weight > 0) + { + if (_tongInOutBlendValue != 0) + { + float newWeight = (_tongInOutBlendValue + -weight) / 2f; + _tongInOutBlendValue = newWeight; + } + else + { + _tongInOutBlendValue = -weight; + } + } + + break; + case ".tongueOut": + if (weight > 0) + { + if (_tongInOutBlendValue != 0) + { + float newWeight = (_tongInOutBlendValue + weight) / 2f; + _tongInOutBlendValue = newWeight; + } + else + { + _tongInOutBlendValue = weight; + } + } + + break; + case ".tongueLower": + if (weight > 0) + { + if (_tongLowerRaiseBlendValue != 0) + { + float newWeight = (_tongLowerRaiseBlendValue + -weight) / 2f; + _tongLowerRaiseBlendValue = newWeight; + } + else + { + _tongLowerRaiseBlendValue = -weight; + } + } + + break; + case ".tongueRaise": + if (weight > 0) + { + if (_tongLowerRaiseBlendValue != 0) + { + float newWeight = (_tongLowerRaiseBlendValue + weight) / 2f; + _tongLowerRaiseBlendValue = newWeight; + } + else + { + _tongLowerRaiseBlendValue = weight; + } + } + + break; + case ".tongueTwistLeft": + if (weight > 0) + { + if (_tongTwistLeftRightBlendValue != 0) + { + float newWeight = (_tongTwistLeftRightBlendValue + -weight) / 2f; + _tongTwistLeftRightBlendValue = newWeight; + } + else + { + _tongTwistLeftRightBlendValue = -weight; + } + } + + break; + case ".tongueTwistRight": + if (weight > 0) + { + if (_tongTwistLeftRightBlendValue != 0) + { + float newWeight = (_tongTwistLeftRightBlendValue + weight) / 2f; + _tongTwistLeftRightBlendValue = newWeight; + } + else + { + _tongTwistLeftRightBlendValue = weight; + } + } + + break; + case ".tongueCurlDown": + if (weight > 0) + { + if (_tongCurlDownUpBlendValue != 0) + { + float newWeight = (_tongCurlDownUpBlendValue + -weight) / 2f; + _tongCurlDownUpBlendValue = newWeight; + } + else + { + _tongCurlDownUpBlendValue = -weight; + } + } + + break; + case ".tongueCurlUp": + if (weight > 0) + { + if (_tongCurlDownUpBlendValue != 0) + { + float newWeight = (_tongCurlDownUpBlendValue + weight) / 2f; + _tongCurlDownUpBlendValue = newWeight; + } + else + { + _tongCurlDownUpBlendValue = weight; + } + } + + break; + case ".tongueCurlLeft": + if (weight > 0) + { + if (_tongCurlLeftRightBlendValue != 0) + { + float newWeight = (_tongCurlLeftRightBlendValue + -weight) / 2f; + _tongCurlLeftRightBlendValue = newWeight; + } + else + { + _tongCurlLeftRightBlendValue = -weight; + } + } + + break; + case ".tongueCurlRight": + if (weight > 0) + { + if (_tongCurlLeftRightBlendValue != 0) + { + float newWeight = (_tongCurlLeftRightBlendValue + weight) / 2f; + _tongCurlLeftRightBlendValue = newWeight; + } + else + { + _tongCurlLeftRightBlendValue = weight; + } + } + + break; + case ".tongueSideCurlDown": + if (weight > 0) + { + if (_tongCurlSideDownUpBlendValue != 0) + { + float newWeight = (_tongCurlSideDownUpBlendValue + -weight) / 2f; + _tongCurlSideDownUpBlendValue = newWeight; + } + else + { + _tongCurlSideDownUpBlendValue = -weight; + } + } + + break; + case ".tongueSideCurlUp": + if (weight > 0) + { + if (_tongCurlSideDownUpBlendValue != 0) + { + float newWeight = (_tongCurlSideDownUpBlendValue + weight) / 2f; + _tongCurlSideDownUpBlendValue = newWeight; + } + else + { + _tongCurlSideDownUpBlendValue = weight; + } + } + + break; + } + + #endregion + } + } + } + } + + public void SavePreset() + { + if (string.IsNullOrEmpty(_saveName)) + { + EditorUtility.DisplayDialog("Unable to Save Preset", "No preset name was provided to save the preset to.", "Ok"); + return; + } + + List serializedData = SerializeValues(); + string outputFileName = Path.Combine(_presetDirectory, _saveName + ".fcp"); + File.WriteAllLines(outputFileName, serializedData); + } + + public List SerializeValues() + { + List serialisedValues = new List(); + foreach (string field in _variableNames) + { + switch (field) + { + case "ebrlFrownBlendValue": + serialisedValues.Add(field + ":" + _ebrlFrownBlendValue); + break; + case "ebrlInnerBlendValue": + serialisedValues.Add(field + ":" + _ebrlInnerBlendValue); + break; + case "ebrlOuterBlendValue": + serialisedValues.Add(field + ":" + _ebrlOuterBlendValue); + break; + case "ebrrFrownBlendValue": + serialisedValues.Add(field + ":" + _ebrrFrownBlendValue); + break; + case "ebrrInnerBlendValue": + serialisedValues.Add(field + ":" + _ebrrInnerBlendValue); + break; + case "ebrrOuterBlendValue": + serialisedValues.Add(field + ":" + _ebrrOuterBlendValue); + break; + case "eyelUpDownBlendValue": + serialisedValues.Add(field + ":" + _eyelUpDownBlendValue); + break; + case "eyelLeftRightBlendValue": + serialisedValues.Add(field + ":" + _eyelLeftRightBlendValue); + break; + case "eyelBlinkBlendValue": + serialisedValues.Add(field + ":" + _eyelBlinkBlendValue); + break; + case "eyelSquintBlendValue": + serialisedValues.Add(field + ":" + _eyelSquintBlendValue); + break; + case "eyelWideBlendValue": + serialisedValues.Add(field + ":" + _eyelWideBlendValue); + break; + case "eyerUpDownBlendValue": + serialisedValues.Add(field + ":" + _eyerUpDownBlendValue); + break; + case "eyerLeftRightBlendValue": + serialisedValues.Add(field + ":" + _eyerLeftRightBlendValue); + break; + case "eyerBlinkBlendValue": + serialisedValues.Add(field + ":" + _eyerBlinkBlendValue); + break; + case "eyerSquintBlendValue": + serialisedValues.Add(field + ":" + _eyerSquintBlendValue); + break; + case "eyerWideBlendValue": + serialisedValues.Add(field + ":" + _eyerWideBlendValue); + break; + case "noslSneerBlendValue": + serialisedValues.Add(field + ":" + _noslSneerBlendValue); + break; + case "nosrSneerBlendValue": + serialisedValues.Add(field + ":" + _nosrSneerBlendValue); + break; + case "chklHollowPuffBlendValue": + serialisedValues.Add(field + ":" + _chklHollowPuffBlendValue); + break; + case "chkrHollowPuffBlendValue": + serialisedValues.Add(field + ":" + _chkrHollowPuffBlendValue); + break; + case "jawOpenCloseBlendValue": + serialisedValues.Add(field + ":" + _jawOpenCloseBlendValue); + break; + case "jawLeftRightBlendValue": + serialisedValues.Add(field + ":" + _jawLeftRightBlendValue); + break; + case "jawBackForwardBlendValue": + serialisedValues.Add(field + ":" + _jawBackForwardBlendValue); + break; + case "mthLeftRightBlendValue": + serialisedValues.Add(field + ":" + _mthLeftRightBlendValue); + break; + case "mthFunnelBlendValue": + serialisedValues.Add(field + ":" + _mthFunnelBlendValue); + break; + case "mthPuckerBlendValue": + serialisedValues.Add(field + ":" + _mthPuckerBlendValue); + break; + case "mthShrugUpperBlendValue": + serialisedValues.Add(field + ":" + _mthShrugUpperBlendValue); + break; + case "mthShrugLowerBlendValue": + serialisedValues.Add(field + ":" + _mthShrugLowerBlendValue); + break; + case "mthRollUpperBlendValue": + serialisedValues.Add(field + ":" + _mthRollUpperBlendValue); + break; + case "mthRollOutUpperBlendValue": + serialisedValues.Add(field + ":" + _mthRollOutUpperBlendValue); + break; + case "mthRollLowerBlendValue": + serialisedValues.Add(field + ":" + _mthRollLowerBlendValue); + break; + case "mthRollOutLowerBlendValue": + serialisedValues.Add(field + ":" + _mthRollOutLowerBlendValue); + break; + case "mthCloseBlendValue": + serialisedValues.Add(field + ":" + _mthCloseBlendValue); + break; + case "mthlFrownSmileBlendValue": + serialisedValues.Add(field + ":" + _mthlFrownSmileBlendValue); + break; + case "mthrFrownSmileBlendValue": + serialisedValues.Add(field + ":" + _mthrFrownSmileBlendValue); + break; + case "mthlPressStretchBlendValue": + serialisedValues.Add(field + ":" + _mthlPressStretchBlendValue); + break; + case "mthrPressStretchBlendValue": + serialisedValues.Add(field + ":" + _mthrPressStretchBlendValue); + break; + case "mthlUpperUpBlendValue": + serialisedValues.Add(field + ":" + _mthlUpperUpBlendValue); + break; + case "mthrUpperUpBlendValue": + serialisedValues.Add(field + ":" + _mthrUpperUpBlendValue); + break; + case "mthlLowerDownBlendValue": + serialisedValues.Add(field + ":" + _mthlLowerDownBlendValue); + break; + case "mthrLowerDownBlendValue": + serialisedValues.Add(field + ":" + _mthrLowerDownBlendValue); + break; + case "tongDownUpBlendValue": + serialisedValues.Add(field + ":" + _tongDownUpBlendValue); + break; + case "tongInOutBlendValue": + serialisedValues.Add(field + ":" + _tongInOutBlendValue); + break; + case "tongLowerRaiseBlendValue": + serialisedValues.Add(field + ":" + _tongLowerRaiseBlendValue); + break; + case "tongTwistLeftRightBlendValue": + serialisedValues.Add(field + ":" + _tongTwistLeftRightBlendValue); + break; + case "tongCurlDownUpBlendValue": + serialisedValues.Add(field + ":" + _tongCurlDownUpBlendValue); + break; + case "tongCurlLeftRightBlendValue": + serialisedValues.Add(field + ":" + _tongCurlLeftRightBlendValue); + break; + case "tongCurlSideDownUpBlendValue": + serialisedValues.Add(field + ":" + _tongCurlSideDownUpBlendValue); + break; + } + } + + return serialisedValues; + } + + public void LoadPreset(string presetName) + { + if (presetName == "None") + { + return; + } + + string fileLocation = _presetFileDictionary[presetName]; + List serializedData = File.ReadAllLines(fileLocation).ToList(); + string line; + foreach (string field in _variableNames) + { + switch (field) + { + case "ebrlFrownBlendValue": + line = serializedData.Find(data => data.Contains("ebrlFrownBlendValue")); + _ebrlFrownBlendValue = GetValue(line); + break; + case "ebrlInnerBlendValue": + line = serializedData.Find(data => data.Contains("ebrlInnerBlendValue")); + _ebrlInnerBlendValue = GetValue(line); + break; + case "ebrlOuterBlendValue": + line = serializedData.Find(data => data.Contains("ebrlOuterBlendValue")); + _ebrlOuterBlendValue = GetValue(line); + break; + case "ebrrFrownBlendValue": + line = serializedData.Find(data => data.Contains("ebrrFrownBlendValue")); + _ebrrFrownBlendValue = GetValue(line); + break; + case "ebrrInnerBlendValue": + line = serializedData.Find(data => data.Contains("ebrrInnerBlendValue")); + _ebrrInnerBlendValue = GetValue(line); + break; + case "ebrrOuterBlendValue": + line = serializedData.Find(data => data.Contains("ebrrOuterBlendValue")); + _ebrrOuterBlendValue = GetValue(line); + break; + case "eyelUpDownBlendValue": + line = serializedData.Find(data => data.Contains("eyelUpDownBlendValue")); + _eyelUpDownBlendValue = GetValue(line); + break; + case "eyelLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("eyelLeftRightBlendValue")); + _eyelLeftRightBlendValue = GetValue(line); + break; + case "eyelBlinkBlendValue": + line = serializedData.Find(data => data.Contains("eyelBlinkBlendValue")); + _eyelBlinkBlendValue = GetValue(line); + break; + case "eyelSquintBlendValue": + line = serializedData.Find(data => data.Contains("eyelSquintBlendValue")); + _eyelSquintBlendValue = GetValue(line); + break; + case "eyelWideBlendValue": + line = serializedData.Find(data => data.Contains("eyelWideBlendValue")); + _eyelWideBlendValue = GetValue(line); + break; + case "eyerUpDownBlendValue": + line = serializedData.Find(data => data.Contains("eyerUpDownBlendValue")); + _eyerUpDownBlendValue = GetValue(line); + break; + case "eyerLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("eyerLeftRightBlendValue")); + _eyerLeftRightBlendValue = GetValue(line); + break; + case "eyerBlinkBlendValue": + line = serializedData.Find(data => data.Contains("eyerBlinkBlendValue")); + _eyerBlinkBlendValue = GetValue(line); + break; + case "eyerSquintBlendValue": + line = serializedData.Find(data => data.Contains("eyerSquintBlendValue")); + _eyerSquintBlendValue = GetValue(line); + break; + case "eyerWideBlendValue": + line = serializedData.Find(data => data.Contains("eyerWideBlendValue")); + _eyerWideBlendValue = GetValue(line); + break; + case "noslSneerBlendValue": + line = serializedData.Find(data => data.Contains("noslSneerBlendValue")); + _noslSneerBlendValue = GetValue(line); + break; + case "nosrSneerBlendValue": + line = serializedData.Find(data => data.Contains("nosrSneerBlendValue")); + _nosrSneerBlendValue = GetValue(line); + break; + case "chklHollowPuffBlendValue": + line = serializedData.Find(data => data.Contains("chklHollowPuffBlendValue")); + _chklHollowPuffBlendValue = GetValue(line); + break; + case "chkrHollowPuffBlendValue": + line = serializedData.Find(data => data.Contains("chkrHollowPuffBlendValue")); + _chkrHollowPuffBlendValue = GetValue(line); + break; + case "jawOpenCloseBlendValue": + line = serializedData.Find(data => data.Contains("jawOpenCloseBlendValue")); + _jawOpenCloseBlendValue = GetValue(line); + break; + case "jawLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("jawLeftRightBlendValue")); + _jawLeftRightBlendValue = GetValue(line); + break; + case "jawBackForwardBlendValue": + line = serializedData.Find(data => data.Contains("jawBackForwardBlendValue")); + _jawBackForwardBlendValue = GetValue(line); + break; + case "mthLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("mthLeftRightBlendValue")); + _mthLeftRightBlendValue = GetValue(line); + break; + case "mthFunnelBlendValue": + line = serializedData.Find(data => data.Contains("mthFunnelBlendValue")); + _mthFunnelBlendValue = GetValue(line); + break; + case "mthPuckerBlendValue": + line = serializedData.Find(data => data.Contains("mthPuckerBlendValue")); + _mthPuckerBlendValue = GetValue(line); + break; + case "mthShrugUpperBlendValue": + line = serializedData.Find(data => data.Contains("mthShrugUpperBlendValue")); + _mthShrugUpperBlendValue = GetValue(line); + break; + case "mthShrugLowerBlendValue": + line = serializedData.Find(data => data.Contains("mthShrugLowerBlendValue")); + _mthShrugLowerBlendValue = GetValue(line); + break; + case "mthRollUpperBlendValue": + line = serializedData.Find(data => data.Contains("mthRollUpperBlendValue")); + _mthRollUpperBlendValue = GetValue(line); + break; + case "mthRollOutUpperBlendValue": + line = serializedData.Find(data => data.Contains("mthRollOutUpperBlendValue")); + _mthRollOutUpperBlendValue = GetValue(line); + break; + case "mthRollLowerBlendValue": + line = serializedData.Find(data => data.Contains("mthRollLowerBlendValue")); + _mthRollLowerBlendValue = GetValue(line); + break; + case "mthRollOutLowerBlendValue": + line = serializedData.Find(data => data.Contains("mthRollOutLowerBlendValue")); + _mthRollOutLowerBlendValue = GetValue(line); + break; + case "mthCloseBlendValue": + line = serializedData.Find(data => data.Contains("mthCloseBlendValue")); + _mthCloseBlendValue = GetValue(line); + break; + case "mthlFrownSmileBlendValue": + line = serializedData.Find(data => data.Contains("mthlFrownSmileBlendValue")); + _mthlFrownSmileBlendValue = GetValue(line); + break; + case "mthrFrownSmileBlendValue": + line = serializedData.Find(data => data.Contains("mthrFrownSmileBlendValue")); + _mthrFrownSmileBlendValue = GetValue(line); + break; + case "mthlPressStretchBlendValue": + line = serializedData.Find(data => data.Contains("mthlPressStretchBlendValue")); + _mthlPressStretchBlendValue = GetValue(line); + break; + case "mthrPressStretchBlendValue": + line = serializedData.Find(data => data.Contains("mthrPressStretchBlendValue")); + _mthrPressStretchBlendValue = GetValue(line); + break; + case "mthlUpperUpBlendValue": + line = serializedData.Find(data => data.Contains("mthlUpperUpBlendValue")); + _mthlUpperUpBlendValue = GetValue(line); + break; + case "mthrUpperUpBlendValue": + line = serializedData.Find(data => data.Contains("mthrUpperUpBlendValue")); + _mthrUpperUpBlendValue = GetValue(line); + break; + case "mthlLowerDownBlendValue": + line = serializedData.Find(data => data.Contains("mthlLowerDownBlendValue")); + _mthlLowerDownBlendValue = GetValue(line); + break; + case "mthrLowerDownBlendValue": + line = serializedData.Find(data => data.Contains("mthrLowerDownBlendValue")); + _mthrLowerDownBlendValue = GetValue(line); + break; + case "tongDownUpBlendValue": + line = serializedData.Find(data => data.Contains("tongDownUpBlendValue")); + _tongDownUpBlendValue = GetValue(line); + break; + case "tongInOutBlendValue": + line = serializedData.Find(data => data.Contains("tongInOutBlendValue")); + _tongInOutBlendValue = GetValue(line); + break; + case "tongLowerRaiseBlendValue": + line = serializedData.Find(data => data.Contains("tongLowerRaiseBlendValue")); + _tongLowerRaiseBlendValue = GetValue(line); + break; + case "tongTwistLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("tongTwistLeftRightBlendValue")); + _tongTwistLeftRightBlendValue = GetValue(line); + break; + case "tongCurlDownUpBlendValue": + line = serializedData.Find(data => data.Contains("tongCurlDownUpBlendValue")); + _tongCurlDownUpBlendValue = GetValue(line); + break; + case "tongCurlLeftRightBlendValue": + line = serializedData.Find(data => data.Contains("tongCurlLeftRightBlendValue")); + _tongCurlLeftRightBlendValue = GetValue(line); + break; + case "tongCurlSideDownUpBlendValue": + line = serializedData.Find(data => data.Contains("tongCurlSideDownUpBlendValue")); + _tongCurlSideDownUpBlendValue = GetValue(line); + break; + } + } + + ApplyBlendshapes(); + } + + public float GetValue(string line) + { + int index = line.IndexOf(":", StringComparison.Ordinal) + 1; + if (float.TryParse(line.Substring(index, line.Length - index), out float value)) + { + return value; + } + + return 0f; + } + + public void ResetAllSliders() + { + #region RESET_BLENDS + foreach (string field in _variableNames) + { + switch (field) + { + case "ebrlFrownBlendValue": + _ebrlFrownBlendValue = 0; + break; + case "ebrlInnerBlendValue": + _ebrlInnerBlendValue = 0; + break; + case "ebrlOuterBlendValue": + _ebrlOuterBlendValue = 0; + break; + case "ebrrFrownBlendValue": + _ebrrFrownBlendValue = 0; + break; + case "ebrrInnerBlendValue": + _ebrrInnerBlendValue = 0; + break; + case "ebrrOuterBlendValue": + _ebrrOuterBlendValue = 0; + break; + case "eyelUpDownBlendValue": + _eyelUpDownBlendValue = 0; + break; + case "eyelLeftRightBlendValue": + _eyelLeftRightBlendValue = 0; + break; + case "eyelBlinkBlendValue": + _eyelBlinkBlendValue = 0; + break; + case "eyelSquintBlendValue": + _eyelSquintBlendValue = 0; + break; + case "eyelWideBlendValue": + _eyelWideBlendValue = 0; + break; + case "eyerUpDownBlendValue": + _eyerUpDownBlendValue = 0; + break; + case "eyerLeftRightBlendValue": + _eyerLeftRightBlendValue = 0; + break; + case "eyerBlinkBlendValue": + _eyerBlinkBlendValue = 0; + break; + case "eyerSquintBlendValue": + _eyerSquintBlendValue = 0; + break; + case "eyerWideBlendValue": + _eyerWideBlendValue = 0; + break; + case "noslSneerBlendValue": + _noslSneerBlendValue = 0; + break; + case "nosrSneerBlendValue": + _nosrSneerBlendValue = 0; + break; + case "chklHollowPuffBlendValue": + _chklHollowPuffBlendValue = 0; + break; + case "chkrHollowPuffBlendValue": + _chkrHollowPuffBlendValue = 0; + break; + case "jawOpenCloseBlendValue": + _jawOpenCloseBlendValue = 0; + break; + case "jawLeftRightBlendValue": + _jawLeftRightBlendValue = 0; + break; + case "jawBackForwardBlendValue": + _jawBackForwardBlendValue = 0; + break; + case "mthLeftRightBlendValue": + _mthLeftRightBlendValue = 0; + break; + case "mthFunnelBlendValue": + _mthFunnelBlendValue = 0; + break; + case "mthPuckerBlendValue": + _mthPuckerBlendValue = 0; + break; + case "mthShrugUpperBlendValue": + _mthShrugUpperBlendValue = 0; + break; + case "mthShrugLowerBlendValue": + _mthShrugLowerBlendValue = 0; + break; + case "mthRollUpperBlendValue": + _mthRollUpperBlendValue = 0; + break; + case "mthRollOutUpperBlendValue": + _mthRollOutUpperBlendValue = 0; + break; + case "mthRollLowerBlendValue": + _mthRollLowerBlendValue = 0; + break; + case "mthRollOutLowerBlendValue": + _mthRollOutLowerBlendValue = 0; + break; + case "mthCloseBlendValue": + _mthCloseBlendValue = 0; + break; + case "mthlFrownSmileBlendValue": + _mthlFrownSmileBlendValue = 0; + break; + case "mthrFrownSmileBlendValue": + _mthrFrownSmileBlendValue = 0; + break; + case "mthlPressStretchBlendValue": + _mthlPressStretchBlendValue = 0; + break; + case "mthrPressStretchBlendValue": + _mthrPressStretchBlendValue = 0; + break; + case "mthlUpperUpBlendValue": + _mthlUpperUpBlendValue = 0; + break; + case "mthrUpperUpBlendValue": + _mthrUpperUpBlendValue = 0; + break; + case "mthlLowerDownBlendValue": + _mthlLowerDownBlendValue = 0; + break; + case "mthrLowerDownBlendValue": + _mthrLowerDownBlendValue = 0; + break; + case "tongDownUpBlendValue": + _tongDownUpBlendValue = 0; + break; + case "tongInOutBlendValue": + _tongInOutBlendValue = 0; + break; + case "tongLowerRaiseBlendValue": + _tongLowerRaiseBlendValue = 0; + break; + case "tongTwistLeftRightBlendValue": + _tongTwistLeftRightBlendValue = 0; + break; + case "tongCurlDownUpBlendValue": + _tongCurlDownUpBlendValue = 0; + break; + case "tongCurlLeftRightBlendValue": + _tongCurlLeftRightBlendValue = 0; + break; + case "tongCurlSideDownUpBlendValue": + _tongCurlSideDownUpBlendValue = 0; + break; + } + } + #endregion + } + + public void PopulatePresetList() + { + _presetNames = new List(); + if (!string.IsNullOrEmpty(_presetDirectory)) + { + List files = Directory.GetFiles(_presetDirectory, "*.fcp", SearchOption.AllDirectories).ToList(); + foreach (string file in files) + { + FileInfo info = new FileInfo(file); + string fileName = info.Name.Substring(0, info.Name.IndexOf(".fcp", StringComparison.Ordinal)); + _presetNames.Add(fileName); + _presetFileDictionary.TryAdd(fileName, file); + } + } + } + } + + [CustomEditor(typeof(FacialController))] + public class FacialControllerInspector : Editor + { + public override VisualElement CreateInspectorGUI() + { + FacialController controller = (FacialController) target; + VisualElement root = new VisualElement(); + + #region PRESETS + Foldout presets = new Foldout() + { + text = "Presets", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + Label presetFolderTitle = new Label("Preset Directory"); + + presets.Add(presetFolderTitle); + + VisualElement directoryLayout = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row) + } + }; + + TextField directoryField = new TextField() + { + style = + { + width = Length.Percent(85), + }, + isReadOnly = true, + bindingPath = "_presetDirectory" + }; + + Button directoryPickerButton = new Button( + delegate + { + string directory = EditorUtility.OpenFolderPanel("Select Directory", "Assets", ""); + if (!string.IsNullOrEmpty(directory) && directory.Contains("Assets")) + { + int index = directory.IndexOf("Assets", StringComparison.Ordinal); + directoryField.value = directory.Substring(index, directory.Length - index); + } + } + ) + { + text = "Browse", + style = + { + width = Length.Percent(12), + }, + }; + + directoryLayout.Add(directoryPickerButton); + directoryLayout.Add(directoryField); + + presets.Add(directoryLayout); + + Label loadPreset = new Label("Load Preset"); + presets.Add(loadPreset); + + VisualElement presetLayout = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row) + } + }; + + List popupValues = new List + { + "None" + }; + + controller.PopulatePresetList(); + popupValues.AddRange(controller._presetNames); + + PopupField presetPopup = new PopupField() + { + bindingPath = "_selectedPreset", + choices = popupValues, + value = popupValues[0] + }; + + Button prevButton = new Button(delegate { presetPopup.index--; }) + { + text = "Prev", + }; + + Button nextButton = new Button(delegate { presetPopup.index++; }) + { + text = "Next" + }; + + prevButton.SetEnabled(presetPopup.index > 0); + nextButton.SetEnabled(presetPopup.index < presetPopup.choices.Count - 1); + + presetPopup.RegisterValueChangedCallback( + evt => + { + controller.LoadPreset(evt.newValue); + prevButton.SetEnabled(presetPopup.index > 0); + nextButton.SetEnabled(presetPopup.index < presetPopup.choices.Count - 1); + } + ); + + presetLayout.Add(prevButton); + presetLayout.Add(nextButton); + presetLayout.Add(presetPopup); + + presets.Add(presetLayout); + + Label savePresetLabel = new Label("Save Preset"); + presets.Add(savePresetLabel); + + VisualElement saveLayout = new VisualElement() + { + style = + { + flexDirection = new StyleEnum(FlexDirection.Row) + } + }; + + TextField saveNameField = new TextField() + { + style = + { + width = Length.Percent(85), + }, + bindingPath = "_saveName" + }; + + Button saveButton = new Button( + delegate + { + controller.SavePreset(); + } + ) + { + text = "Save", + style = + { + width = Length.Percent(12), + }, + }; + + saveLayout.Add(saveNameField); + saveLayout.Add(saveButton); + + presets.Add(saveLayout); + + root.Add(presets); + + #endregion + + Foldout controls = new Foldout() + { + text = "Controls", + style = + { + unityFontStyleAndWeight = new StyleEnum(FontStyle.Bold) + } + }; + + #region EYEBROWS + Foldout eyebrowFoldout = new Foldout + { + text = "EYEBROWS" + }; + + Label leftEyebrowLabel = new Label("LEFT"); + + Slider ebrlFrownRaise = new Slider + { + bindingPath = "_ebrlFrownBlendValue", + label = "Frown/Raise", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider ebrlInnerDownUp = new Slider + { + bindingPath = "_ebrlInnerBlendValue", + label = "Inner Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider ebrlOuterDownUp = new Slider + { + bindingPath = "_ebrlOuterBlendValue", + label = "Outer Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + eyebrowFoldout.Add(leftEyebrowLabel); + eyebrowFoldout.Add(ebrlFrownRaise); + eyebrowFoldout.Add(ebrlInnerDownUp); + eyebrowFoldout.Add(ebrlOuterDownUp); + + Label rightEyebrowLabel = new Label("RIGHT"); + + Slider ebrrFrownRaise = new Slider + { + bindingPath = "_ebrrFrownBlendValue", + label = "Frown/Raise", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider ebrrInnerDownUp = new Slider + { + bindingPath = "_ebrrInnerBlendValue", + label = "Inner Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider ebrrOuterDownUp = new Slider + { + bindingPath = "_ebrrOuterBlendValue", + label = "Outer Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + eyebrowFoldout.Add(rightEyebrowLabel); + eyebrowFoldout.Add(ebrrFrownRaise); + eyebrowFoldout.Add(ebrrInnerDownUp); + eyebrowFoldout.Add(ebrrOuterDownUp); + + controls.Add(eyebrowFoldout); + #endregion + + #region EYES + Foldout eyeFoldout = new Foldout + { + text = "EYES" + }; + + Label leftEyeLabel = new Label("LEFT"); + + Slider eyelLookUpDown = new Slider + { + bindingPath = "_eyelUpDownBlendValue", + label = "Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider eyelLookLeftRight = new Slider + { + bindingPath = "_eyelLeftRightBlendValue", + label = "Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider eyelBlink = new Slider + { + bindingPath = "_eyelBlinkBlendValue", + label = "Blink", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider eyelSquint = new Slider + { + bindingPath = "_eyelSquintBlendValue", + label = "Squint", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider eyelWide = new Slider + { + bindingPath = "_eyelWideBlendValue", + label = "Wide", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + eyeFoldout.Add(leftEyeLabel); + eyeFoldout.Add(eyelLookUpDown); + eyeFoldout.Add(eyelLookLeftRight); + eyeFoldout.Add(eyelBlink); + eyeFoldout.Add(eyelSquint); + eyeFoldout.Add(eyelWide); + + Label rightEyeLabel = new Label("RIGHT"); + + Slider eyerLookUpDown = new Slider + { + bindingPath = "_eyerUpDownBlendValue", + label = "Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider eyerLookLeftRight = new Slider + { + bindingPath = "_eyerLeftRightBlendValue", + label = "Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider eyerBlink = new Slider + { + bindingPath = "_eyerBlinkBlendValue", + label = "Blink", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider eyerSquint = new Slider + { + bindingPath = "_eyerSquintBlendValue", + label = "Squint", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider eyerWide = new Slider + { + bindingPath = "_eyerWideBlendValue", + label = "Wide", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + eyeFoldout.Add(rightEyeLabel); + eyeFoldout.Add(eyerLookUpDown); + eyeFoldout.Add(eyerLookLeftRight); + eyeFoldout.Add(eyerBlink); + eyeFoldout.Add(eyerSquint); + eyeFoldout.Add(eyerWide); + + controls.Add(eyeFoldout); + #endregion + + #region NOSE + Foldout noseFoldout = new Foldout + { + text = "NOSE" + }; + + Label sneerLeft = new Label("LEFT"); + + Slider noseSneerLeft = new Slider + { + bindingPath = "_noslSneerBlendValue", + label = "Sneer", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Label sneerRight = new Label("RIGHT"); + + Slider noseSneerRight = new Slider + { + bindingPath = "_nosrSneerBlendValue", + label = "Sneer", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + noseFoldout.Add(sneerLeft); + noseFoldout.Add(noseSneerLeft); + noseFoldout.Add(sneerRight); + noseFoldout.Add(noseSneerRight); + + controls.Add(noseFoldout); + #endregion + + #region CHEEKS + Foldout cheeksFoldout = new Foldout + { + text = "CHEEKS" + }; + + Label cheekLeft = new Label("LEFT"); + + Slider cheekHollowPuffLeft = new Slider + { + bindingPath = "_chklHollowPuffBlendValue", + label = "Hollow/Puff", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Label cheekRight = new Label("Right"); + + Slider cheekHollowPuffRight = new Slider + { + bindingPath = "_chkrHollowPuffBlendValue", + label = "Hollow/Puff", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + cheeksFoldout.Add(cheekLeft); + cheeksFoldout.Add(cheekHollowPuffLeft); + cheeksFoldout.Add(cheekRight); + cheeksFoldout.Add(cheekHollowPuffRight); + + controls.Add(cheeksFoldout); + #endregion + + #region JAW + Foldout jawFoldout = new Foldout + { + text = "JAW" + }; + + Slider jawCloseOpen = new Slider + { + bindingPath = "_jawOpenCloseBlendValue", + label = "Close/Open", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider jawLeftRight = new Slider + { + bindingPath = "_jawLeftRightBlendValue", + label = "Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider jawBackwardForward = new Slider + { + bindingPath = "_jawBackForwardBlendValue", + label = "Backward/Forward", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + jawFoldout.Add(jawCloseOpen); + jawFoldout.Add(jawLeftRight); + jawFoldout.Add(jawBackwardForward); + + controls.Add(jawFoldout); + #endregion + + #region MOUTH + Foldout mouthFoldout = new Foldout + { + text = "MOUTH" + }; + + Slider mouthLeftRight = new Slider + { + bindingPath = "_mthLeftRightBlendValue", + label = "Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider mouthFunnel = new Slider + { + bindingPath = "_mthFunnelBlendValue", + label = "Funnel", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthPucker = new Slider + { + bindingPath = "_mthPuckerBlendValue", + label = "Pucker", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthShrugUpper = new Slider + { + bindingPath = "_mthShrugUpperBlendValue", + label = "Shrug Upper", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthShrugLower = new Slider + { + bindingPath = "_mthShrugLowerBlendValue", + label = "Shrug Lower", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthRollUpper = new Slider + { + bindingPath = "_mthRollUpperBlendValue", + label = "Roll Upper", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthRollOutUpper = new Slider + { + bindingPath = "_mthRollOutUpperBlendValue", + label = "Roll Out Upper", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthRollLower = new Slider + { + bindingPath = "_mthRollLowerBlendValue", + label = "Roll Lower", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthRollOutLower = new Slider + { + bindingPath = "_mthRollOutLowerBlendValue", + label = "Roll Out Lower", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthClose = new Slider + { + bindingPath = "_mthCloseBlendValue", + label = "Close", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Label mouthLeft = new Label("LEFT"); + + Slider mouthFrownSmileLeft = new Slider + { + bindingPath = "_mthlFrownSmileBlendValue", + label = "Frown/Smile", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider mouthPressStretchLeft = new Slider + { + bindingPath = "_mthlPressStretchBlendValue", + label = "PressStretch", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider mouthUpperUpLeft = new Slider + { + bindingPath = "_mthlUpperUpBlendValue", + label = "Upper Up", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthLowerDownLeft = new Slider + { + bindingPath = "_mthlLowerDownBlendValue", + label = "Lower Down", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Label mouthRight = new Label("RIGHT"); + + Slider mouthFrownSmileRight = new Slider + { + bindingPath = "_mthrFrownSmileBlendValue", + label = "Frown/Smile", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider mouthPressStretchRight = new Slider + { + bindingPath = "_mthrPressStretchBlendValue", + label = "PressStretch", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider mouthUpperUpRight = new Slider + { + bindingPath = "_mthrUpperUpBlendValue", + label = "Upper Up", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + Slider mouthLowerDownRight = new Slider + { + bindingPath = "_mthrLowerDownBlendValue", + label = "Lower Down", + showInputField = true, + lowValue = 0, + highValue = 1 + }; + + mouthFoldout.Add(mouthLeftRight); + mouthFoldout.Add(mouthFunnel); + mouthFoldout.Add(mouthPucker); + mouthFoldout.Add(mouthShrugUpper); + mouthFoldout.Add(mouthShrugLower); + mouthFoldout.Add(mouthRollUpper); + mouthFoldout.Add(mouthRollOutUpper); + mouthFoldout.Add(mouthRollLower); + mouthFoldout.Add(mouthRollOutLower); + mouthFoldout.Add(mouthClose); + mouthFoldout.Add(mouthLeft); + mouthFoldout.Add(mouthFrownSmileLeft); + mouthFoldout.Add(mouthPressStretchLeft); + mouthFoldout.Add(mouthUpperUpLeft); + mouthFoldout.Add(mouthLowerDownLeft); + mouthFoldout.Add(mouthRight); + mouthFoldout.Add(mouthFrownSmileRight); + mouthFoldout.Add(mouthPressStretchRight); + mouthFoldout.Add(mouthUpperUpRight); + mouthFoldout.Add(mouthLowerDownRight); + + controls.Add(mouthFoldout); + #endregion + + #region TONGUE + Foldout tongueFoldout = new Foldout + { + text = "TONGUE" + }; + + Slider tongueDownUp = new Slider + { + bindingPath = "_tongDownUpBlendValue", + label = "Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueInOut = new Slider + { + bindingPath = "_tongInOutBlendValue", + label = "In/Out", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueLowerRaise = new Slider + { + bindingPath = "_tongLowerRaiseBlendValue", + label = "Lower/Raise", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueTwistLeftRight = new Slider + { + bindingPath = "_tongTwistLeftRightBlendValue", + label = "Twist Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueCurlDownUp = new Slider + { + bindingPath = "_tongCurlDownUpBlendValue", + label = "Curl Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueCurlLeftRight = new Slider + { + bindingPath = "_tongCurlLeftRightBlendValue", + label = "Curl Left/Right", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + Slider tongueCurlSideDownUp = new Slider + { + bindingPath = "_tongCurlSideDownUpBlendValue", + label = "Curl Side Down/Up", + showInputField = true, + lowValue = -1, + highValue = 1 + }; + + tongueFoldout.Add(tongueDownUp); + tongueFoldout.Add(tongueInOut); + tongueFoldout.Add(tongueLowerRaise); + tongueFoldout.Add(tongueTwistLeftRight); + tongueFoldout.Add(tongueCurlDownUp); + tongueFoldout.Add(tongueCurlLeftRight); + tongueFoldout.Add(tongueCurlSideDownUp); + + controls.Add(tongueFoldout); + #endregion + + root.Add(controls); + + return root; + } + } +} +#endif diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs.meta old mode 100644 new mode 100755 index ab9129bf..a33c49de --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs.meta +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Blendshapes/FacialController.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 37c1c136edf8d3744be383c6fac071a8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 37c1c136edf8d3744be383c6fac071a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs old mode 100644 new mode 100755 index 67657de7..5b3bf429 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs @@ -1,347 +1,347 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using SQLite; -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Synty.SidekickCharacters.Database.DTO -{ - [Table("sk_color_row")] - public class SidekickColorRow - { - private SidekickColorSet _colorSet; - private SidekickColorProperty _colorProperty; - private Color? _niceColor; - private Color? _niceMetallic; - private Color? _niceSmoothness; - private Color? _niceReflection; - private Color? _niceEmission; - private Color? _niceOpacity; - - [PrimaryKey, AutoIncrement, Column("id")] - public int ID { get; set; } - [Column("ptr_color_set")] - public int PtrColorSet { get; set; } - [Column("ptr_color_property")] - public int PtrColorProperty { get; set; } - [Column("color")] - public string MainColor { get; set; } - [Column("metallic")] - public string Metallic { get; set; } - [Column("smoothness")] - public string Smoothness { get; set; } - [Column("reflection")] - public string Reflection { get; set; } - [Column("emission")] - public string Emission { get; set; } - [Column("opacity")] - public string Opacity { get; set; } - - [Ignore] - public SidekickColorSet ColorSet - { - get => _colorSet; - set - { - _colorSet = value; - PtrColorSet = value.ID; - } - } - [Ignore] - public SidekickColorProperty ColorProperty - { - get => _colorProperty; - set - { - _colorProperty = value; - PtrColorProperty = value.ID; - } - } - [Ignore] - public Color NiceColor - { - get - { - _niceColor ??= ColorUtility.TryParseHtmlString("#" + MainColor, out Color color) ? color : Color.white; - return (Color) _niceColor; - } - set - { - _niceColor = value; - MainColor = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public Color NiceMetallic - { - get - { - _niceMetallic ??= ColorUtility.TryParseHtmlString("#" + Metallic, out Color color) ? color : Color.white; - return (Color) _niceMetallic; - } - set - { - _niceMetallic = value; - Metallic = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public Color NiceSmoothness - { - get - { - _niceSmoothness ??= ColorUtility.TryParseHtmlString("#" + Smoothness, out Color color) ? color : Color.white; - return (Color) _niceSmoothness; - } - set - { - _niceSmoothness = value; - Smoothness = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public Color NiceReflection - { - get - { - _niceReflection ??= ColorUtility.TryParseHtmlString("#" + Reflection, out Color color) ? color : Color.white; - return (Color) _niceReflection; - } - set - { - _niceReflection = value; - Reflection = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public Color NiceEmission - { - get - { - _niceEmission ??= ColorUtility.TryParseHtmlString("#" + Emission, out Color color) ? color : Color.white; - return (Color) _niceEmission; - } - set - { - _niceEmission = value; - Emission = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public Color NiceOpacity - { - get - { - _niceOpacity ??= ColorUtility.TryParseHtmlString("#" + Opacity, out Color color) ? color : Color.white; - return (Color) _niceOpacity; - } - set - { - _niceOpacity = value; - Opacity = ColorUtility.ToHtmlStringRGB(value); - } - } - [Ignore] - public bool IsLocked { get; set; } - [Ignore] - public Image ButtonImage { get; set; } - - /// - /// Gets a list of all the Color Rows in the database. - /// - /// The Database Manager to use. - /// A list of all Color Rows in the database. - public static List GetAll(DatabaseManager dbManager) - { - List rows = dbManager.GetCurrentDbConnection().Table().ToList(); - - foreach (SidekickColorRow row in rows) - { - Decorate(dbManager, row); - } - - return rows; - } - - /// - /// Gets a specific Color Row by its database ID. - /// - /// The Database Manager to use. - /// The id of the required Color Row. - /// The specific Color Row if it exists; otherwise null. - public static SidekickColorRow GetByID(DatabaseManager dbManager, int id) - { - SidekickColorRow row = dbManager.GetCurrentDbConnection().Find(id); - Decorate(dbManager, row); - return row; - } - - /// - /// Gets a list of all the Color Rows in the database that have the matching Property. - /// - /// The Database Manager to use. - /// The property to get all the color rows for. - /// A list of all color rows in the database for the given property. - public static List GetAllByProperty(DatabaseManager dbManager, SidekickColorProperty property) - { - List rows = dbManager.GetCurrentDbConnection().Table() - .Where(row => row.PtrColorProperty == property.ID) - .ToList(); - - foreach (SidekickColorRow row in rows) - { - row.ColorProperty = property; - Decorate(dbManager, row); - } - - return rows; - } - - /// - /// Gets a list of all the Color Rows in the database that have the matching Set and Property. - /// - /// The Database Manager to use. - /// The color set to get the color rows for. - /// The property to get all the color rows for. - /// A list of all color rows in the database for the given set and property. - public static List GetAllBySetAndProperty(DatabaseManager dbManager, SidekickColorSet set, SidekickColorProperty property) - { - List rows = dbManager.GetCurrentDbConnection().Table() - .Where(row => row.PtrColorSet == set.ID && row.PtrColorProperty == property.ID) - .ToList(); - - foreach (SidekickColorRow row in rows) - { - row.ColorSet = set; - row.ColorProperty = property; - Decorate(dbManager, row); - } - - return rows; - } - - /// - /// Gets a list of all the Color Rows in the database that have the matching Set. - /// - /// The Database Manager to use. - /// The color set to get the color rows for. - /// A list of all color rows in the database for the given set. - public static List GetAllBySet(DatabaseManager dbManager, SidekickColorSet set) - { - List rows = dbManager.GetCurrentDbConnection().Table() - .Where(row => row.PtrColorSet == set.ID) - .ToList(); - - foreach (SidekickColorRow row in rows) - { - row.ColorSet = set; - Decorate(dbManager, row); - } - - return rows; - } - - /// - /// Creates a SidekickColorRow from a SidekickColorPresetRow. - /// - /// The SidekickColorPresetRow to convert. - /// A SidekickColorRow created from a SidekickColorPresetRow. - public static SidekickColorRow CreateFromPresetColorRow(SidekickColorPresetRow row) - { - SidekickColorRow newRow = new SidekickColorRow() - { - MainColor = row.MainColor, - Emission = row.Emission, - Metallic = row.Metallic, - Opacity = row.Opacity, - Reflection = row.Reflection, - Smoothness = row.Smoothness, - ColorProperty = row.ColorProperty - }; - - return newRow; - } - - /// - /// Ensures that the given row has its nice DTO class properties set - /// - /// The Database Manager to use. - /// The color row to decorate - /// A color row with all DTO class properties set - private static void Decorate(DatabaseManager dbManager, SidekickColorRow row) - { - // don't need PtrColorProperty check as should always be >= 0; if it's not, we have bad data and want the error - row.ColorProperty ??= SidekickColorProperty.GetByID(dbManager, row.PtrColorProperty); - if (row.ColorSet == null && row.PtrColorSet >= 0) - { - row.ColorSet = SidekickColorSet.GetByID(dbManager, row.PtrColorSet); - } - } - - /// - /// Delete this color row from the database. - /// - /// The Database Manager to use. - public void Delete(DatabaseManager dbManager) - { - int deletedCount = dbManager.GetCurrentDbConnection().Delete(ID); - if (deletedCount == 0) - { - throw new Exception($"Could not delete color set with ID '{ID}'"); - } - } - - /// - /// Inserts, or updates the values in the database, depending on this object has been saved before or not. - /// - /// The Database Manager to use. - public void Save(DatabaseManager dbManager) - { - if (ID < 0) - { - SaveToDB(dbManager); - } - else - { - UpdateDB(dbManager); - } - } - - /// - /// Saves this Color Set to the database with the current values. - /// - /// The Database Manager to use. - private void SaveToDB(DatabaseManager dbManager) - { - SQLiteConnection connection = dbManager.GetCurrentDbConnection(); - int insertCount = connection.Insert(this); - if (insertCount == 0) - { - throw new Exception("Unable to save current color row"); - } - - // in theory this could return a different ID, but in practice it's highly unlikely - ID = (int) SQLite3.LastInsertRowid(connection.Handle); - } - - /// - /// Updates this Color Set in the database with the current values. - /// - /// The Database Manager to use. - private void UpdateDB(DatabaseManager dbManager) - { - int updatedCount = dbManager.GetCurrentDbConnection().Update(this); - if (updatedCount == 0) - { - throw new Exception($"Could not update color row with ID '{ID}'"); - } - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using SQLite; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Synty.SidekickCharacters.Database.DTO +{ + [Table("sk_color_row")] + public class SidekickColorRow + { + private SidekickColorSet _colorSet; + private SidekickColorProperty _colorProperty; + private Color? _niceColor; + private Color? _niceMetallic; + private Color? _niceSmoothness; + private Color? _niceReflection; + private Color? _niceEmission; + private Color? _niceOpacity; + + [PrimaryKey, AutoIncrement, Column("id")] + public int ID { get; set; } + [Column("ptr_color_set")] + public int PtrColorSet { get; set; } + [Column("ptr_color_property")] + public int PtrColorProperty { get; set; } + [Column("color")] + public string MainColor { get; set; } + [Column("metallic")] + public string Metallic { get; set; } + [Column("smoothness")] + public string Smoothness { get; set; } + [Column("reflection")] + public string Reflection { get; set; } + [Column("emission")] + public string Emission { get; set; } + [Column("opacity")] + public string Opacity { get; set; } + + [Ignore] + public SidekickColorSet ColorSet + { + get => _colorSet; + set + { + _colorSet = value; + PtrColorSet = value.ID; + } + } + [Ignore] + public SidekickColorProperty ColorProperty + { + get => _colorProperty; + set + { + _colorProperty = value; + PtrColorProperty = value.ID; + } + } + [Ignore] + public Color NiceColor + { + get + { + _niceColor ??= ColorUtility.TryParseHtmlString("#" + MainColor, out Color color) ? color : Color.white; + return (Color) _niceColor; + } + set + { + _niceColor = value; + MainColor = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public Color NiceMetallic + { + get + { + _niceMetallic ??= ColorUtility.TryParseHtmlString("#" + Metallic, out Color color) ? color : Color.white; + return (Color) _niceMetallic; + } + set + { + _niceMetallic = value; + Metallic = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public Color NiceSmoothness + { + get + { + _niceSmoothness ??= ColorUtility.TryParseHtmlString("#" + Smoothness, out Color color) ? color : Color.white; + return (Color) _niceSmoothness; + } + set + { + _niceSmoothness = value; + Smoothness = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public Color NiceReflection + { + get + { + _niceReflection ??= ColorUtility.TryParseHtmlString("#" + Reflection, out Color color) ? color : Color.white; + return (Color) _niceReflection; + } + set + { + _niceReflection = value; + Reflection = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public Color NiceEmission + { + get + { + _niceEmission ??= ColorUtility.TryParseHtmlString("#" + Emission, out Color color) ? color : Color.white; + return (Color) _niceEmission; + } + set + { + _niceEmission = value; + Emission = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public Color NiceOpacity + { + get + { + _niceOpacity ??= ColorUtility.TryParseHtmlString("#" + Opacity, out Color color) ? color : Color.white; + return (Color) _niceOpacity; + } + set + { + _niceOpacity = value; + Opacity = ColorUtility.ToHtmlStringRGB(value); + } + } + [Ignore] + public bool IsLocked { get; set; } + [Ignore] + public Image ButtonImage { get; set; } + + /// + /// Gets a list of all the Color Rows in the database. + /// + /// The Database Manager to use. + /// A list of all Color Rows in the database. + public static List GetAll(DatabaseManager dbManager) + { + List rows = dbManager.GetCurrentDbConnection().Table().ToList(); + + foreach (SidekickColorRow row in rows) + { + Decorate(dbManager, row); + } + + return rows; + } + + /// + /// Gets a specific Color Row by its database ID. + /// + /// The Database Manager to use. + /// The id of the required Color Row. + /// The specific Color Row if it exists; otherwise null. + public static SidekickColorRow GetByID(DatabaseManager dbManager, int id) + { + SidekickColorRow row = dbManager.GetCurrentDbConnection().Find(id); + Decorate(dbManager, row); + return row; + } + + /// + /// Gets a list of all the Color Rows in the database that have the matching Property. + /// + /// The Database Manager to use. + /// The property to get all the color rows for. + /// A list of all color rows in the database for the given property. + public static List GetAllByProperty(DatabaseManager dbManager, SidekickColorProperty property) + { + List rows = dbManager.GetCurrentDbConnection().Table() + .Where(row => row.PtrColorProperty == property.ID) + .ToList(); + + foreach (SidekickColorRow row in rows) + { + row.ColorProperty = property; + Decorate(dbManager, row); + } + + return rows; + } + + /// + /// Gets a list of all the Color Rows in the database that have the matching Set and Property. + /// + /// The Database Manager to use. + /// The color set to get the color rows for. + /// The property to get all the color rows for. + /// A list of all color rows in the database for the given set and property. + public static List GetAllBySetAndProperty(DatabaseManager dbManager, SidekickColorSet set, SidekickColorProperty property) + { + List rows = dbManager.GetCurrentDbConnection().Table() + .Where(row => row.PtrColorSet == set.ID && row.PtrColorProperty == property.ID) + .ToList(); + + foreach (SidekickColorRow row in rows) + { + row.ColorSet = set; + row.ColorProperty = property; + Decorate(dbManager, row); + } + + return rows; + } + + /// + /// Gets a list of all the Color Rows in the database that have the matching Set. + /// + /// The Database Manager to use. + /// The color set to get the color rows for. + /// A list of all color rows in the database for the given set. + public static List GetAllBySet(DatabaseManager dbManager, SidekickColorSet set) + { + List rows = dbManager.GetCurrentDbConnection().Table() + .Where(row => row.PtrColorSet == set.ID) + .ToList(); + + foreach (SidekickColorRow row in rows) + { + row.ColorSet = set; + Decorate(dbManager, row); + } + + return rows; + } + + /// + /// Creates a SidekickColorRow from a SidekickColorPresetRow. + /// + /// The SidekickColorPresetRow to convert. + /// A SidekickColorRow created from a SidekickColorPresetRow. + public static SidekickColorRow CreateFromPresetColorRow(SidekickColorPresetRow row) + { + SidekickColorRow newRow = new SidekickColorRow() + { + MainColor = row.MainColor, + Emission = row.Emission, + Metallic = row.Metallic, + Opacity = row.Opacity, + Reflection = row.Reflection, + Smoothness = row.Smoothness, + ColorProperty = row.ColorProperty + }; + + return newRow; + } + + /// + /// Ensures that the given row has its nice DTO class properties set + /// + /// The Database Manager to use. + /// The color row to decorate + /// A color row with all DTO class properties set + private static void Decorate(DatabaseManager dbManager, SidekickColorRow row) + { + // don't need PtrColorProperty check as should always be >= 0; if it's not, we have bad data and want the error + row.ColorProperty ??= SidekickColorProperty.GetByID(dbManager, row.PtrColorProperty); + if (row.ColorSet == null && row.PtrColorSet >= 0) + { + row.ColorSet = SidekickColorSet.GetByID(dbManager, row.PtrColorSet); + } + } + + /// + /// Delete this color row from the database. + /// + /// The Database Manager to use. + public void Delete(DatabaseManager dbManager) + { + int deletedCount = dbManager.GetCurrentDbConnection().Delete(ID); + if (deletedCount == 0) + { + throw new Exception($"Could not delete color set with ID '{ID}'"); + } + } + + /// + /// Inserts, or updates the values in the database, depending on this object has been saved before or not. + /// + /// The Database Manager to use. + public void Save(DatabaseManager dbManager) + { + if (ID < 0) + { + SaveToDB(dbManager); + } + else + { + UpdateDB(dbManager); + } + } + + /// + /// Saves this Color Set to the database with the current values. + /// + /// The Database Manager to use. + private void SaveToDB(DatabaseManager dbManager) + { + SQLiteConnection connection = dbManager.GetCurrentDbConnection(); + int insertCount = connection.Insert(this); + if (insertCount == 0) + { + throw new Exception("Unable to save current color row"); + } + + // in theory this could return a different ID, but in practice it's highly unlikely + ID = (int) SQLite3.LastInsertRowid(connection.Handle); + } + + /// + /// Updates this Color Set in the database with the current values. + /// + /// The Database Manager to use. + private void UpdateDB(DatabaseManager dbManager) + { + int updatedCount = dbManager.GetCurrentDbConnection().Update(this); + if (updatedCount == 0) + { + throw new Exception($"Could not update color row with ID '{ID}'"); + } + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorRow.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs old mode 100644 new mode 100755 index 02461545..696956ae --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs @@ -154,18 +154,6 @@ namespace Synty.SidekickCharacters.Database.DTO /// A color set with all DTO class properties set private static void Decorate(DatabaseManager dbManager, SidekickColorSet set) { - if (set == null) - { - return; - } - - set.SourceColorPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceColorPath); - set.SourceMetallicPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceMetallicPath); - set.SourceSmoothnessPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceSmoothnessPath); - set.SourceReflectionPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceReflectionPath); - set.SourceEmissionPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceEmissionPath); - set.SourceOpacityPath = DatabaseManager.NormalizeLegacyAssetPath(set.SourceOpacityPath); - if (set.Species == null && set.PtrSpecies >= 0) { set.Species = SidekickSpecies.GetByID(dbManager, set.PtrSpecies); diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickColorSet.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs old mode 100644 new mode 100755 index d0ad6246..fd2fdf2b --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs @@ -222,8 +222,6 @@ namespace Synty.SidekickCharacters.Database.DTO { if (part != null) { - part.Location = DatabaseManager.NormalizeLegacyAssetPath(part.Location); - if (part.Species == null && part.PtrSpecies >= 0) { part.Species = SidekickSpecies.GetByID(dbManager, part.PtrSpecies); diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPart.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs old mode 100644 new mode 100755 index 643d5c19..028351b4 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs @@ -1,285 +1,285 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using SQLite; -using Synty.SidekickCharacters.Enums; -using Synty.SidekickCharacters.Utils; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Synty.SidekickCharacters.Database.DTO -{ - [Table("sk_part_preset")] - public class SidekickPartPreset - { - private SidekickSpecies _species; - - [PrimaryKey] - [AutoIncrement] - [Column("id")] - public int ID { get; set; } - [Column("name")] - public string Name { get; set; } - [Column("part_group")] - public PartGroup PartGroup { get; set; } - [Column("ptr_species")] - public int PtrSpecies { get; set; } - [Column("outfit")] - public string Outfit { get; set; } - - [Ignore] - public SidekickSpecies Species - { - get => _species; - set - { - _species = value; - PtrSpecies = value.ID; - } - } - - /// - /// Gets a specific Preset by its database ID. - /// - /// The Database Manager to use. - /// The id of the required Preset. - /// The specific Preset if it exists; otherwise null. - public static SidekickPartPreset GetByID(DatabaseManager dbManager, int id) - { - SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection().Find(id); - Decorate(dbManager, partPreset); - return partPreset; - } - - /// - /// Gets a list of all the Presets in the database. - /// - /// The Database Manager to use. - /// A list of all presets in the database. - public static List GetAll(DatabaseManager dbManager) - { - List partPresets = dbManager.GetCurrentDbConnection().Table().ToList(); - - foreach (SidekickPartPreset partPreset in partPresets) - { - Decorate(dbManager, partPreset); - } - - return partPresets; - } - - /// - /// Gets a list of all the Part Presets in the database that have the matching species. - /// - /// The Database Manager to use. - /// The species to get all the part presets for. - /// A list of all part presets in the database for the given species. - public static List GetAllBySpecies(DatabaseManager dbManager, SidekickSpecies species) - { - List partPresets = dbManager.GetCurrentDbConnection().Table() - .Where(partPreset => partPreset.PtrSpecies == species.ID) - .ToList(); - - foreach (SidekickPartPreset partPreset in partPresets) - { - partPreset.Species = species; - } - - return partPresets; - } - - /// - /// Gets a Part Presets in the database with the matching name if one exists. - /// - /// The Database Manager to use. - /// The name of the preset to retrieve. - /// Returns a Part Presets in the database with the matching name if one exists; otherwise null. - public static SidekickPartPreset GetByName(DatabaseManager dbManager, string name) - { - SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection() - .Table() - .FirstOrDefault(partPreset => partPreset.Name == name); - - if (partPreset != null) - { - Decorate(dbManager, partPreset); - } - - return partPreset; - } - - /// - /// Gets a list of all the Part Presets in the database that have the matching species and part group. - /// - /// The Database Manager to use. - /// The part group to filter search by. - /// A list of all part presets in the database for the given species and part group. - public static List GetAllByGroup(DatabaseManager dbManager, PartGroup partGroup, bool excludeMissingParts = true) - { - List partPresets = dbManager.GetCurrentDbConnection().Table() - .Where(partPreset => partPreset.PartGroup == partGroup) - .ToList(); - - foreach (SidekickPartPreset partPreset in partPresets) - { - Decorate(dbManager, partPreset); - } - - if (excludeMissingParts) - { - List toRemove = new List(); - foreach (SidekickPartPreset partPreset in partPresets) - { - if (!partPreset.HasAllPartsAvailable(dbManager)) - { - toRemove.Add(partPreset); - } - } - - partPresets.RemoveAll(preset => toRemove.Contains(preset)); - } - - return partPresets; - } - - /// - /// Gets a list of all the Part Presets in the database that have the matching species and part group. - /// - /// The Database Manager to use. - /// The species to get all the part presets for. - /// The part group to filter search by. - /// A list of all part presets in the database for the given species and part group. - public static List GetAllBySpeciesAndGroup(DatabaseManager dbManager, SidekickSpecies species, PartGroup partGroup) - { - List partPresets = dbManager.GetCurrentDbConnection().Table() - .Where(partPreset => partPreset.PtrSpecies == species.ID && partPreset.PartGroup == partGroup) - .ToList(); - - foreach (SidekickPartPreset partPreset in partPresets) - { - partPreset.Species = species; - } - - return partPresets; - } - - /// - /// Ensures that the given set has its nice DTO class properties set - /// - /// The Database Manager to use. - /// The color set to decorate - /// A color set with all DTO class properties set - private static void Decorate(DatabaseManager dbManager, SidekickPartPreset partPreset) - { - if (partPreset.Species == null && partPreset.PtrSpecies >= 0) - { - partPreset.Species = SidekickSpecies.GetByID(dbManager, partPreset.PtrSpecies); - } - } - - /// - /// Updates or Inserts this item in the Database. - /// - /// The database manager to use. - public int Save(DatabaseManager dbManager) - { - if (ID < 0) - { - dbManager.GetCurrentDbConnection().Insert(this); - // in theory this could return a different ID, but in practice it's highly unlikely - ID = (int) SQLite3.LastInsertRowid(dbManager.GetCurrentDbConnection().Handle); - } - dbManager.GetCurrentDbConnection().Update(this); - return ID; - } - - /// - /// Deletes this item from the database - /// - /// The database manager to use. - public void Delete(DatabaseManager dbManager) - { - foreach (SidekickPartPresetRow row in SidekickPartPresetRow.GetAllByPreset(dbManager, this)) - { - row.Delete(dbManager); - } - - foreach (SidekickPresetFilterRow row in SidekickPresetFilterRow.GetAllForPreset(dbManager, this)) - { - row.Delete(dbManager); - } - - SidekickPartPresetImage image = SidekickPartPresetImage.GetByPresetAndPartGroup(dbManager, this, PartGroup); - image?.Delete(dbManager); - - dbManager.GetCurrentDbConnection().Delete(ID); - } - - /// - /// Determines if all the parts associated with this preset are valid (has a file in the project). - /// - /// The database manager to use. - /// True if all parts are valid; otherwise False. - public bool HasAllPartsAvailable(DatabaseManager dbManager) - { - List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this); - return allRows.Count > 0 && allRows.All(row => row.HasValidPart()); - } - - /// - /// Determines if all the parts associated with this preset are valid (has a file in the project). - /// - /// The database manager to use. - /// True if all parts are valid; otherwise False. - public bool HasOnlyBasePartsAndAllAvailable(DatabaseManager dbManager) - { - List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this); - return allRows.Count > 0 && allRows.All(row => row.HasValidPart() && (row.Part == null || PartUtils.IsBaseSpeciesPart(row.PartName))); - } - - /// - /// Checks the equality of this preset to the given preset. - /// - /// The preset to check equality with. - /// True if the presets are equal, otherwise false. - protected bool Equals(SidekickPartPreset other) - { - return ID == other.ID - && Name == other.Name - && PartGroup == other.PartGroup - && PtrSpecies == other.PtrSpecies; - } - - /// - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj.GetType() != this.GetType()) - { - return false; - } - - return Equals((SidekickPartPreset) obj); - } - - /// - public override int GetHashCode() - { - return HashCode.Combine(ID, Name, (int) PartGroup, PtrSpecies); - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using SQLite; +using Synty.SidekickCharacters.Enums; +using Synty.SidekickCharacters.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Synty.SidekickCharacters.Database.DTO +{ + [Table("sk_part_preset")] + public class SidekickPartPreset + { + private SidekickSpecies _species; + + [PrimaryKey] + [AutoIncrement] + [Column("id")] + public int ID { get; set; } + [Column("name")] + public string Name { get; set; } + [Column("part_group")] + public PartGroup PartGroup { get; set; } + [Column("ptr_species")] + public int PtrSpecies { get; set; } + [Column("outfit")] + public string Outfit { get; set; } + + [Ignore] + public SidekickSpecies Species + { + get => _species; + set + { + _species = value; + PtrSpecies = value.ID; + } + } + + /// + /// Gets a specific Preset by its database ID. + /// + /// The Database Manager to use. + /// The id of the required Preset. + /// The specific Preset if it exists; otherwise null. + public static SidekickPartPreset GetByID(DatabaseManager dbManager, int id) + { + SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection().Find(id); + Decorate(dbManager, partPreset); + return partPreset; + } + + /// + /// Gets a list of all the Presets in the database. + /// + /// The Database Manager to use. + /// A list of all presets in the database. + public static List GetAll(DatabaseManager dbManager) + { + List partPresets = dbManager.GetCurrentDbConnection().Table().ToList(); + + foreach (SidekickPartPreset partPreset in partPresets) + { + Decorate(dbManager, partPreset); + } + + return partPresets; + } + + /// + /// Gets a list of all the Part Presets in the database that have the matching species. + /// + /// The Database Manager to use. + /// The species to get all the part presets for. + /// A list of all part presets in the database for the given species. + public static List GetAllBySpecies(DatabaseManager dbManager, SidekickSpecies species) + { + List partPresets = dbManager.GetCurrentDbConnection().Table() + .Where(partPreset => partPreset.PtrSpecies == species.ID) + .ToList(); + + foreach (SidekickPartPreset partPreset in partPresets) + { + partPreset.Species = species; + } + + return partPresets; + } + + /// + /// Gets a Part Presets in the database with the matching name if one exists. + /// + /// The Database Manager to use. + /// The name of the preset to retrieve. + /// Returns a Part Presets in the database with the matching name if one exists; otherwise null. + public static SidekickPartPreset GetByName(DatabaseManager dbManager, string name) + { + SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection() + .Table() + .FirstOrDefault(partPreset => partPreset.Name == name); + + if (partPreset != null) + { + Decorate(dbManager, partPreset); + } + + return partPreset; + } + + /// + /// Gets a list of all the Part Presets in the database that have the matching species and part group. + /// + /// The Database Manager to use. + /// The part group to filter search by. + /// A list of all part presets in the database for the given species and part group. + public static List GetAllByGroup(DatabaseManager dbManager, PartGroup partGroup, bool excludeMissingParts = true) + { + List partPresets = dbManager.GetCurrentDbConnection().Table() + .Where(partPreset => partPreset.PartGroup == partGroup) + .ToList(); + + foreach (SidekickPartPreset partPreset in partPresets) + { + Decorate(dbManager, partPreset); + } + + if (excludeMissingParts) + { + List toRemove = new List(); + foreach (SidekickPartPreset partPreset in partPresets) + { + if (!partPreset.HasAllPartsAvailable(dbManager)) + { + toRemove.Add(partPreset); + } + } + + partPresets.RemoveAll(preset => toRemove.Contains(preset)); + } + + return partPresets; + } + + /// + /// Gets a list of all the Part Presets in the database that have the matching species and part group. + /// + /// The Database Manager to use. + /// The species to get all the part presets for. + /// The part group to filter search by. + /// A list of all part presets in the database for the given species and part group. + public static List GetAllBySpeciesAndGroup(DatabaseManager dbManager, SidekickSpecies species, PartGroup partGroup) + { + List partPresets = dbManager.GetCurrentDbConnection().Table() + .Where(partPreset => partPreset.PtrSpecies == species.ID && partPreset.PartGroup == partGroup) + .ToList(); + + foreach (SidekickPartPreset partPreset in partPresets) + { + partPreset.Species = species; + } + + return partPresets; + } + + /// + /// Ensures that the given set has its nice DTO class properties set + /// + /// The Database Manager to use. + /// The color set to decorate + /// A color set with all DTO class properties set + private static void Decorate(DatabaseManager dbManager, SidekickPartPreset partPreset) + { + if (partPreset.Species == null && partPreset.PtrSpecies >= 0) + { + partPreset.Species = SidekickSpecies.GetByID(dbManager, partPreset.PtrSpecies); + } + } + + /// + /// Updates or Inserts this item in the Database. + /// + /// The database manager to use. + public int Save(DatabaseManager dbManager) + { + if (ID < 0) + { + dbManager.GetCurrentDbConnection().Insert(this); + // in theory this could return a different ID, but in practice it's highly unlikely + ID = (int) SQLite3.LastInsertRowid(dbManager.GetCurrentDbConnection().Handle); + } + dbManager.GetCurrentDbConnection().Update(this); + return ID; + } + + /// + /// Deletes this item from the database + /// + /// The database manager to use. + public void Delete(DatabaseManager dbManager) + { + foreach (SidekickPartPresetRow row in SidekickPartPresetRow.GetAllByPreset(dbManager, this)) + { + row.Delete(dbManager); + } + + foreach (SidekickPresetFilterRow row in SidekickPresetFilterRow.GetAllForPreset(dbManager, this)) + { + row.Delete(dbManager); + } + + SidekickPartPresetImage image = SidekickPartPresetImage.GetByPresetAndPartGroup(dbManager, this, PartGroup); + image?.Delete(dbManager); + + dbManager.GetCurrentDbConnection().Delete(ID); + } + + /// + /// Determines if all the parts associated with this preset are valid (has a file in the project). + /// + /// The database manager to use. + /// True if all parts are valid; otherwise False. + public bool HasAllPartsAvailable(DatabaseManager dbManager) + { + List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this); + return allRows.Count > 0 && allRows.All(row => row.HasValidPart()); + } + + /// + /// Determines if all the parts associated with this preset are valid (has a file in the project). + /// + /// The database manager to use. + /// True if all parts are valid; otherwise False. + public bool HasOnlyBasePartsAndAllAvailable(DatabaseManager dbManager) + { + List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this); + return allRows.Count > 0 && allRows.All(row => row.HasValidPart() && (row.Part == null || PartUtils.IsBaseSpeciesPart(row.PartName))); + } + + /// + /// Checks the equality of this preset to the given preset. + /// + /// The preset to check equality with. + /// True if the presets are equal, otherwise false. + protected bool Equals(SidekickPartPreset other) + { + return ID == other.ID + && Name == other.Name + && PartGroup == other.PartGroup + && PtrSpecies == other.PtrSpecies; + } + + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((SidekickPartPreset) obj); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(ID, Name, (int) PartGroup, PtrSpecies); + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DTO/SidekickPartPreset.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs old mode 100644 new mode 100755 index 36ae79e6..4f2d0aeb --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs @@ -12,9 +12,7 @@ using SQLite; using Synty.SidekickCharacters.Database.DTO; using System; -using System.IO; using System.Linq; -using UnityEngine; namespace Synty.SidekickCharacters.Database { @@ -23,18 +21,11 @@ namespace Synty.SidekickCharacters.Database /// public class DatabaseManager { - private const string _DATABASE_FILE_NAME = "Side_Kick_Data.db"; - private const string _LEGACY_PACKAGE_ROOT = "Assets/Synty/SidekickCharacters"; - private const string _LEGACY_TOOLS_PACKAGE_ROOT = "Assets/Synty/Tools/SidekickCharacters"; - private const string _WORKING_DATABASE_DIRECTORY = "SidekickCharacters"; + private static readonly string _DATABASE_PATH = "Assets/External/Models/SidekickCharacters/Database/Side_Kick_Data.db"; private readonly string _CURRENT_VERSION = "1.0.2"; private static SQLiteConnection _connection; private static int _connectionHash; - private static string _databasePath; - private static string _seedDatabasePath; - private static string _packageRootAbsolutePath; - private static string _packageRootAssetPath; /// /// Gets the DB connection with the given connection details. @@ -48,13 +39,7 @@ namespace Synty.SidekickCharacters.Database { if (_connection == null) { - string databasePath = GetDatabasePath(); - if (string.IsNullOrEmpty(databasePath)) - { - throw new FileNotFoundException("Unable to locate Sidekick database file in this Unity project."); - } - - _connection = new SQLiteConnection(databasePath, true); + _connection = new SQLiteConnection(_DATABASE_PATH, true); } else { @@ -115,12 +100,12 @@ namespace Synty.SidekickCharacters.Database { Species = new SidekickSpecies { ID = -1, Name = "None" }, Name = "Default", - SourceColorPath = GetPackageAssetPath("Resources", "Textures", "T_ColorMap.png"), - SourceMetallicPath = GetPackageAssetPath("Resources", "Textures", "T_MetallicMap.png"), - SourceSmoothnessPath = GetPackageAssetPath("Resources", "Textures", "T_SmoothnessMap.png"), - SourceReflectionPath = GetPackageAssetPath("Resources", "Textures", "T_ReflectionMap.png"), - SourceEmissionPath = GetPackageAssetPath("Resources", "Textures", "T_EmissionMap.png"), - SourceOpacityPath = GetPackageAssetPath("Resources", "Textures", "T_OpacityMap.png"), + SourceColorPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_ColorMap.png", + SourceMetallicPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_MetallicMap.png", + SourceSmoothnessPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_SmoothnessMap.png", + SourceReflectionPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_ReflectionMap.png", + SourceEmissionPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_EmissionMap.png", + SourceOpacityPath = "Assets/External/Models/SidekickCharacters/Resources/Textures/T_OpacityMap.png", }; newSet.Save(this); @@ -221,216 +206,5 @@ namespace Synty.SidekickCharacters.Database { return new Version(GetCurrentDbConnection()?.Table().FirstOrDefault().SemanticVersion ?? "0.0.1ea"); } - - /// - /// Gets the absolute filesystem path to the Sidekick database file. - /// - /// The absolute path to the DB file, if found. - public static string GetDatabasePath() - { - if (!string.IsNullOrEmpty(_databasePath) && File.Exists(_databasePath)) - { - return _databasePath; - } - - string seedDatabasePath = GetSeedDatabasePath(); - if (string.IsNullOrEmpty(seedDatabasePath)) - { - return null; - } - - string projectRoot = Directory.GetParent(Application.dataPath)?.FullName; - if (string.IsNullOrEmpty(projectRoot)) - { - return null; - } - - string workingDirectory = Path.Combine(projectRoot, "Library", _WORKING_DATABASE_DIRECTORY); - Directory.CreateDirectory(workingDirectory); - - _databasePath = Path.Combine(workingDirectory, _DATABASE_FILE_NAME); - if (!File.Exists(_databasePath)) - { - File.Copy(seedDatabasePath, _databasePath, false); - } - - _databasePath = Path.GetFullPath(_databasePath); - CleanupLegacyDatabaseArtifacts(seedDatabasePath); - return _databasePath; - } - - /// - /// Gets the absolute filesystem path to the Sidekick package root. - /// - /// The absolute path to the package root, if found. - public static string GetPackageRootAbsolutePath() - { - if (!string.IsNullOrEmpty(_packageRootAbsolutePath) && Directory.Exists(_packageRootAbsolutePath)) - { - return _packageRootAbsolutePath; - } - - string seedDatabasePath = GetSeedDatabasePath(); - if (string.IsNullOrEmpty(seedDatabasePath)) - { - return null; - } - - string databaseDirectory = Path.GetDirectoryName(seedDatabasePath); - if (string.IsNullOrEmpty(databaseDirectory)) - { - return null; - } - - _packageRootAbsolutePath = Path.GetDirectoryName(databaseDirectory); - if (!string.IsNullOrEmpty(_packageRootAbsolutePath)) - { - _packageRootAbsolutePath = Path.GetFullPath(_packageRootAbsolutePath); - } - - return _packageRootAbsolutePath; - } - - /// - /// Gets the project-relative asset path to the Sidekick package root. - /// - /// The asset path to the package root, if found. - public static string GetPackageRootAssetPath() - { - if (!string.IsNullOrEmpty(_packageRootAssetPath)) - { - return _packageRootAssetPath; - } - - string packageRootAbsolutePath = GetPackageRootAbsolutePath(); - if (string.IsNullOrEmpty(packageRootAbsolutePath)) - { - return null; - } - - _packageRootAssetPath = ToAssetPath(packageRootAbsolutePath); - return _packageRootAssetPath; - } - - /// - /// Builds a project-relative asset path under the Sidekick package root. - /// - /// Path segments under the package root. - /// The combined asset path, if the package root could be found. - public static string GetPackageAssetPath(params string[] relativeSegments) - { - string packageRootAssetPath = GetPackageRootAssetPath(); - if (string.IsNullOrEmpty(packageRootAssetPath)) - { - return null; - } - - string combinedPath = packageRootAssetPath; - foreach (string segment in relativeSegments) - { - combinedPath = Path.Combine(combinedPath, segment); - } - - return NormalizePathSeparators(combinedPath); - } - - /// - /// Normalizes legacy Sidekick asset paths so moved packages still load correctly. - /// - /// The asset path to normalize. - /// The remapped path if it pointed at an old root; otherwise the original path. - public static string NormalizeLegacyAssetPath(string assetPath) - { - if (string.IsNullOrWhiteSpace(assetPath)) - { - return assetPath; - } - - string normalizedPath = NormalizePathSeparators(assetPath); - string packageRootAssetPath = GetPackageRootAssetPath(); - if (string.IsNullOrEmpty(packageRootAssetPath)) - { - return normalizedPath; - } - - if (normalizedPath.StartsWith(_LEGACY_TOOLS_PACKAGE_ROOT, StringComparison.OrdinalIgnoreCase)) - { - return packageRootAssetPath + normalizedPath.Substring(_LEGACY_TOOLS_PACKAGE_ROOT.Length); - } - - if (normalizedPath.StartsWith(_LEGACY_PACKAGE_ROOT, StringComparison.OrdinalIgnoreCase)) - { - return packageRootAssetPath + normalizedPath.Substring(_LEGACY_PACKAGE_ROOT.Length); - } - - return normalizedPath; - } - - private static string ToAssetPath(string fullPath) - { - string normalizedFullPath = NormalizePathSeparators(Path.GetFullPath(fullPath)); - string normalizedAssetsPath = NormalizePathSeparators(Path.GetFullPath(Application.dataPath)); - - if (!normalizedFullPath.StartsWith(normalizedAssetsPath, StringComparison.OrdinalIgnoreCase)) - { - return normalizedFullPath; - } - - return "Assets" + normalizedFullPath.Substring(normalizedAssetsPath.Length); - } - - private static string NormalizePathSeparators(string path) - { - return path?.Replace('\\', '/'); - } - - private static string GetSeedDatabasePath() - { - if (!string.IsNullOrEmpty(_seedDatabasePath) && File.Exists(_seedDatabasePath)) - { - return _seedDatabasePath; - } - - string[] databaseFiles = Directory.GetFiles(Application.dataPath, _DATABASE_FILE_NAME, SearchOption.AllDirectories); - _seedDatabasePath = databaseFiles - .OrderBy(path => path.Contains($"{Path.DirectorySeparatorChar}SidekickCharacters{Path.DirectorySeparatorChar}Database{Path.DirectorySeparatorChar}") ? 0 : 1) - .FirstOrDefault(); - - if (!string.IsNullOrEmpty(_seedDatabasePath)) - { - _seedDatabasePath = Path.GetFullPath(_seedDatabasePath); - } - - return _seedDatabasePath; - } - - private static void CleanupLegacyDatabaseArtifacts(string seedDatabasePath) - { - if (string.IsNullOrEmpty(seedDatabasePath)) - { - return; - } - - DeleteIfExists(seedDatabasePath + "-journal"); - DeleteIfExists(seedDatabasePath + "-journal.meta"); - DeleteIfExists(seedDatabasePath + "-wal"); - DeleteIfExists(seedDatabasePath + "-wal.meta"); - DeleteIfExists(seedDatabasePath + "-shm"); - DeleteIfExists(seedDatabasePath + "-shm.meta"); - } - - private static void DeleteIfExists(string path) - { - try - { - if (File.Exists(path)) - { - File.Delete(path); - } - } - catch - { - } - } } } diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Database/DatabaseManager.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs old mode 100644 new mode 100755 index 7596dc1e..3121fa21 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs @@ -1,204 +1,204 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.EventSystems; - -namespace Synty.SidekickCharacters.Filters -{ - public class FilterGroup - { - public SidekickRuntime Runtime; - public FilterCombineType CombineType; - - private Dictionary> _filteredParts; - private List _filterItems = new List(); - private List _subGroups = new List(); - - /// - /// Adds a sub group of filters to this group. - /// - /// The group to add as a sub group. - public void AddFilterSubGroup(FilterGroup subGroup) - { - if (_subGroups.Count < 1 || _subGroups[0].CombineType == subGroup.CombineType) - { - _subGroups.Add(subGroup); - } - else - { - Debug.LogWarning("Unable to add sub group as sub groups cannot have different combine types."); - } - } - - /// - /// Adds a filter item to this group. - /// - /// The filter item to add. - public void AddFilterItem(FilterItem filterItem) - { - if (_filterItems.Count < 1 || _filterItems[0].CombineType == filterItem.CombineType) - { - _filterItems.Add(filterItem); - } - else - { - Debug.LogWarning("Unable to add filter as filters cannot have different combine types."); - } - } - - /// - /// Removes the given filter item from this group, if it exists. - /// - /// The filter item to remove. - public void RemoveFilterItem(FilterItem filterItem) - { - _filterItems.RemoveAll(fi => fi.Filter == filterItem.Filter); - } - - /// - /// Resets the part dictionaries for all filter items. - /// - public void ResetFiltersForSpeciesChange() - { - foreach (FilterItem item in _filterItems) - { - item.ResetPartsForSpeciesChange(); - } - } - - /// - /// Gets a list of all parts that the filters within this group evaluate to. - /// - /// The list of all filtered parts - public Dictionary> GetFilteredParts() - { - _filteredParts = new Dictionary>(); - - // If there are no filter items, it means that we aren't filtering any parts out. Return all parts. - if (_filterItems.Count < 1) - { - return Runtime.MappedBasePartDictionary[Runtime.CurrentSpecies]; - } - - if (_filterItems.Count > 1) - { - FilterCombineType filterCombineType = _filterItems[1].CombineType; - if (_filterItems[0].CombineType != FilterCombineType.Or) - { - _filteredParts = Runtime.MappedPartList; - } - - - foreach (FilterItem item in _filterItems) - { - Dictionary> newFilteredParts = item.GetFilteredParts(); - List toRemove = new List(); - - foreach (KeyValuePair> entry in newFilteredParts) - { - switch (filterCombineType) - { - case FilterCombineType.And: - toRemove = new List(); - - foreach (string part in _filteredParts[entry.Key]) - { - if (!entry.Value.Contains(part)) - { - toRemove.Add(part); - } - } - - _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); - break; - case FilterCombineType.Or: - HashSet uniqueList = entry.Value.ToHashSet(); - HashSet existingList = _filteredParts.TryGetValue(entry.Key, out List filteredList) ? filteredList.ToHashSet() : new HashSet(); - existingList.UnionWith(uniqueList); - _filteredParts[entry.Key] = existingList.ToList(); - - break; - case FilterCombineType.Not: - toRemove = new List(); - - foreach (string part in _filteredParts[entry.Key]) - { - if (entry.Value.Contains(part)) - { - toRemove.Add(part); - } - } - - _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); - break; - } - } - } - } - else - { - _filteredParts = _filterItems[0].GetFilteredParts(); - } - - foreach (FilterGroup group in _subGroups) - { - FilterCombineType filterCombineType = group.CombineType; - Dictionary> newFilteredParts = group.GetFilteredParts(); - List toRemove = new List(); - - foreach (KeyValuePair> entry in newFilteredParts) - { - switch (filterCombineType) - { - case FilterCombineType.And: - toRemove = new List(); - - foreach (string part in _filteredParts[entry.Key]) - { - if (!entry.Value.Contains(part)) - { - toRemove.Add(part); - } - } - - _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); - break; - case FilterCombineType.Or: - HashSet uniqueList = entry.Value.ToHashSet(); - HashSet existingList = _filteredParts[entry.Key].ToHashSet(); - existingList.UnionWith(uniqueList); - _filteredParts[entry.Key] = existingList.ToList(); - - break; - case FilterCombineType.Not: - toRemove = new List(); - - foreach (string part in _filteredParts[entry.Key]) - { - if (entry.Value.Contains(part)) - { - toRemove.Add(part); - } - } - - _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); - break; - } - } - } - - return _filteredParts; - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.EventSystems; + +namespace Synty.SidekickCharacters.Filters +{ + public class FilterGroup + { + public SidekickRuntime Runtime; + public FilterCombineType CombineType; + + private Dictionary> _filteredParts; + private List _filterItems = new List(); + private List _subGroups = new List(); + + /// + /// Adds a sub group of filters to this group. + /// + /// The group to add as a sub group. + public void AddFilterSubGroup(FilterGroup subGroup) + { + if (_subGroups.Count < 1 || _subGroups[0].CombineType == subGroup.CombineType) + { + _subGroups.Add(subGroup); + } + else + { + Debug.LogWarning("Unable to add sub group as sub groups cannot have different combine types."); + } + } + + /// + /// Adds a filter item to this group. + /// + /// The filter item to add. + public void AddFilterItem(FilterItem filterItem) + { + if (_filterItems.Count < 1 || _filterItems[0].CombineType == filterItem.CombineType) + { + _filterItems.Add(filterItem); + } + else + { + Debug.LogWarning("Unable to add filter as filters cannot have different combine types."); + } + } + + /// + /// Removes the given filter item from this group, if it exists. + /// + /// The filter item to remove. + public void RemoveFilterItem(FilterItem filterItem) + { + _filterItems.RemoveAll(fi => fi.Filter == filterItem.Filter); + } + + /// + /// Resets the part dictionaries for all filter items. + /// + public void ResetFiltersForSpeciesChange() + { + foreach (FilterItem item in _filterItems) + { + item.ResetPartsForSpeciesChange(); + } + } + + /// + /// Gets a list of all parts that the filters within this group evaluate to. + /// + /// The list of all filtered parts + public Dictionary> GetFilteredParts() + { + _filteredParts = new Dictionary>(); + + // If there are no filter items, it means that we aren't filtering any parts out. Return all parts. + if (_filterItems.Count < 1) + { + return Runtime.MappedBasePartDictionary[Runtime.CurrentSpecies]; + } + + if (_filterItems.Count > 1) + { + FilterCombineType filterCombineType = _filterItems[1].CombineType; + if (_filterItems[0].CombineType != FilterCombineType.Or) + { + _filteredParts = Runtime.MappedPartList; + } + + + foreach (FilterItem item in _filterItems) + { + Dictionary> newFilteredParts = item.GetFilteredParts(); + List toRemove = new List(); + + foreach (KeyValuePair> entry in newFilteredParts) + { + switch (filterCombineType) + { + case FilterCombineType.And: + toRemove = new List(); + + foreach (string part in _filteredParts[entry.Key]) + { + if (!entry.Value.Contains(part)) + { + toRemove.Add(part); + } + } + + _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); + break; + case FilterCombineType.Or: + HashSet uniqueList = entry.Value.ToHashSet(); + HashSet existingList = _filteredParts.TryGetValue(entry.Key, out List filteredList) ? filteredList.ToHashSet() : new HashSet(); + existingList.UnionWith(uniqueList); + _filteredParts[entry.Key] = existingList.ToList(); + + break; + case FilterCombineType.Not: + toRemove = new List(); + + foreach (string part in _filteredParts[entry.Key]) + { + if (entry.Value.Contains(part)) + { + toRemove.Add(part); + } + } + + _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); + break; + } + } + } + } + else + { + _filteredParts = _filterItems[0].GetFilteredParts(); + } + + foreach (FilterGroup group in _subGroups) + { + FilterCombineType filterCombineType = group.CombineType; + Dictionary> newFilteredParts = group.GetFilteredParts(); + List toRemove = new List(); + + foreach (KeyValuePair> entry in newFilteredParts) + { + switch (filterCombineType) + { + case FilterCombineType.And: + toRemove = new List(); + + foreach (string part in _filteredParts[entry.Key]) + { + if (!entry.Value.Contains(part)) + { + toRemove.Add(part); + } + } + + _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); + break; + case FilterCombineType.Or: + HashSet uniqueList = entry.Value.ToHashSet(); + HashSet existingList = _filteredParts[entry.Key].ToHashSet(); + existingList.UnionWith(uniqueList); + _filteredParts[entry.Key] = existingList.ToList(); + + break; + case FilterCombineType.Not: + toRemove = new List(); + + foreach (string part in _filteredParts[entry.Key]) + { + if (entry.Value.Contains(part)) + { + toRemove.Add(part); + } + } + + _filteredParts[entry.Key].RemoveAll(part => toRemove.Contains(part)); + break; + } + } + } + + return _filteredParts; + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterGroup.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs old mode 100644 new mode 100755 index 8ce88813..221ed303 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs @@ -1,59 +1,59 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using System; -using System.Collections.Generic; - -namespace Synty.SidekickCharacters.Filters -{ - public class FilterItem - { - public SidekickRuntime Runtime; - public SidekickPartFilter Filter; - public FilterCombineType CombineType; - - private Dictionary> _filteredParts = new Dictionary>(); - - public FilterItem(SidekickRuntime runtime, SidekickPartFilter filter, FilterCombineType combineType) - { - Runtime = runtime; - Filter = filter; - CombineType = combineType; - } - - /// - /// Resets the part dictionary when the species is changed. - /// - public void ResetPartsForSpeciesChange() - { - _filteredParts = new Dictionary>(); - } - - /// - /// Gets a list of all the parts for this filter item. - /// - /// A list of all parts for this filter item. - public Dictionary> GetFilteredParts() - { - if (_filteredParts == null || _filteredParts.Count < 1) - { - _filteredParts = new Dictionary>(); - - foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) - { - List parts = SidekickPartFilterRow.GetAllPartNamesForFilterSpeciesAndType(Runtime.DBManager, Filter, Runtime.CurrentSpecies, type); - _filteredParts[type] = parts; - } - } - - return _filteredParts; - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using System; +using System.Collections.Generic; + +namespace Synty.SidekickCharacters.Filters +{ + public class FilterItem + { + public SidekickRuntime Runtime; + public SidekickPartFilter Filter; + public FilterCombineType CombineType; + + private Dictionary> _filteredParts = new Dictionary>(); + + public FilterItem(SidekickRuntime runtime, SidekickPartFilter filter, FilterCombineType combineType) + { + Runtime = runtime; + Filter = filter; + CombineType = combineType; + } + + /// + /// Resets the part dictionary when the species is changed. + /// + public void ResetPartsForSpeciesChange() + { + _filteredParts = new Dictionary>(); + } + + /// + /// Gets a list of all the parts for this filter item. + /// + /// A list of all parts for this filter item. + public Dictionary> GetFilteredParts() + { + if (_filteredParts == null || _filteredParts.Count < 1) + { + _filteredParts = new Dictionary>(); + + foreach (CharacterPartType type in Enum.GetValues(typeof(CharacterPartType))) + { + List parts = SidekickPartFilterRow.GetAllPartNamesForFilterSpeciesAndType(Runtime.DBManager, Filter, Runtime.CurrentSpecies, type); + _filteredParts[type] = parts; + } + } + + return _filteredParts; + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/FilterItem.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs old mode 100644 new mode 100755 index 94a322cb..3d2ad76e --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs @@ -1,36 +1,36 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace Synty.SidekickCharacters.Filters -{ - public class ParsedPart - { - public string Species; - public string Outfit1; - public string Outfit2; - public string PartArea; - public string Filename; - public string Name; - - public ParsedPart(string partName, string name) - { - Species = partName.Substring(partName.LastIndexOf('_') + 1, 2); - Outfit1 = partName.Substring(3, 4); - Outfit2 = partName.Substring(8, 4); - PartArea = partName.Substring(18, 4); - Filename = partName; - Name = name; - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace Synty.SidekickCharacters.Filters +{ + public class ParsedPart + { + public string Species; + public string Outfit1; + public string Outfit2; + public string PartArea; + public string Filename; + public string Name; + + public ParsedPart(string partName, string name) + { + Species = partName.Substring(partName.LastIndexOf('_') + 1, 2); + Outfit1 = partName.Substring(3, 4); + Outfit2 = partName.Substring(8, 4); + PartArea = partName.Substring(18, 4); + Filename = partName; + Name = name; + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs.meta old mode 100644 new mode 100755 index 46509973..eed22e3c --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs.meta +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/ParsedPart.cs.meta @@ -1,3 +1,3 @@ -fileFormatVersion: 2 -guid: 88015ac5c0e044149a859e8143155d4d +fileFormatVersion: 2 +guid: 88015ac5c0e044149a859e8143155d4d timeCreated: 1741050319 \ No newline at end of file diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs old mode 100644 new mode 100755 index f55d1b14..69070387 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs @@ -1,45 +1,45 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using System.Collections.Generic; -using System.Linq; - -namespace Synty.SidekickCharacters.Filters -{ - public class PresetFilterItem - { - public DatabaseManager DbManager; - public SidekickPresetFilter Filter; - public FilterCombineType CombineType; - - private List _filteredPresets; - - public PresetFilterItem(DatabaseManager dbManager, SidekickPresetFilter filter, FilterCombineType combineType) - { - DbManager = dbManager; - Filter = filter; - CombineType = combineType; - } - - /// - /// Gets a list of all the presets for this filter item. - /// - /// A list of all presets for this filter item. - public List GetFilteredPresets() - { - if (_filteredPresets == null || _filteredPresets.Count < 1) - { - _filteredPresets = SidekickPresetFilterRow.GetAllForFilter(DbManager, Filter).Select(row => row.Preset).ToList(); - } - - return _filteredPresets; - } - } -} +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using System.Collections.Generic; +using System.Linq; + +namespace Synty.SidekickCharacters.Filters +{ + public class PresetFilterItem + { + public DatabaseManager DbManager; + public SidekickPresetFilter Filter; + public FilterCombineType CombineType; + + private List _filteredPresets; + + public PresetFilterItem(DatabaseManager dbManager, SidekickPresetFilter filter, FilterCombineType combineType) + { + DbManager = dbManager; + Filter = filter; + CombineType = combineType; + } + + /// + /// Gets a list of all the presets for this filter item. + /// + /// A list of all presets for this filter item. + public List GetFilteredPresets() + { + if (_filteredPresets == null || _filteredPresets.Count < 1) + { + _filteredPresets = SidekickPresetFilterRow.GetAllForFilter(DbManager, Filter).Select(row => row.Preset).ToList(); + } + + return _filteredPresets; + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs.meta old mode 100644 new mode 100755 index e3bb4ef1..81175248 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs.meta +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Filters/PresetFilterItem.cs.meta @@ -1,3 +1,3 @@ -fileFormatVersion: 2 -guid: b852b386e6bc4e6eab4140b0d792d22e +fileFormatVersion: 2 +guid: b852b386e6bc4e6eab4140b0d792d22e timeCreated: 1747794343 \ No newline at end of file diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs old mode 100644 new mode 100755 index 589314eb..86b13814 --- a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs +++ b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs @@ -1,70 +1,70 @@ -// Copyright (c) 2025 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the End User Licence Agreement (EULA) -// of the store at which you purchased this asset. -// -// Synty assets are available at: -// https://www.syntystore.com -// https://assetstore.unity.com/publishers/5217 -// https://www.fab.com/sellers/Synty%20Studios -// -// Sample scripts are included only as examples and are not intended as production-ready. - -using UnityEngine; -using UnityEngine.EventSystems; - -#if ENABLE_INPUT_SYSTEM -using UnityEngine.InputSystem; -// compile errors? -using UnityEngine.InputSystem.UI; -// compile errors? -// if you are getting a compile error here you likely need to import the Input System package (com.unity.inputsystem) in the package manager or change the input setting in player settings back to 'Input Manager (Old)' -#endif - - -namespace Synty.SidekickCharacters.Utils -{ - /// - /// Sample script that helps automatically select the correct input event module depending on your project's settings. - /// - [ExecuteAlways] - [RequireComponent(typeof(EventSystem))] - public class SampleAutoInputModule : MonoBehaviour - { - void OnEnable() - { - UpdateInputModule(); - } - - void UpdateInputModule() - { -#if ENABLE_INPUT_SYSTEM - // New Input System only - if (GetComponent() == null) - { - // Remove any existing modules - foreach (var module in GetComponents()) - { - DestroyImmediate(module); - } - gameObject.AddComponent(); - if(!Application.isPlaying) Debug.Log("Added InputSystemUIInputModule (new input system)"); - } -#elif ENABLE_LEGACY_INPUT_MANAGER - // Old Input Manager only - if (GetComponent() == null) - { - // Remove any existing modules - foreach (var module in GetComponents()) - { - DestroyImmediate(module); - } - gameObject.AddComponent(); - if(!Application.isPlaying) Debug.Log("Added StandaloneInputModule (old input manager)"); - } -#else - Debug.LogWarning("No input system enabled in project settings."); -#endif - } - } -} +// Copyright (c) 2025 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the End User Licence Agreement (EULA) +// of the store at which you purchased this asset. +// +// Synty assets are available at: +// https://www.syntystore.com +// https://assetstore.unity.com/publishers/5217 +// https://www.fab.com/sellers/Synty%20Studios +// +// Sample scripts are included only as examples and are not intended as production-ready. + +using UnityEngine; +using UnityEngine.EventSystems; + +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +// compile errors? +using UnityEngine.InputSystem.UI; +// compile errors? +// if you are getting a compile error here you likely need to import the Input System package (com.unity.inputsystem) in the package manager or change the input setting in player settings back to 'Input Manager (Old)' +#endif + + +namespace Synty.SidekickCharacters.Utils +{ + /// + /// Sample script that helps automatically select the correct input event module depending on your project's settings. + /// + [ExecuteAlways] + [RequireComponent(typeof(EventSystem))] + public class SampleAutoInputModule : MonoBehaviour + { + void OnEnable() + { + UpdateInputModule(); + } + + void UpdateInputModule() + { +#if ENABLE_INPUT_SYSTEM + // New Input System only + if (GetComponent() == null) + { + // Remove any existing modules + foreach (var module in GetComponents()) + { + DestroyImmediate(module); + } + gameObject.AddComponent(); + if(!Application.isPlaying) Debug.Log("Added InputSystemUIInputModule (new input system)"); + } +#elif ENABLE_LEGACY_INPUT_MANAGER + // Old Input Manager only + if (GetComponent() == null) + { + // Remove any existing modules + foreach (var module in GetComponents()) + { + DestroyImmediate(module); + } + gameObject.AddComponent(); + if(!Application.isPlaying) Debug.Log("Added StandaloneInputModule (old input manager)"); + } +#else + Debug.LogWarning("No input system enabled in project settings."); +#endif + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs.meta b/Assets/External/Models/SidekickCharacters/Scripts/Runtime/Utils/SampleAutoInputModule.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Materials/M_SampleFace.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Materials/M_SampleFace.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Materials/SK_FacialDemoCharacter.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Materials/SK_FacialDemoCharacter.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Apocalypse_Bat/pasted__SK2.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Apocalypse_Bat/pasted__SK2.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Goblin_Axe/lambert2.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Goblin_Axe/lambert2.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/blinn1.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/blinn1.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert2.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert2.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert4.mat.meta b/Assets/External/Models/SidekickCharacters/_Demos/Meshes/Weapons/Pirate_Sword/lambert4.mat.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk b/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk old mode 100644 new mode 100755 index 739990ba..06561996 --- a/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk +++ b/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk @@ -1,761 +1,761 @@ -Name: SK_FacialDemoCharacter -Species: 1 -Parts: -- Name: SK_HUMN_BASE_01_01HEAD_HU01 - PartType: Head - PartVersion: 1 -- Name: SK_HUMN_BASE_01_04EBRR_HU01 - PartType: EyebrowRight - PartVersion: 1 -- Name: SK_HUMN_BASE_01_03EBRL_HU01 - PartType: EyebrowLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_10_21FOTR_HU01 - PartType: FootRight - PartVersion: 1 -- Name: SK_HUMN_BASE_01_05EYEL_HU01 - PartType: EyeLeft - PartVersion: 1 -- Name: SK_HUMN_BASE_01_06EYER_HU01 - PartType: EyeRight - PartVersion: 1 -- Name: SK_HUMN_BASE_01_07EARL_HU01 - PartType: EarLeft - PartVersion: 1 -- Name: SK_HUMN_BASE_01_08EARR_HU01 - PartType: EarRight - PartVersion: 1 -- Name: SK_HUMN_BASE_01_35NOSE_HU01 - PartType: Nose - PartVersion: 1 -- Name: SK_HUMN_BASE_01_02HAIR_HU01 - PartType: Hair - PartVersion: 1 -- Name: SK_HUMN_BASE_01_36TETH_HU01 - PartType: Teeth - PartVersion: 1 -- Name: SK_HUMN_BASE_01_37TONG_HU01 - PartType: Tongue - PartVersion: 1 -- Name: SK_APOC_OUTL_06_10TORS_HU01 - PartType: Torso - PartVersion: 1 -- Name: SK_APOC_OUTL_08_11AUPL_HU01 - PartType: ArmUpperLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_07_12AUPR_HU01 - PartType: ArmUpperRight - PartVersion: 1 -- Name: SK_APOC_OUTL_12_13ALWL_HU01 - PartType: ArmLowerLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_08_14ALWR_HU01 - PartType: ArmLowerRight - PartVersion: 1 -- Name: SK_APOC_OUTL_06_32AEBR_HU01 - PartType: AttachmentElbowRight - PartVersion: 1 -- Name: SK_APOC_OUTL_09_18LEGL_HU01 - PartType: LegLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_05_24ABAC_HU01 - PartType: AttachmentBack - PartVersion: 1 -- Name: SK_APOC_OUTL_08_20FOTL_HU01 - PartType: FootLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_09_17HIPS_HU01 - PartType: Hips - PartVersion: 1 -- Name: SK_APOC_OUTL_09_19LEGR_HU01 - PartType: LegRight - PartVersion: 1 -- Name: SK_APOC_OUTL_01_16HNDR_HU01 - PartType: HandRight - PartVersion: 1 -- Name: SK_APOC_OUTL_05_26AHPB_HU01 - PartType: AttachmentHipsBack - PartVersion: 1 -- Name: SK_APOC_OUTL_09_28AHPR_HU01 - PartType: AttachmentHipsRight - PartVersion: 1 -- Name: SK_APOC_OUTL_04_33AKNL_HU01 - PartType: AttachmentKneeLeft - PartVersion: 1 -- Name: SK_APOC_OUTL_04_34AKNR_HU01 - PartType: AttachmentKneeRight - PartVersion: 1 -- Name: SK_APOC_OUTL_06_27AHPL_HU01 - PartType: AttachmentHipsLeft - PartVersion: 1 -ColorSet: - Species: 1 - Name: Custom - SourceColorPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_ColorMap.png - SourceMetallicPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_MetallicMap.png - SourceSmoothnessPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_SmoothnessMap.png - SourceReflectionPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_ReflectionMap.png - SourceEmissionPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_EmissionMap.png - SourceOpacityPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_OpacityMap.png -ColorRows: -- ColorProperty: 1 - MainColor: BF9062 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 2 - MainColor: C7986A - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 3 - MainColor: C7986A - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 4 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 5 - MainColor: C7986A - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 6 - MainColor: BF9062 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 7 - MainColor: BF9062 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 8 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 9 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 10 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 11 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 12 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 13 - MainColor: AF8057 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 14 - MainColor: BF9062 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 15 - MainColor: E79A9C - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 16 - MainColor: FFF3CE - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 17 - MainColor: E5D8AF - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 18 - MainColor: E79A9C - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 19 - MainColor: E79A9C - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 20 - MainColor: D0D0D0 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 21 - MainColor: D0D0D0 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 22 - MainColor: 32281D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 23 - MainColor: 32281D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 24 - MainColor: 262626 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 25 - MainColor: 262626 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 26 - MainColor: 503E2B - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 27 - MainColor: 503E2B - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 28 - MainColor: FFFFFF - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 29 - MainColor: FFFFFF - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 30 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 31 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 32 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 33 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 34 - MainColor: CAA58E - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 35 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 36 - MainColor: 26272D - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 37 - MainColor: CAA58E - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 38 - MainColor: B35149 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 39 - MainColor: 944842 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 40 - MainColor: AFA382 - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 41 - MainColor: 94896F - Metallic: FF0000 - Smoothness: FF0000 - Reflection: FF0000 - Emission: FF0000 - Opacity: FF0000 -- ColorProperty: 42 - MainColor: 787469 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 43 - MainColor: 7F6637 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 44 - MainColor: 514C46 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 45 - MainColor: 7D6652 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 46 - MainColor: 6A5C4D - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 47 - MainColor: 787469 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 48 - MainColor: 7F6637 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 49 - MainColor: 403C37 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 50 - MainColor: 7D6652 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 51 - MainColor: 6A5C4D - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 52 - MainColor: 787469 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 53 - MainColor: 7F6637 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 54 - MainColor: 403C37 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 55 - MainColor: 7D6652 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 56 - MainColor: 6A5C4D - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 57 - MainColor: 787469 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 58 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 59 - MainColor: 65583F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 60 - MainColor: 898580 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 61 - MainColor: 76726C - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 62 - MainColor: 787469 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 63 - MainColor: 918473 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 64 - MainColor: 65583F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 65 - MainColor: 7D7973 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 66 - MainColor: 6A6660 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 67 - MainColor: 35425F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 68 - MainColor: 8F4F46 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 69 - MainColor: 9C793B - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 70 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 71 - MainColor: 575655 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 72 - MainColor: 35425F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 73 - MainColor: 35425F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 74 - MainColor: 9C793B - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 75 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 76 - MainColor: 575655 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 77 - MainColor: 35425F - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 78 - MainColor: 6A5143 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 79 - MainColor: 9C793B - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 80 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 81 - MainColor: 575655 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 82 - MainColor: 69584A - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 83 - MainColor: 5A441D - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 84 - MainColor: 514C46 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 85 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 86 - MainColor: 957A4A - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 87 - MainColor: 69584A - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 88 - MainColor: 5A441D - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 89 - MainColor: 514C46 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 90 - MainColor: 998B79 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 91 - MainColor: 957A4A - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 92 - MainColor: 7A593E - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 93 - MainColor: 7A593E - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -- ColorProperty: 94 - MainColor: B7B7B7 - Metallic: 545454 - Smoothness: 545454 - Reflection: 000000 - Emission: 000000 - Opacity: FFFFFF -BlendShapes: - BodyTypeValue: -100 - MuscleValue: -100 +Name: SK_FacialDemoCharacter +Species: 1 +Parts: +- Name: SK_HUMN_BASE_01_01HEAD_HU01 + PartType: Head + PartVersion: 1 +- Name: SK_HUMN_BASE_01_04EBRR_HU01 + PartType: EyebrowRight + PartVersion: 1 +- Name: SK_HUMN_BASE_01_03EBRL_HU01 + PartType: EyebrowLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_10_21FOTR_HU01 + PartType: FootRight + PartVersion: 1 +- Name: SK_HUMN_BASE_01_05EYEL_HU01 + PartType: EyeLeft + PartVersion: 1 +- Name: SK_HUMN_BASE_01_06EYER_HU01 + PartType: EyeRight + PartVersion: 1 +- Name: SK_HUMN_BASE_01_07EARL_HU01 + PartType: EarLeft + PartVersion: 1 +- Name: SK_HUMN_BASE_01_08EARR_HU01 + PartType: EarRight + PartVersion: 1 +- Name: SK_HUMN_BASE_01_35NOSE_HU01 + PartType: Nose + PartVersion: 1 +- Name: SK_HUMN_BASE_01_02HAIR_HU01 + PartType: Hair + PartVersion: 1 +- Name: SK_HUMN_BASE_01_36TETH_HU01 + PartType: Teeth + PartVersion: 1 +- Name: SK_HUMN_BASE_01_37TONG_HU01 + PartType: Tongue + PartVersion: 1 +- Name: SK_APOC_OUTL_06_10TORS_HU01 + PartType: Torso + PartVersion: 1 +- Name: SK_APOC_OUTL_08_11AUPL_HU01 + PartType: ArmUpperLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_07_12AUPR_HU01 + PartType: ArmUpperRight + PartVersion: 1 +- Name: SK_APOC_OUTL_12_13ALWL_HU01 + PartType: ArmLowerLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_08_14ALWR_HU01 + PartType: ArmLowerRight + PartVersion: 1 +- Name: SK_APOC_OUTL_06_32AEBR_HU01 + PartType: AttachmentElbowRight + PartVersion: 1 +- Name: SK_APOC_OUTL_09_18LEGL_HU01 + PartType: LegLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_05_24ABAC_HU01 + PartType: AttachmentBack + PartVersion: 1 +- Name: SK_APOC_OUTL_08_20FOTL_HU01 + PartType: FootLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_09_17HIPS_HU01 + PartType: Hips + PartVersion: 1 +- Name: SK_APOC_OUTL_09_19LEGR_HU01 + PartType: LegRight + PartVersion: 1 +- Name: SK_APOC_OUTL_01_16HNDR_HU01 + PartType: HandRight + PartVersion: 1 +- Name: SK_APOC_OUTL_05_26AHPB_HU01 + PartType: AttachmentHipsBack + PartVersion: 1 +- Name: SK_APOC_OUTL_09_28AHPR_HU01 + PartType: AttachmentHipsRight + PartVersion: 1 +- Name: SK_APOC_OUTL_04_33AKNL_HU01 + PartType: AttachmentKneeLeft + PartVersion: 1 +- Name: SK_APOC_OUTL_04_34AKNR_HU01 + PartType: AttachmentKneeRight + PartVersion: 1 +- Name: SK_APOC_OUTL_06_27AHPL_HU01 + PartType: AttachmentHipsLeft + PartVersion: 1 +ColorSet: + Species: 1 + Name: Custom + SourceColorPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_ColorMap.png + SourceMetallicPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_MetallicMap.png + SourceSmoothnessPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_SmoothnessMap.png + SourceReflectionPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_ReflectionMap.png + SourceEmissionPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_EmissionMap.png + SourceOpacityPath: Assets/Synty/Tools/SidekickCharacters/Resources/Textures/T_OpacityMap.png +ColorRows: +- ColorProperty: 1 + MainColor: BF9062 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 2 + MainColor: C7986A + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 3 + MainColor: C7986A + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 4 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 5 + MainColor: C7986A + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 6 + MainColor: BF9062 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 7 + MainColor: BF9062 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 8 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 9 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 10 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 11 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 12 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 13 + MainColor: AF8057 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 14 + MainColor: BF9062 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 15 + MainColor: E79A9C + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 16 + MainColor: FFF3CE + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 17 + MainColor: E5D8AF + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 18 + MainColor: E79A9C + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 19 + MainColor: E79A9C + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 20 + MainColor: D0D0D0 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 21 + MainColor: D0D0D0 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 22 + MainColor: 32281D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 23 + MainColor: 32281D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 24 + MainColor: 262626 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 25 + MainColor: 262626 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 26 + MainColor: 503E2B + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 27 + MainColor: 503E2B + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 28 + MainColor: FFFFFF + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 29 + MainColor: FFFFFF + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 30 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 31 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 32 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 33 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 34 + MainColor: CAA58E + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 35 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 36 + MainColor: 26272D + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 37 + MainColor: CAA58E + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 38 + MainColor: B35149 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 39 + MainColor: 944842 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 40 + MainColor: AFA382 + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 41 + MainColor: 94896F + Metallic: FF0000 + Smoothness: FF0000 + Reflection: FF0000 + Emission: FF0000 + Opacity: FF0000 +- ColorProperty: 42 + MainColor: 787469 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 43 + MainColor: 7F6637 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 44 + MainColor: 514C46 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 45 + MainColor: 7D6652 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 46 + MainColor: 6A5C4D + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 47 + MainColor: 787469 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 48 + MainColor: 7F6637 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 49 + MainColor: 403C37 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 50 + MainColor: 7D6652 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 51 + MainColor: 6A5C4D + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 52 + MainColor: 787469 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 53 + MainColor: 7F6637 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 54 + MainColor: 403C37 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 55 + MainColor: 7D6652 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 56 + MainColor: 6A5C4D + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 57 + MainColor: 787469 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 58 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 59 + MainColor: 65583F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 60 + MainColor: 898580 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 61 + MainColor: 76726C + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 62 + MainColor: 787469 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 63 + MainColor: 918473 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 64 + MainColor: 65583F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 65 + MainColor: 7D7973 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 66 + MainColor: 6A6660 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 67 + MainColor: 35425F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 68 + MainColor: 8F4F46 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 69 + MainColor: 9C793B + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 70 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 71 + MainColor: 575655 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 72 + MainColor: 35425F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 73 + MainColor: 35425F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 74 + MainColor: 9C793B + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 75 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 76 + MainColor: 575655 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 77 + MainColor: 35425F + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 78 + MainColor: 6A5143 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 79 + MainColor: 9C793B + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 80 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 81 + MainColor: 575655 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 82 + MainColor: 69584A + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 83 + MainColor: 5A441D + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 84 + MainColor: 514C46 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 85 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 86 + MainColor: 957A4A + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 87 + MainColor: 69584A + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 88 + MainColor: 5A441D + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 89 + MainColor: 514C46 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 90 + MainColor: 998B79 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 91 + MainColor: 957A4A + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 92 + MainColor: 7A593E + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 93 + MainColor: 7A593E + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +- ColorProperty: 94 + MainColor: B7B7B7 + Metallic: 545454 + Smoothness: 545454 + Reflection: 000000 + Emission: 000000 + Opacity: FFFFFF +BlendShapes: + BodyTypeValue: -100 + MuscleValue: -100 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk.meta b/Assets/External/Models/SidekickCharacters/_Demos/SavedCharacters/SK_FacialDemoCharacter.sk.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs old mode 100644 new mode 100755 index 0a5232cc..113d1719 --- a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs +++ b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs @@ -1,140 +1,140 @@ -using UnityEngine; -using UnityEngine.UI; - -public class RandomisedLayerWeight : MonoBehaviour -{ - [SerializeField] private Animator animator; - - [Header("Random Variance Settings")] - [SerializeField, Range(0f, 1f)] private float maxRandomVariance = 0.5f; - [SerializeField] private Slider randomVarianceSlider; - [SerializeField] private Text maxRandomVarianceText; // UI Text to display maxRandomVariance - - [Header("Layer Weight Settings")] // Changed header name to "Layer Weight Settings" - [SerializeField, Range(0f, 1f)] private float layerWeight = 1f; // Changed variable name to layerWeight - [SerializeField] private Slider layerWeightSlider; // Changed slider name to layerWeightSlider - [SerializeField] private Text layerWeightText; // Changed UI Text name to layerWeightText - - [Header("Transition Settings")] - [SerializeField] private string layerName = "Emotion_Additive"; // Adjust this layer name in the Inspector - [SerializeField] private float averageTransitionTime = 0.4f; - [SerializeField] private float transitionVariationAmount = 0.3f; - - [Header("Hold Settings")] - [SerializeField] private float averageHoldTime = 1.0f; - [SerializeField] private float holdVariationAmount = 1.0f; - - private int layerIndex; - private float currentWeight = 0f; - private float targetWeight = 0f; - private float transitionTimer = 0f; - private float holdTimer = 0f; - - void Start() - { - if (animator == null) - { - Debug.LogError("Animator component is not assigned."); - enabled = false; - return; - } - - layerIndex = animator.GetLayerIndex(layerName); - if (layerIndex == -1) - { - Debug.LogError($"Layer '{layerName}' not found in the Animator."); - enabled = false; - return; - } - - // Initialize sliders and UI Texts - if (randomVarianceSlider != null) - { - randomVarianceSlider.value = maxRandomVariance; - randomVarianceSlider.onValueChanged.AddListener(SetMaxRandomVariance); - } - - if (layerWeightSlider != null) // Changed to layerWeightSlider - { - layerWeightSlider.value = layerWeight; // Changed to layerWeight - layerWeightSlider.onValueChanged.AddListener(SetLayerWeight); // Changed to SetLayerWeight - } - - // Initialize UI Texts - if (maxRandomVarianceText != null) - { - maxRandomVarianceText.text = $"Random Variance: {maxRandomVariance:P0}"; - } - - if (layerWeightText != null) // Changed to layerWeightText - { - layerWeightText.text = $"Layer Weight: {layerWeight:P0}"; // Changed to Layer Weight - } - - // Initialize the weight to a random value between 0 and 1 - currentWeight = Random.value; - animator.SetLayerWeight(layerIndex, currentWeight * layerWeight); // Changed to layerWeight - - // Start the initial transition - StartTransition(); - } - - void Update() - { - // Update timers - transitionTimer -= Time.deltaTime; - holdTimer -= Time.deltaTime; - - // Check if it's time to transition to a new weight - if (transitionTimer <= 0f) - { - StartTransition(); - } - // Otherwise, check if it's time to hold the current weight - else if (holdTimer <= 0f) - { - holdTimer = GenerateHoldTime(); - } - - // Smoothly adjust the weight towards the target weight - currentWeight = Mathf.Lerp(currentWeight, targetWeight, Time.deltaTime / averageTransitionTime); - animator.SetLayerWeight(layerIndex, currentWeight * layerWeight); // Changed to layerWeight - } - - private void StartTransition() - { - // Set a new target weight - targetWeight = Random.Range(Mathf.Max(0f, 1f - maxRandomVariance), 1f) * layerWeight; // Changed to layerWeight - transitionTimer = GenerateTransitionTime(); - } - - private float GenerateTransitionTime() - { - float variation = Random.Range(-transitionVariationAmount, transitionVariationAmount); - return Mathf.Max(0f, averageTransitionTime + variation); - } - - private float GenerateHoldTime() - { - float variation = Random.Range(-holdVariationAmount, holdVariationAmount); - return Mathf.Max(0f, averageHoldTime + variation); - } - - private void SetMaxRandomVariance(float value) - { - maxRandomVariance = value; - if (maxRandomVarianceText != null) - { - maxRandomVarianceText.text = $"Random Variance: {maxRandomVariance:P0}"; - } - } - - private void SetLayerWeight(float value) // Changed method name to SetLayerWeight - { - layerWeight = value; // Changed to layerWeight - if (layerWeightText != null) // Changed to layerWeightText - { - layerWeightText.text = $"Layer Weight: {layerWeight:P0}"; // Changed to Layer Weight - } - } -} +using UnityEngine; +using UnityEngine.UI; + +public class RandomisedLayerWeight : MonoBehaviour +{ + [SerializeField] private Animator animator; + + [Header("Random Variance Settings")] + [SerializeField, Range(0f, 1f)] private float maxRandomVariance = 0.5f; + [SerializeField] private Slider randomVarianceSlider; + [SerializeField] private Text maxRandomVarianceText; // UI Text to display maxRandomVariance + + [Header("Layer Weight Settings")] // Changed header name to "Layer Weight Settings" + [SerializeField, Range(0f, 1f)] private float layerWeight = 1f; // Changed variable name to layerWeight + [SerializeField] private Slider layerWeightSlider; // Changed slider name to layerWeightSlider + [SerializeField] private Text layerWeightText; // Changed UI Text name to layerWeightText + + [Header("Transition Settings")] + [SerializeField] private string layerName = "Emotion_Additive"; // Adjust this layer name in the Inspector + [SerializeField] private float averageTransitionTime = 0.4f; + [SerializeField] private float transitionVariationAmount = 0.3f; + + [Header("Hold Settings")] + [SerializeField] private float averageHoldTime = 1.0f; + [SerializeField] private float holdVariationAmount = 1.0f; + + private int layerIndex; + private float currentWeight = 0f; + private float targetWeight = 0f; + private float transitionTimer = 0f; + private float holdTimer = 0f; + + void Start() + { + if (animator == null) + { + Debug.LogError("Animator component is not assigned."); + enabled = false; + return; + } + + layerIndex = animator.GetLayerIndex(layerName); + if (layerIndex == -1) + { + Debug.LogError($"Layer '{layerName}' not found in the Animator."); + enabled = false; + return; + } + + // Initialize sliders and UI Texts + if (randomVarianceSlider != null) + { + randomVarianceSlider.value = maxRandomVariance; + randomVarianceSlider.onValueChanged.AddListener(SetMaxRandomVariance); + } + + if (layerWeightSlider != null) // Changed to layerWeightSlider + { + layerWeightSlider.value = layerWeight; // Changed to layerWeight + layerWeightSlider.onValueChanged.AddListener(SetLayerWeight); // Changed to SetLayerWeight + } + + // Initialize UI Texts + if (maxRandomVarianceText != null) + { + maxRandomVarianceText.text = $"Random Variance: {maxRandomVariance:P0}"; + } + + if (layerWeightText != null) // Changed to layerWeightText + { + layerWeightText.text = $"Layer Weight: {layerWeight:P0}"; // Changed to Layer Weight + } + + // Initialize the weight to a random value between 0 and 1 + currentWeight = Random.value; + animator.SetLayerWeight(layerIndex, currentWeight * layerWeight); // Changed to layerWeight + + // Start the initial transition + StartTransition(); + } + + void Update() + { + // Update timers + transitionTimer -= Time.deltaTime; + holdTimer -= Time.deltaTime; + + // Check if it's time to transition to a new weight + if (transitionTimer <= 0f) + { + StartTransition(); + } + // Otherwise, check if it's time to hold the current weight + else if (holdTimer <= 0f) + { + holdTimer = GenerateHoldTime(); + } + + // Smoothly adjust the weight towards the target weight + currentWeight = Mathf.Lerp(currentWeight, targetWeight, Time.deltaTime / averageTransitionTime); + animator.SetLayerWeight(layerIndex, currentWeight * layerWeight); // Changed to layerWeight + } + + private void StartTransition() + { + // Set a new target weight + targetWeight = Random.Range(Mathf.Max(0f, 1f - maxRandomVariance), 1f) * layerWeight; // Changed to layerWeight + transitionTimer = GenerateTransitionTime(); + } + + private float GenerateTransitionTime() + { + float variation = Random.Range(-transitionVariationAmount, transitionVariationAmount); + return Mathf.Max(0f, averageTransitionTime + variation); + } + + private float GenerateHoldTime() + { + float variation = Random.Range(-holdVariationAmount, holdVariationAmount); + return Mathf.Max(0f, averageHoldTime + variation); + } + + private void SetMaxRandomVariance(float value) + { + maxRandomVariance = value; + if (maxRandomVarianceText != null) + { + maxRandomVarianceText.text = $"Random Variance: {maxRandomVariance:P0}"; + } + } + + private void SetLayerWeight(float value) // Changed method name to SetLayerWeight + { + layerWeight = value; // Changed to layerWeight + if (layerWeightText != null) // Changed to layerWeightText + { + layerWeightText.text = $"Layer Weight: {layerWeight:P0}"; // Changed to Layer Weight + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs.meta b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RandomisedLayerWeight.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs old mode 100644 new mode 100755 index 430e134e..226859e3 --- a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs +++ b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs @@ -1,223 +1,223 @@ -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using Synty.SidekickCharacters.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using TMPro; -using UnityEngine; -using UnityEngine.UI; -using Random = UnityEngine.Random; - -namespace Synty.SidekickCharacters.Demo -{ - /// - /// An example script to show how to interact with the Sidekick API in regards to colors at runtime. - /// - public class RuntimeColorDemo : MonoBehaviour - { - private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; - - private Dictionary _availableHeadPresetDictionary = new Dictionary(); - private Dictionary _availableUpperBodyPresetDictionary = new Dictionary(); - private Dictionary _availableLowerBodyPresetDictionary = new Dictionary(); - private List _availableBodyShapes = new List(); - private List _availableColorPresets = new List(); - - private int _currentHeadPresetIndex = 0; - private int _currentUpperBodyPresetIndex = 0; - private int _currentLowerBodyPresetIndex = 0; - private int _currentBodyShapePresetIndex = 0; - private int _currentColorPresetIndex = 0; - - private DatabaseManager _dbManager; - private SidekickRuntime _sidekickRuntime; - - private Dictionary> _partLibrary; - - public TextMeshProUGUI _loadingText; - - /// - void Start() - { - _dbManager = new DatabaseManager(); - - GameObject model = Resources.Load("Meshes/SK_BaseModel"); - Material material = Resources.Load("Materials/M_BaseMaterial"); - - _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); - - SidekickRuntime.PopulateToolData(_sidekickRuntime); - _partLibrary = _sidekickRuntime.MappedPartDictionary; - - foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) - { - // only filter head part presets by species - List presets = SidekickPartPreset.GetAllByGroup(_dbManager, partGroup); - List presetNames = new List(); - if (presets.Count < 1) - { - Debug.LogWarning("No parts found for " + partGroup + ". Please add at least 1 Sidekicks content pack."); - continue; - } - - foreach (SidekickPartPreset preset in presets) - { - switch (partGroup) - { - case PartGroup.Head: - _availableHeadPresetDictionary.Add(preset.Name, preset); - break; - case PartGroup.UpperBody: - _availableUpperBodyPresetDictionary.Add(preset.Name, preset); - break; - case PartGroup.LowerBody: - _availableLowerBodyPresetDictionary.Add(preset.Name, preset); - break; - } - - presetNames.Add(preset.Name); - } - } - - _availableBodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); - - // An example of how to retrieve color presets from the database. To retrieve presets for other areas of the material, use the ColorGroup - // enum to retrieve other presets. - _availableColorPresets = SidekickColorPreset.GetAllByColorGroup(_dbManager, ColorGroup.Outfits); - - _currentHeadPresetIndex = Random.Range(0, _availableHeadPresetDictionary.Count - 1); - _currentUpperBodyPresetIndex = Random.Range(0, _availableUpperBodyPresetDictionary.Count - 1); - _currentLowerBodyPresetIndex = Random.Range(0, _availableLowerBodyPresetDictionary.Count - 1); - _currentBodyShapePresetIndex = Random.Range(0, _availableBodyShapes.Count - 1); - _currentColorPresetIndex = Random.Range(0, _availableColorPresets.Count - 1); - - _loadingText.enabled = false; - - UpdateModel(); - } - - /// - /// Processes the change of the skin color on the character. - /// - /// The image tile that contains the color to change to. - public void ProcessSkinColorChange(Image image) - { - ColorType colorType = ColorType.MainColor; - List allProperties = SidekickColorProperty.GetAll(_dbManager); - List selectedProperties = allProperties.FindAll(scp => scp.Name.ToLower().Contains("skin")); - foreach (SidekickColorProperty property in selectedProperties) - { - SidekickColorRow row = new SidekickColorRow() - { - ColorProperty = property, - MainColor = ColorUtility.ToHtmlStringRGB(image.color), - }; - _sidekickRuntime.UpdateColor(colorType, row); - } - } - - /// - /// Processes the change of the outfit color on the character. - /// - /// The image tile that contains the color to change to. - public void ProcessOutfitColorChange(Image image) - { - ColorType colorType = ColorType.MainColor; - List allProperties = SidekickColorProperty.GetAll(_dbManager); - List selectedProperties = allProperties.FindAll(scp => scp.Name.ToLower().Contains("outfit")); - foreach (SidekickColorProperty property in selectedProperties) - { - SidekickColorRow row = new SidekickColorRow() - { - ColorProperty = property, - MainColor = ColorUtility.ToHtmlStringRGB(image.color), - }; - _sidekickRuntime.UpdateColor(colorType, row); - } - } - - /// - /// Updates the created character model. - /// - private void UpdateModel() - { - // If there aren't enough presets, stop trying to update the model. - if (_availableHeadPresetDictionary.Values.Count < 1 - || _availableUpperBodyPresetDictionary.Values.Count < 1 - || _availableLowerBodyPresetDictionary.Values.Count < 1) - { - return; - } - - // Create and populate the list of parts to use from the parts list and the selected colors. - List presets = new List() - { - _availableHeadPresetDictionary.Values.ToArray()[_currentHeadPresetIndex], - _availableUpperBodyPresetDictionary.Values.ToArray()[_currentUpperBodyPresetIndex], - _availableLowerBodyPresetDictionary.Values.ToArray()[_currentLowerBodyPresetIndex] - }; - - List partsToUse = new List(); - - foreach (SidekickPartPreset preset in presets) - { - List rows = SidekickPartPresetRow.GetAllByPreset(_dbManager, preset); - foreach (SidekickPartPresetRow row in rows) - { - if (!string.IsNullOrEmpty(row.PartName)) - { - CharacterPartType type = Enum.Parse(CharacterPartTypeUtils.GetTypeNameFromShortcode(row.PartType)); - Dictionary partLocationDictionary = _partLibrary[type]; - GameObject selectedPart = partLocationDictionary[row.PartName].GetPartModel(); - SkinnedMeshRenderer selectedMesh = selectedPart.GetComponentInChildren(); - partsToUse.Add(selectedMesh); - } - } - } - - SidekickBodyShapePreset bodyPreset = _availableBodyShapes[_currentBodyShapePresetIndex]; - _sidekickRuntime.BodyTypeBlendValue = bodyPreset.BodyType; - _sidekickRuntime.BodySizeHeavyBlendValue = bodyPreset.BodySize > 0 ? bodyPreset.BodySize : 0; - _sidekickRuntime.BodySizeSkinnyBlendValue = bodyPreset.BodySize < 0 ? -bodyPreset.BodySize : 0; - _sidekickRuntime.MusclesBlendValue = bodyPreset.Musculature; - - List colorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, _availableColorPresets[_currentColorPresetIndex]); - foreach (SidekickColorPresetRow row in colorRows) - { - SidekickColorRow colorRow = SidekickColorRow.CreateFromPresetColorRow(row); - foreach (ColorType property in Enum.GetValues(typeof(ColorType))) - { - _sidekickRuntime.UpdateColor(property, colorRow); - } - } - - // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. - GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); - - if (character != null) - { - Destroy(character); - } - - // Create a new character using the selected parts using the Sidekicks API. - character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); - } - - /// - /// Gets a resource path for using with Resources.Load() from a full path. - /// - /// The full path to get the resource path from. - /// The resource path. - private string GetResourcePath(string fullPath) - { - string directory = Path.GetDirectoryName(fullPath); - int startIndex = directory.IndexOf("Resources") + 10; - directory = directory.Substring(startIndex, directory.Length - startIndex); - return Path.Combine(directory, Path.GetFileNameWithoutExtension(fullPath)); - } - } -} +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using Synty.SidekickCharacters.Utils; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TMPro; +using UnityEngine; +using UnityEngine.UI; +using Random = UnityEngine.Random; + +namespace Synty.SidekickCharacters.Demo +{ + /// + /// An example script to show how to interact with the Sidekick API in regards to colors at runtime. + /// + public class RuntimeColorDemo : MonoBehaviour + { + private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; + + private Dictionary _availableHeadPresetDictionary = new Dictionary(); + private Dictionary _availableUpperBodyPresetDictionary = new Dictionary(); + private Dictionary _availableLowerBodyPresetDictionary = new Dictionary(); + private List _availableBodyShapes = new List(); + private List _availableColorPresets = new List(); + + private int _currentHeadPresetIndex = 0; + private int _currentUpperBodyPresetIndex = 0; + private int _currentLowerBodyPresetIndex = 0; + private int _currentBodyShapePresetIndex = 0; + private int _currentColorPresetIndex = 0; + + private DatabaseManager _dbManager; + private SidekickRuntime _sidekickRuntime; + + private Dictionary> _partLibrary; + + public TextMeshProUGUI _loadingText; + + /// + void Start() + { + _dbManager = new DatabaseManager(); + + GameObject model = Resources.Load("Meshes/SK_BaseModel"); + Material material = Resources.Load("Materials/M_BaseMaterial"); + + _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); + + SidekickRuntime.PopulateToolData(_sidekickRuntime); + _partLibrary = _sidekickRuntime.MappedPartDictionary; + + foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) + { + // only filter head part presets by species + List presets = SidekickPartPreset.GetAllByGroup(_dbManager, partGroup); + List presetNames = new List(); + if (presets.Count < 1) + { + Debug.LogWarning("No parts found for " + partGroup + ". Please add at least 1 Sidekicks content pack."); + continue; + } + + foreach (SidekickPartPreset preset in presets) + { + switch (partGroup) + { + case PartGroup.Head: + _availableHeadPresetDictionary.Add(preset.Name, preset); + break; + case PartGroup.UpperBody: + _availableUpperBodyPresetDictionary.Add(preset.Name, preset); + break; + case PartGroup.LowerBody: + _availableLowerBodyPresetDictionary.Add(preset.Name, preset); + break; + } + + presetNames.Add(preset.Name); + } + } + + _availableBodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); + + // An example of how to retrieve color presets from the database. To retrieve presets for other areas of the material, use the ColorGroup + // enum to retrieve other presets. + _availableColorPresets = SidekickColorPreset.GetAllByColorGroup(_dbManager, ColorGroup.Outfits); + + _currentHeadPresetIndex = Random.Range(0, _availableHeadPresetDictionary.Count - 1); + _currentUpperBodyPresetIndex = Random.Range(0, _availableUpperBodyPresetDictionary.Count - 1); + _currentLowerBodyPresetIndex = Random.Range(0, _availableLowerBodyPresetDictionary.Count - 1); + _currentBodyShapePresetIndex = Random.Range(0, _availableBodyShapes.Count - 1); + _currentColorPresetIndex = Random.Range(0, _availableColorPresets.Count - 1); + + _loadingText.enabled = false; + + UpdateModel(); + } + + /// + /// Processes the change of the skin color on the character. + /// + /// The image tile that contains the color to change to. + public void ProcessSkinColorChange(Image image) + { + ColorType colorType = ColorType.MainColor; + List allProperties = SidekickColorProperty.GetAll(_dbManager); + List selectedProperties = allProperties.FindAll(scp => scp.Name.ToLower().Contains("skin")); + foreach (SidekickColorProperty property in selectedProperties) + { + SidekickColorRow row = new SidekickColorRow() + { + ColorProperty = property, + MainColor = ColorUtility.ToHtmlStringRGB(image.color), + }; + _sidekickRuntime.UpdateColor(colorType, row); + } + } + + /// + /// Processes the change of the outfit color on the character. + /// + /// The image tile that contains the color to change to. + public void ProcessOutfitColorChange(Image image) + { + ColorType colorType = ColorType.MainColor; + List allProperties = SidekickColorProperty.GetAll(_dbManager); + List selectedProperties = allProperties.FindAll(scp => scp.Name.ToLower().Contains("outfit")); + foreach (SidekickColorProperty property in selectedProperties) + { + SidekickColorRow row = new SidekickColorRow() + { + ColorProperty = property, + MainColor = ColorUtility.ToHtmlStringRGB(image.color), + }; + _sidekickRuntime.UpdateColor(colorType, row); + } + } + + /// + /// Updates the created character model. + /// + private void UpdateModel() + { + // If there aren't enough presets, stop trying to update the model. + if (_availableHeadPresetDictionary.Values.Count < 1 + || _availableUpperBodyPresetDictionary.Values.Count < 1 + || _availableLowerBodyPresetDictionary.Values.Count < 1) + { + return; + } + + // Create and populate the list of parts to use from the parts list and the selected colors. + List presets = new List() + { + _availableHeadPresetDictionary.Values.ToArray()[_currentHeadPresetIndex], + _availableUpperBodyPresetDictionary.Values.ToArray()[_currentUpperBodyPresetIndex], + _availableLowerBodyPresetDictionary.Values.ToArray()[_currentLowerBodyPresetIndex] + }; + + List partsToUse = new List(); + + foreach (SidekickPartPreset preset in presets) + { + List rows = SidekickPartPresetRow.GetAllByPreset(_dbManager, preset); + foreach (SidekickPartPresetRow row in rows) + { + if (!string.IsNullOrEmpty(row.PartName)) + { + CharacterPartType type = Enum.Parse(CharacterPartTypeUtils.GetTypeNameFromShortcode(row.PartType)); + Dictionary partLocationDictionary = _partLibrary[type]; + GameObject selectedPart = partLocationDictionary[row.PartName].GetPartModel(); + SkinnedMeshRenderer selectedMesh = selectedPart.GetComponentInChildren(); + partsToUse.Add(selectedMesh); + } + } + } + + SidekickBodyShapePreset bodyPreset = _availableBodyShapes[_currentBodyShapePresetIndex]; + _sidekickRuntime.BodyTypeBlendValue = bodyPreset.BodyType; + _sidekickRuntime.BodySizeHeavyBlendValue = bodyPreset.BodySize > 0 ? bodyPreset.BodySize : 0; + _sidekickRuntime.BodySizeSkinnyBlendValue = bodyPreset.BodySize < 0 ? -bodyPreset.BodySize : 0; + _sidekickRuntime.MusclesBlendValue = bodyPreset.Musculature; + + List colorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, _availableColorPresets[_currentColorPresetIndex]); + foreach (SidekickColorPresetRow row in colorRows) + { + SidekickColorRow colorRow = SidekickColorRow.CreateFromPresetColorRow(row); + foreach (ColorType property in Enum.GetValues(typeof(ColorType))) + { + _sidekickRuntime.UpdateColor(property, colorRow); + } + } + + // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. + GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); + + if (character != null) + { + Destroy(character); + } + + // Create a new character using the selected parts using the Sidekicks API. + character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); + } + + /// + /// Gets a resource path for using with Resources.Load() from a full path. + /// + /// The full path to get the resource path from. + /// The resource path. + private string GetResourcePath(string fullPath) + { + string directory = Path.GetDirectoryName(fullPath); + int startIndex = directory.IndexOf("Resources") + 10; + directory = directory.Substring(startIndex, directory.Length - startIndex); + return Path.Combine(directory, Path.GetFileNameWithoutExtension(fullPath)); + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs.meta b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimeColorDemo.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs old mode 100644 new mode 100755 index dab5d15b..0f0429e5 --- a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs +++ b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs @@ -1,380 +1,380 @@ -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using Synty.SidekickCharacters.Utils; -using System.Collections.Generic; -using System.Linq; -using TMPro; -using UnityEngine; -using UnityEngine.UI; -using Random = UnityEngine.Random; - -namespace Synty.SidekickCharacters.Demo -{ - /// - /// An example script to show how to interact with the Sidekick API in regards to parts at runtime. - /// - public class RuntimePartsDemo : MonoBehaviour - { - private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; - - Dictionary _partIndexDictionary = new Dictionary(); - Dictionary> _availablePartDictionary = new Dictionary>(); - - private DatabaseManager _dbManager; - private SidekickRuntime _sidekickRuntime; - - private Dictionary> _partLibrary; - - public TextMeshProUGUI _loadingText; - - /// - void Start() - { - // Create a new instance of the database manager to access database content. - _dbManager = new DatabaseManager(); - - // Load the base model and material required to create an instance of the Sidekick Runtime API. - GameObject model = Resources.Load("Meshes/SK_BaseModel"); - Material material = Resources.Load("Materials/M_BaseMaterial"); - - _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); - - // Populate the parts list for easy access. - SidekickRuntime.PopulateToolData(_sidekickRuntime); - _partLibrary = _sidekickRuntime.MappedPartDictionary; - - // For this example we are only interested in Upper Body parts, so we filter the list of all parts to only get the ones we want. - List upperBodyParts = PartGroup.UpperBody.GetPartTypes(); - - foreach (CharacterPartType type in upperBodyParts) - { - _availablePartDictionary.Add(type, _partLibrary[type]); - _partIndexDictionary.Add(type, Random.Range(0, _availablePartDictionary[type].Count - 1)); - } - - _loadingText.enabled = false; - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Torso part. - /// - public void ForwardTorso() - { - int index = _partIndexDictionary[CharacterPartType.Torso]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.Torso].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.Torso] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Torso part. - /// - public void BackwardTorso() - { - int index = _partIndexDictionary[CharacterPartType.Torso]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.Torso].Count - 1; - } - - _partIndexDictionary[CharacterPartType.Torso] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the ArmUpperLeft part. - /// - public void ForwardUpperArmLeft() - { - int index = _partIndexDictionary[CharacterPartType.ArmUpperLeft]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.ArmUpperLeft].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.ArmUpperLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the ArmUpperLeft part. - /// - public void BackwardUpperArmLeft() - { - int index = _partIndexDictionary[CharacterPartType.ArmUpperLeft]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.ArmUpperLeft].Count - 1; - } - - _partIndexDictionary[CharacterPartType.ArmUpperLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the ArmUpperRight part. - /// - public void ForwardUpperArmRight() - { - int index = _partIndexDictionary[CharacterPartType.ArmUpperRight]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.ArmUpperRight].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.ArmUpperRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the ArmUpperRight part. - /// - public void BackwardUpperArmRight() - { - int index = _partIndexDictionary[CharacterPartType.ArmUpperRight]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.ArmUpperRight].Count - 1; - } - - _partIndexDictionary[CharacterPartType.ArmUpperRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the ArmLowerLeft part. - /// - public void ForwardLowerArmLeft() - { - int index = _partIndexDictionary[CharacterPartType.ArmLowerLeft]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.ArmLowerLeft].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.ArmLowerLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the ArmLowerLeft part. - /// - public void BackwardLowerArmLeft() - { - int index = _partIndexDictionary[CharacterPartType.ArmLowerLeft]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.ArmLowerLeft].Count - 1; - } - - _partIndexDictionary[CharacterPartType.ArmLowerLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the ArmLowerRight part. - /// - public void ForwardLowerArmRight() - { - int index = _partIndexDictionary[CharacterPartType.ArmLowerRight]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.ArmLowerRight].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.ArmLowerRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the ArmLowerRight part. - /// - public void BackwardLowerArmRight() - { - int index = _partIndexDictionary[CharacterPartType.ArmLowerRight]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.ArmLowerRight].Count - 1; - } - - _partIndexDictionary[CharacterPartType.ArmLowerRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the HandLeft part. - /// - public void ForwardHandLeft() - { - int index = _partIndexDictionary[CharacterPartType.HandLeft]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.HandLeft].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.HandLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the HandLeft part. - /// - public void BackwardHandLeft() - { - int index = _partIndexDictionary[CharacterPartType.HandLeft]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.HandLeft].Count - 1; - } - - _partIndexDictionary[CharacterPartType.HandLeft] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the HandRight part. - /// - public void ForwardHandRight() - { - int index = _partIndexDictionary[CharacterPartType.HandRight]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.HandRight].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.HandRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the HandRight part. - /// - public void BackwardHandRight() - { - int index = _partIndexDictionary[CharacterPartType.HandRight]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.HandRight].Count - 1; - } - - _partIndexDictionary[CharacterPartType.HandRight] = index; - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the AttachmentBack part. - /// - public void ForwardBackAttachment() - { - int index = _partIndexDictionary[CharacterPartType.AttachmentBack]; - index++; - if (index >= _availablePartDictionary[CharacterPartType.AttachmentBack].Count) - { - index = 0; - } - - _partIndexDictionary[CharacterPartType.AttachmentBack] = index; - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the AttachmentBack part. - /// - public void BackwardBackAttachment() - { - int index = _partIndexDictionary[CharacterPartType.AttachmentBack]; - index--; - if (index < 0) - { - index = _availablePartDictionary[CharacterPartType.AttachmentBack].Count - 1; - } - - _partIndexDictionary[CharacterPartType.AttachmentBack] = index; - UpdateModel(); - } - - /// - /// Updates the body size blends based on the slider values. - /// - /// The UI slider to get the values from. - public void UpdateBodySize(Slider slider) - { - // If the slider is greater than 0, then we update the Heavy blend and zero the Skinny. - if (slider.value > 0) - { - _sidekickRuntime.BodySizeHeavyBlendValue = slider.value; - _sidekickRuntime.BodySizeSkinnyBlendValue = 0; - } - // If the slider is 0 or below, we zero the Heavy blend, then we update the Skinny blend. - else - { - _sidekickRuntime.BodySizeHeavyBlendValue = 0; - _sidekickRuntime.BodySizeSkinnyBlendValue = -slider.value; - } - - UpdateModel(); - } - - /// - /// Updates the created character model. - /// - private void UpdateModel() - { - // Create and populate the list of parts to use from the parts list. - List partsToUse = new List(); - - foreach (KeyValuePair> entry in _availablePartDictionary) - { - int index = _partIndexDictionary[entry.Key]; - List parts = entry.Value.Values.ToList(); - GameObject partContainer = null; - if (parts.Count > 0 && index < parts.Count) - { - if (index > parts.Count) - { - index = parts.Count - 1; - } - partContainer = parts[index].GetPartModel(); - } - - if (partContainer != null) - { - partsToUse.Add(partContainer.GetComponentInChildren()); - } - } - - // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. - GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); - - if (character != null) - { - Destroy(character); - } - - // Create a new character using the selected parts using the Sidekicks API. - character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); - } - } -} +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using Synty.SidekickCharacters.Utils; +using System.Collections.Generic; +using System.Linq; +using TMPro; +using UnityEngine; +using UnityEngine.UI; +using Random = UnityEngine.Random; + +namespace Synty.SidekickCharacters.Demo +{ + /// + /// An example script to show how to interact with the Sidekick API in regards to parts at runtime. + /// + public class RuntimePartsDemo : MonoBehaviour + { + private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; + + Dictionary _partIndexDictionary = new Dictionary(); + Dictionary> _availablePartDictionary = new Dictionary>(); + + private DatabaseManager _dbManager; + private SidekickRuntime _sidekickRuntime; + + private Dictionary> _partLibrary; + + public TextMeshProUGUI _loadingText; + + /// + void Start() + { + // Create a new instance of the database manager to access database content. + _dbManager = new DatabaseManager(); + + // Load the base model and material required to create an instance of the Sidekick Runtime API. + GameObject model = Resources.Load("Meshes/SK_BaseModel"); + Material material = Resources.Load("Materials/M_BaseMaterial"); + + _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); + + // Populate the parts list for easy access. + SidekickRuntime.PopulateToolData(_sidekickRuntime); + _partLibrary = _sidekickRuntime.MappedPartDictionary; + + // For this example we are only interested in Upper Body parts, so we filter the list of all parts to only get the ones we want. + List upperBodyParts = PartGroup.UpperBody.GetPartTypes(); + + foreach (CharacterPartType type in upperBodyParts) + { + _availablePartDictionary.Add(type, _partLibrary[type]); + _partIndexDictionary.Add(type, Random.Range(0, _availablePartDictionary[type].Count - 1)); + } + + _loadingText.enabled = false; + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Torso part. + /// + public void ForwardTorso() + { + int index = _partIndexDictionary[CharacterPartType.Torso]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.Torso].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.Torso] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Torso part. + /// + public void BackwardTorso() + { + int index = _partIndexDictionary[CharacterPartType.Torso]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.Torso].Count - 1; + } + + _partIndexDictionary[CharacterPartType.Torso] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the ArmUpperLeft part. + /// + public void ForwardUpperArmLeft() + { + int index = _partIndexDictionary[CharacterPartType.ArmUpperLeft]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.ArmUpperLeft].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.ArmUpperLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the ArmUpperLeft part. + /// + public void BackwardUpperArmLeft() + { + int index = _partIndexDictionary[CharacterPartType.ArmUpperLeft]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.ArmUpperLeft].Count - 1; + } + + _partIndexDictionary[CharacterPartType.ArmUpperLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the ArmUpperRight part. + /// + public void ForwardUpperArmRight() + { + int index = _partIndexDictionary[CharacterPartType.ArmUpperRight]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.ArmUpperRight].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.ArmUpperRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the ArmUpperRight part. + /// + public void BackwardUpperArmRight() + { + int index = _partIndexDictionary[CharacterPartType.ArmUpperRight]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.ArmUpperRight].Count - 1; + } + + _partIndexDictionary[CharacterPartType.ArmUpperRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the ArmLowerLeft part. + /// + public void ForwardLowerArmLeft() + { + int index = _partIndexDictionary[CharacterPartType.ArmLowerLeft]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.ArmLowerLeft].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.ArmLowerLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the ArmLowerLeft part. + /// + public void BackwardLowerArmLeft() + { + int index = _partIndexDictionary[CharacterPartType.ArmLowerLeft]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.ArmLowerLeft].Count - 1; + } + + _partIndexDictionary[CharacterPartType.ArmLowerLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the ArmLowerRight part. + /// + public void ForwardLowerArmRight() + { + int index = _partIndexDictionary[CharacterPartType.ArmLowerRight]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.ArmLowerRight].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.ArmLowerRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the ArmLowerRight part. + /// + public void BackwardLowerArmRight() + { + int index = _partIndexDictionary[CharacterPartType.ArmLowerRight]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.ArmLowerRight].Count - 1; + } + + _partIndexDictionary[CharacterPartType.ArmLowerRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the HandLeft part. + /// + public void ForwardHandLeft() + { + int index = _partIndexDictionary[CharacterPartType.HandLeft]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.HandLeft].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.HandLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the HandLeft part. + /// + public void BackwardHandLeft() + { + int index = _partIndexDictionary[CharacterPartType.HandLeft]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.HandLeft].Count - 1; + } + + _partIndexDictionary[CharacterPartType.HandLeft] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the HandRight part. + /// + public void ForwardHandRight() + { + int index = _partIndexDictionary[CharacterPartType.HandRight]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.HandRight].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.HandRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the HandRight part. + /// + public void BackwardHandRight() + { + int index = _partIndexDictionary[CharacterPartType.HandRight]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.HandRight].Count - 1; + } + + _partIndexDictionary[CharacterPartType.HandRight] = index; + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the AttachmentBack part. + /// + public void ForwardBackAttachment() + { + int index = _partIndexDictionary[CharacterPartType.AttachmentBack]; + index++; + if (index >= _availablePartDictionary[CharacterPartType.AttachmentBack].Count) + { + index = 0; + } + + _partIndexDictionary[CharacterPartType.AttachmentBack] = index; + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the AttachmentBack part. + /// + public void BackwardBackAttachment() + { + int index = _partIndexDictionary[CharacterPartType.AttachmentBack]; + index--; + if (index < 0) + { + index = _availablePartDictionary[CharacterPartType.AttachmentBack].Count - 1; + } + + _partIndexDictionary[CharacterPartType.AttachmentBack] = index; + UpdateModel(); + } + + /// + /// Updates the body size blends based on the slider values. + /// + /// The UI slider to get the values from. + public void UpdateBodySize(Slider slider) + { + // If the slider is greater than 0, then we update the Heavy blend and zero the Skinny. + if (slider.value > 0) + { + _sidekickRuntime.BodySizeHeavyBlendValue = slider.value; + _sidekickRuntime.BodySizeSkinnyBlendValue = 0; + } + // If the slider is 0 or below, we zero the Heavy blend, then we update the Skinny blend. + else + { + _sidekickRuntime.BodySizeHeavyBlendValue = 0; + _sidekickRuntime.BodySizeSkinnyBlendValue = -slider.value; + } + + UpdateModel(); + } + + /// + /// Updates the created character model. + /// + private void UpdateModel() + { + // Create and populate the list of parts to use from the parts list. + List partsToUse = new List(); + + foreach (KeyValuePair> entry in _availablePartDictionary) + { + int index = _partIndexDictionary[entry.Key]; + List parts = entry.Value.Values.ToList(); + GameObject partContainer = null; + if (parts.Count > 0 && index < parts.Count) + { + if (index > parts.Count) + { + index = parts.Count - 1; + } + partContainer = parts[index].GetPartModel(); + } + + if (partContainer != null) + { + partsToUse.Add(partContainer.GetComponentInChildren()); + } + } + + // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. + GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); + + if (character != null) + { + Destroy(character); + } + + // Create a new character using the selected parts using the Sidekicks API. + character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs.meta b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePartsDemo.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs old mode 100644 new mode 100755 index 005c56e0..2bdf230e --- a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs +++ b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs @@ -1,325 +1,325 @@ -using Synty.SidekickCharacters.API; -using Synty.SidekickCharacters.Database; -using Synty.SidekickCharacters.Database.DTO; -using Synty.SidekickCharacters.Enums; -using Synty.SidekickCharacters.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using TMPro; -using UnityEngine; -using Random = UnityEngine.Random; - -namespace Synty.SidekickCharacters.Demo -{ - /// - /// An example script to show how to interact with the Sidekick API in regards to presets at runtime. - /// - public class RuntimePresetDemo : MonoBehaviour - { - private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; - - private Dictionary _availableHeadPresetDictionary = new Dictionary(); - private Dictionary _availableUpperBodyPresetDictionary = new Dictionary(); - private Dictionary _availableLowerBodyPresetDictionary = new Dictionary(); - private List _availableBodyShapes = new List(); - private List _availableColorPresets = new List(); - - private int _currentHeadPresetIndex = 0; - private int _currentUpperBodyPresetIndex = 0; - private int _currentLowerBodyPresetIndex = 0; - private int _currentBodyShapePresetIndex = 0; - private int _currentColorPresetIndex = 0; - - private DatabaseManager _dbManager; - private SidekickRuntime _sidekickRuntime; - - private Dictionary> _partLibrary; - - public TextMeshProUGUI _loadingText; - - /// - void Start() - { - _dbManager = new DatabaseManager(); - - GameObject model = Resources.Load("Meshes/SK_BaseModel"); - Material material = Resources.Load("Materials/M_BaseMaterial"); - - _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); - SidekickRuntime.PopulateToolData(_sidekickRuntime); - _partLibrary = _sidekickRuntime.MappedPartDictionary; - - foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) - { - // only filter head part presets by species - List presets = SidekickPartPreset.GetAllByGroup(_dbManager, partGroup); - List presetNames = new List(); - if (presets.Count < 1) - { - Debug.LogWarning("No parts found for " + partGroup + ". Please add at least 1 Sidekicks content pack."); - continue; - } - - foreach (SidekickPartPreset preset in presets) - { - if (preset.HasAllPartsAvailable(_dbManager)) - { - switch (partGroup) - { - case PartGroup.Head: - _availableHeadPresetDictionary.Add(preset.Name, preset); - break; - - case PartGroup.UpperBody: - _availableUpperBodyPresetDictionary.Add(preset.Name, preset); - break; - - case PartGroup.LowerBody: - _availableLowerBodyPresetDictionary.Add(preset.Name, preset); - break; - } - presetNames.Add(preset.Name); - } - } - } - - _availableBodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); - - // An example of how to retrieve color presets from the database. To retrieve presets for other areas of the material, use the ColorGroup - // enum to retrieve other presets. - _availableColorPresets = SidekickColorPreset.GetAllByColorGroup(_dbManager, ColorGroup.Outfits); - - _currentHeadPresetIndex = Random.Range(0, _availableHeadPresetDictionary.Count - 1); - _currentUpperBodyPresetIndex = Random.Range(0, _availableUpperBodyPresetDictionary.Count - 1); - _currentLowerBodyPresetIndex = Random.Range(0, _availableLowerBodyPresetDictionary.Count - 1); - _currentBodyShapePresetIndex = Random.Range(0, _availableBodyShapes.Count - 1); - _currentColorPresetIndex = Random.Range(0, _availableColorPresets.Count - 1); - - _loadingText.enabled = false; - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Head Preset. - /// - public void ForwardHeadPreset() - { - _currentHeadPresetIndex++; - if (_currentHeadPresetIndex >= _availableHeadPresetDictionary.Count) - { - _currentHeadPresetIndex = 0; - } - - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Head Preset. - /// - public void BackwardHeadPreset() - { - _currentHeadPresetIndex--; - if (_currentHeadPresetIndex < 0) - { - _currentHeadPresetIndex = _availableHeadPresetDictionary.Count - 1; - } - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Upper Body Preset. - /// - public void ForwardUpperBodyPreset() - { - _currentUpperBodyPresetIndex++; - if (_currentUpperBodyPresetIndex >= _availableUpperBodyPresetDictionary.Count) - { - _currentUpperBodyPresetIndex = 0; - } - - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Upper Body Preset. - /// - public void BackwardUpperBodyPreset() - { - _currentUpperBodyPresetIndex--; - if (_currentUpperBodyPresetIndex < 0) - { - _currentUpperBodyPresetIndex = _availableUpperBodyPresetDictionary.Count - 1; - } - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Lower Body Preset. - /// - public void ForwardLowerBodyPreset() - { - _currentLowerBodyPresetIndex++; - if (_currentLowerBodyPresetIndex >= _availableLowerBodyPresetDictionary.Count) - { - _currentLowerBodyPresetIndex = 0; - } - - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Lower Body Preset. - /// - public void BackwardLowerBodyPreset() - { - _currentLowerBodyPresetIndex--; - if (_currentLowerBodyPresetIndex < 0) - { - _currentLowerBodyPresetIndex = _availableLowerBodyPresetDictionary.Count - 1; - } - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Body Shape Preset. - /// - public void ForwardBodyShapePreset() - { - _currentBodyShapePresetIndex++; - if (_currentBodyShapePresetIndex >= _availableBodyShapes.Count) - { - _currentBodyShapePresetIndex = 0; - } - - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Body Shape Preset. - /// - public void BackwardBodyShapePreset() - { - _currentBodyShapePresetIndex--; - if (_currentBodyShapePresetIndex < 0) - { - _currentBodyShapePresetIndex = _availableBodyShapes.Count - 1; - } - - UpdateModel(); - } - - /// - /// Handles the click on the forward button for the Color Preset. - /// - public void ForwardColorPreset() - { - _currentColorPresetIndex++; - if (_currentColorPresetIndex >= _availableColorPresets.Count) - { - _currentColorPresetIndex = 0; - } - - UpdateModel(); - } - - /// - /// Handles the click on the backward button for the Color Preset. - /// - public void BackwardColorPreset() - { - _currentColorPresetIndex--; - if (_currentColorPresetIndex < 0) - { - _currentColorPresetIndex = _availableColorPresets.Count - 1; - } - - UpdateModel(); - } - - /// - /// Updates the created character model. - /// - private void UpdateModel() - { - // If there aren't enough presets, stop trying to update the model. - if (_availableHeadPresetDictionary.Values.Count < 1 - || _availableUpperBodyPresetDictionary.Values.Count < 1 - || _availableLowerBodyPresetDictionary.Values.Count < 1) - { - return; - } - - // Create and populate the list of parts to use from the parts list, and the selected presets. - List presets = new List() - { - _availableHeadPresetDictionary.Values.ToArray()[_currentHeadPresetIndex], - _availableUpperBodyPresetDictionary.Values.ToArray()[_currentUpperBodyPresetIndex], - _availableLowerBodyPresetDictionary.Values.ToArray()[_currentLowerBodyPresetIndex] - }; - - List partsToUse = new List(); - - foreach (SidekickPartPreset preset in presets) - { - List rows = SidekickPartPresetRow.GetAllByPreset(_dbManager, preset); - foreach (SidekickPartPresetRow row in rows) - { - if (!string.IsNullOrEmpty(row.PartName)) - { - CharacterPartType type = Enum.Parse(CharacterPartTypeUtils.GetTypeNameFromShortcode(row.PartType)); - Dictionary partLocationDictionary = _partLibrary[type]; - GameObject selectedPart = partLocationDictionary[row.PartName].GetPartModel(); - SkinnedMeshRenderer selectedMesh = selectedPart.GetComponentInChildren(); - partsToUse.Add(selectedMesh); - } - } - } - - SidekickBodyShapePreset bodyPreset = _availableBodyShapes[_currentBodyShapePresetIndex]; - _sidekickRuntime.BodyTypeBlendValue = bodyPreset.BodyType; - _sidekickRuntime.BodySizeHeavyBlendValue = bodyPreset.BodySize > 0 ? bodyPreset.BodySize : 0; - _sidekickRuntime.BodySizeSkinnyBlendValue = bodyPreset.BodySize < 0 ? -bodyPreset.BodySize : 0; - _sidekickRuntime.MusclesBlendValue = bodyPreset.Musculature; - - List colorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, _availableColorPresets[_currentColorPresetIndex]); - foreach (SidekickColorPresetRow row in colorRows) - { - SidekickColorRow colorRow = SidekickColorRow.CreateFromPresetColorRow(row); - foreach (ColorType property in Enum.GetValues(typeof(ColorType))) - { - _sidekickRuntime.UpdateColor(property, colorRow); - } - } - - // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. - GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); - - if (character != null) - { - Destroy(character); - } - - // Create a new character using the selected parts using the Sidekicks API. - character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); - } - - /// - /// Gets a resource path for using with Resources.Load() from a full path. - /// - /// The full path to get the resource path from. - /// The resource path. - private string GetResourcePath(string fullPath) - { - string directory = Path.GetDirectoryName(fullPath); - int startIndex = directory.IndexOf("Resources") + 10; - directory = directory.Substring(startIndex, directory.Length - startIndex); - return Path.Combine(directory, Path.GetFileNameWithoutExtension(fullPath)); - } - } -} +using Synty.SidekickCharacters.API; +using Synty.SidekickCharacters.Database; +using Synty.SidekickCharacters.Database.DTO; +using Synty.SidekickCharacters.Enums; +using Synty.SidekickCharacters.Utils; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TMPro; +using UnityEngine; +using Random = UnityEngine.Random; + +namespace Synty.SidekickCharacters.Demo +{ + /// + /// An example script to show how to interact with the Sidekick API in regards to presets at runtime. + /// + public class RuntimePresetDemo : MonoBehaviour + { + private readonly string _OUTPUT_MODEL_NAME = "Sidekick Character"; + + private Dictionary _availableHeadPresetDictionary = new Dictionary(); + private Dictionary _availableUpperBodyPresetDictionary = new Dictionary(); + private Dictionary _availableLowerBodyPresetDictionary = new Dictionary(); + private List _availableBodyShapes = new List(); + private List _availableColorPresets = new List(); + + private int _currentHeadPresetIndex = 0; + private int _currentUpperBodyPresetIndex = 0; + private int _currentLowerBodyPresetIndex = 0; + private int _currentBodyShapePresetIndex = 0; + private int _currentColorPresetIndex = 0; + + private DatabaseManager _dbManager; + private SidekickRuntime _sidekickRuntime; + + private Dictionary> _partLibrary; + + public TextMeshProUGUI _loadingText; + + /// + void Start() + { + _dbManager = new DatabaseManager(); + + GameObject model = Resources.Load("Meshes/SK_BaseModel"); + Material material = Resources.Load("Materials/M_BaseMaterial"); + + _sidekickRuntime = new SidekickRuntime(model, material, null, _dbManager); + SidekickRuntime.PopulateToolData(_sidekickRuntime); + _partLibrary = _sidekickRuntime.MappedPartDictionary; + + foreach (PartGroup partGroup in Enum.GetValues(typeof(PartGroup))) + { + // only filter head part presets by species + List presets = SidekickPartPreset.GetAllByGroup(_dbManager, partGroup); + List presetNames = new List(); + if (presets.Count < 1) + { + Debug.LogWarning("No parts found for " + partGroup + ". Please add at least 1 Sidekicks content pack."); + continue; + } + + foreach (SidekickPartPreset preset in presets) + { + if (preset.HasAllPartsAvailable(_dbManager)) + { + switch (partGroup) + { + case PartGroup.Head: + _availableHeadPresetDictionary.Add(preset.Name, preset); + break; + + case PartGroup.UpperBody: + _availableUpperBodyPresetDictionary.Add(preset.Name, preset); + break; + + case PartGroup.LowerBody: + _availableLowerBodyPresetDictionary.Add(preset.Name, preset); + break; + } + presetNames.Add(preset.Name); + } + } + } + + _availableBodyShapes = SidekickBodyShapePreset.GetAll(_dbManager); + + // An example of how to retrieve color presets from the database. To retrieve presets for other areas of the material, use the ColorGroup + // enum to retrieve other presets. + _availableColorPresets = SidekickColorPreset.GetAllByColorGroup(_dbManager, ColorGroup.Outfits); + + _currentHeadPresetIndex = Random.Range(0, _availableHeadPresetDictionary.Count - 1); + _currentUpperBodyPresetIndex = Random.Range(0, _availableUpperBodyPresetDictionary.Count - 1); + _currentLowerBodyPresetIndex = Random.Range(0, _availableLowerBodyPresetDictionary.Count - 1); + _currentBodyShapePresetIndex = Random.Range(0, _availableBodyShapes.Count - 1); + _currentColorPresetIndex = Random.Range(0, _availableColorPresets.Count - 1); + + _loadingText.enabled = false; + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Head Preset. + /// + public void ForwardHeadPreset() + { + _currentHeadPresetIndex++; + if (_currentHeadPresetIndex >= _availableHeadPresetDictionary.Count) + { + _currentHeadPresetIndex = 0; + } + + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Head Preset. + /// + public void BackwardHeadPreset() + { + _currentHeadPresetIndex--; + if (_currentHeadPresetIndex < 0) + { + _currentHeadPresetIndex = _availableHeadPresetDictionary.Count - 1; + } + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Upper Body Preset. + /// + public void ForwardUpperBodyPreset() + { + _currentUpperBodyPresetIndex++; + if (_currentUpperBodyPresetIndex >= _availableUpperBodyPresetDictionary.Count) + { + _currentUpperBodyPresetIndex = 0; + } + + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Upper Body Preset. + /// + public void BackwardUpperBodyPreset() + { + _currentUpperBodyPresetIndex--; + if (_currentUpperBodyPresetIndex < 0) + { + _currentUpperBodyPresetIndex = _availableUpperBodyPresetDictionary.Count - 1; + } + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Lower Body Preset. + /// + public void ForwardLowerBodyPreset() + { + _currentLowerBodyPresetIndex++; + if (_currentLowerBodyPresetIndex >= _availableLowerBodyPresetDictionary.Count) + { + _currentLowerBodyPresetIndex = 0; + } + + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Lower Body Preset. + /// + public void BackwardLowerBodyPreset() + { + _currentLowerBodyPresetIndex--; + if (_currentLowerBodyPresetIndex < 0) + { + _currentLowerBodyPresetIndex = _availableLowerBodyPresetDictionary.Count - 1; + } + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Body Shape Preset. + /// + public void ForwardBodyShapePreset() + { + _currentBodyShapePresetIndex++; + if (_currentBodyShapePresetIndex >= _availableBodyShapes.Count) + { + _currentBodyShapePresetIndex = 0; + } + + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Body Shape Preset. + /// + public void BackwardBodyShapePreset() + { + _currentBodyShapePresetIndex--; + if (_currentBodyShapePresetIndex < 0) + { + _currentBodyShapePresetIndex = _availableBodyShapes.Count - 1; + } + + UpdateModel(); + } + + /// + /// Handles the click on the forward button for the Color Preset. + /// + public void ForwardColorPreset() + { + _currentColorPresetIndex++; + if (_currentColorPresetIndex >= _availableColorPresets.Count) + { + _currentColorPresetIndex = 0; + } + + UpdateModel(); + } + + /// + /// Handles the click on the backward button for the Color Preset. + /// + public void BackwardColorPreset() + { + _currentColorPresetIndex--; + if (_currentColorPresetIndex < 0) + { + _currentColorPresetIndex = _availableColorPresets.Count - 1; + } + + UpdateModel(); + } + + /// + /// Updates the created character model. + /// + private void UpdateModel() + { + // If there aren't enough presets, stop trying to update the model. + if (_availableHeadPresetDictionary.Values.Count < 1 + || _availableUpperBodyPresetDictionary.Values.Count < 1 + || _availableLowerBodyPresetDictionary.Values.Count < 1) + { + return; + } + + // Create and populate the list of parts to use from the parts list, and the selected presets. + List presets = new List() + { + _availableHeadPresetDictionary.Values.ToArray()[_currentHeadPresetIndex], + _availableUpperBodyPresetDictionary.Values.ToArray()[_currentUpperBodyPresetIndex], + _availableLowerBodyPresetDictionary.Values.ToArray()[_currentLowerBodyPresetIndex] + }; + + List partsToUse = new List(); + + foreach (SidekickPartPreset preset in presets) + { + List rows = SidekickPartPresetRow.GetAllByPreset(_dbManager, preset); + foreach (SidekickPartPresetRow row in rows) + { + if (!string.IsNullOrEmpty(row.PartName)) + { + CharacterPartType type = Enum.Parse(CharacterPartTypeUtils.GetTypeNameFromShortcode(row.PartType)); + Dictionary partLocationDictionary = _partLibrary[type]; + GameObject selectedPart = partLocationDictionary[row.PartName].GetPartModel(); + SkinnedMeshRenderer selectedMesh = selectedPart.GetComponentInChildren(); + partsToUse.Add(selectedMesh); + } + } + } + + SidekickBodyShapePreset bodyPreset = _availableBodyShapes[_currentBodyShapePresetIndex]; + _sidekickRuntime.BodyTypeBlendValue = bodyPreset.BodyType; + _sidekickRuntime.BodySizeHeavyBlendValue = bodyPreset.BodySize > 0 ? bodyPreset.BodySize : 0; + _sidekickRuntime.BodySizeSkinnyBlendValue = bodyPreset.BodySize < 0 ? -bodyPreset.BodySize : 0; + _sidekickRuntime.MusclesBlendValue = bodyPreset.Musculature; + + List colorRows = SidekickColorPresetRow.GetAllByPreset(_dbManager, _availableColorPresets[_currentColorPresetIndex]); + foreach (SidekickColorPresetRow row in colorRows) + { + SidekickColorRow colorRow = SidekickColorRow.CreateFromPresetColorRow(row); + foreach (ColorType property in Enum.GetValues(typeof(ColorType))) + { + _sidekickRuntime.UpdateColor(property, colorRow); + } + } + + // Check for an existing copy of the model, if it exists, delete it so that we don't end up with duplicates. + GameObject character = GameObject.Find(_OUTPUT_MODEL_NAME); + + if (character != null) + { + Destroy(character); + } + + // Create a new character using the selected parts using the Sidekicks API. + character = _sidekickRuntime.CreateCharacter(_OUTPUT_MODEL_NAME, partsToUse, false, true); + } + + /// + /// Gets a resource path for using with Resources.Load() from a full path. + /// + /// The full path to get the resource path from. + /// The resource path. + private string GetResourcePath(string fullPath) + { + string directory = Path.GetDirectoryName(fullPath); + int startIndex = directory.IndexOf("Resources") + 10; + directory = directory.Substring(startIndex, directory.Length - startIndex); + return Path.Combine(directory, Path.GetFileNameWithoutExtension(fullPath)); + } + } +} diff --git a/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs.meta b/Assets/External/Models/SidekickCharacters/_Demos/Scripts/RuntimePresetDemo.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs b/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs old mode 100644 new mode 100755 index e3a66f49..b08f0129 --- a/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs +++ b/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs @@ -1,212 +1,212 @@ -#if UNITY_EDITOR - -using UnityEditor; -using UnityEditor.PackageManager; -using UnityEditor.PackageManager.Requests; -using UnityEngine; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -[InitializeOnLoad] -public class SyntyPackageHelper -{ - static AddAndRemoveRequest Request; - - static SyntyPackageHelper() - { - EditorApplication.projectChanged += OnProjectChanged; - } - - //Non async way of quickly checking a package is added to the package manager - public static bool IsPackageInstalled(string packageId) - { - if ( !File.Exists("Packages/manifest.json") ) - return false; - - string jsonText = File.ReadAllText("Packages/manifest.json"); - return jsonText.Contains( packageId ); - } - - private static SyntyPackageHelperConfig[] LoadSyntyPackageHelperConfigs() - { - List configs = new List(); - string[] assetGuids = AssetDatabase.FindAssets("t:SyntyPackageHelperConfig"); - - foreach (string guid in assetGuids) - { - string path = AssetDatabase.GUIDToAssetPath(guid); - SyntyPackageHelperConfig config = AssetDatabase.LoadAssetAtPath(path); - if (config != null) - { - configs.Add(config); - } - } - - Debug.Log($"Loaded {configs.Count} ExamplePackConfig assets"); - - return configs.ToArray(); - } - - static void OnProjectChanged() - { - EditorApplication.projectChanged -= OnProjectChanged; - - ProcessConfigs(LoadSyntyPackageHelperConfigs()); - } - - [MenuItem("Synty/Package Helper/Install Packages")] - public static void InstallShaderGraphPackage() - { - ProcessConfigs(LoadSyntyPackageHelperConfigs(), true); - } - - static List packagesToInstall = new List(); - static int requiredPackageCount = 0; - public static void ProcessConfigs(SyntyPackageHelperConfig[] configs, bool forceInstall = false) - { - if(Request != null) - { - EditorUtility.DisplayDialog( - "Synty Package Helper", - "A package installation process is already underway. Please wait until it finished before trying again.", - "OK"); - return; - } - - packagesToInstall.Clear(); - requiredPackageCount = 0; - - foreach(var config in configs) - { - BuildInstallList(config, forceInstall); - config.hasPromptedUser = true; - } - - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - - if(packagesToInstall.Count == 0) - { - if(requiredPackageCount == 0) - { - if(forceInstall) - { - EditorUtility.DisplayDialog( - "Synty Package Helper", - "All required packages installed.", - "OK"); - } - return; - } - else - { - EditorUtility.DisplayDialog( - "Synty Package Helper", - "No packages to install. You skipped the installation of " + requiredPackageCount + " packages.", - "OK"); - return; - } - } - - InstallPackages(packagesToInstall.ToArray()); - } - - public static void BuildInstallList( SyntyPackageHelperConfig config, bool forceInstall = false ) - { - if(!forceInstall && config.hasPromptedUser) - { - return; - } - - foreach(var packageId in config.packageIds) - { - if(IsPackageInstalled(packageId)) - { - continue; - } - - if(packagesToInstall.Contains(packageId)) - { - continue; - } - - requiredPackageCount++; - bool addPackage = PromptPackageInstall(config.assetPackDisplayName, packageId); - - if(addPackage) - { - packagesToInstall.Add(packageId); - } - } - } - - static bool PromptPackageInstall(string packName, string packageName) - { - return EditorUtility.DisplayDialog( - "Synty Package Helper", - packName + " requires the package " + packageName + " to function correctly. Do you want to install this package now?", - "Install", "Skip"); - } - - static string[] requestPackages = null; - static void InstallPackages(string[] packagesToInstall) - { - if(Request != null) - { - Debug.LogError( "Trying to install a packages when when packages are already being installed." ); - return; - } - - // Add a package to the project - requestPackages = packagesToInstall; - Request = Client.AddAndRemove(packagesToInstall); - EditorApplication.update += Progress; - Progress(); - } - - static void Progress() - { - if(Request == null) - { - EditorApplication.update -= Progress; - } - - if(requestPackages != null) - { - int installed = 0; - foreach(var package in requestPackages) - { - if(IsPackageInstalled(package)) - { - installed++; - } - } - - EditorUtility.DisplayProgressBar("Synty Package Helper", "Installing packages... " + installed + "/" + requestPackages.Length + ".", (float)installed / (float)requestPackages.Length); - } - - if (Request.IsCompleted) - { - EditorUtility.ClearProgressBar(); - if (Request.Status == StatusCode.Success) - { - string message = requestPackages.Length + " packages installed successfully!"; - int skipped = requiredPackageCount - requestPackages.Length; - if(skipped > 0) - { - message = message + "\n" + (requiredPackageCount - requestPackages.Length) + " were skipped."; - } - EditorUtility.DisplayDialog("Synty Package Helper", message, "OK"); - } - else if (Request.Status >= StatusCode.Failure) - { - EditorUtility.DisplayDialog("Synty Package Helper", "There was an error installing the required packages.\n\nError:\n" + Request.Error.message, "OK"); - } - - Request = null; - EditorApplication.update -= Progress; - } - } -} +#if UNITY_EDITOR + +using UnityEditor; +using UnityEditor.PackageManager; +using UnityEditor.PackageManager.Requests; +using UnityEngine; +using System.IO; +using System.Collections.Generic; +using System.Linq; + +[InitializeOnLoad] +public class SyntyPackageHelper +{ + static AddAndRemoveRequest Request; + + static SyntyPackageHelper() + { + EditorApplication.projectChanged += OnProjectChanged; + } + + //Non async way of quickly checking a package is added to the package manager + public static bool IsPackageInstalled(string packageId) + { + if ( !File.Exists("Packages/manifest.json") ) + return false; + + string jsonText = File.ReadAllText("Packages/manifest.json"); + return jsonText.Contains( packageId ); + } + + private static SyntyPackageHelperConfig[] LoadSyntyPackageHelperConfigs() + { + List configs = new List(); + string[] assetGuids = AssetDatabase.FindAssets("t:SyntyPackageHelperConfig"); + + foreach (string guid in assetGuids) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + SyntyPackageHelperConfig config = AssetDatabase.LoadAssetAtPath(path); + if (config != null) + { + configs.Add(config); + } + } + + Debug.Log($"Loaded {configs.Count} ExamplePackConfig assets"); + + return configs.ToArray(); + } + + static void OnProjectChanged() + { + EditorApplication.projectChanged -= OnProjectChanged; + + ProcessConfigs(LoadSyntyPackageHelperConfigs()); + } + + [MenuItem("Synty/Package Helper/Install Packages")] + public static void InstallShaderGraphPackage() + { + ProcessConfigs(LoadSyntyPackageHelperConfigs(), true); + } + + static List packagesToInstall = new List(); + static int requiredPackageCount = 0; + public static void ProcessConfigs(SyntyPackageHelperConfig[] configs, bool forceInstall = false) + { + if(Request != null) + { + EditorUtility.DisplayDialog( + "Synty Package Helper", + "A package installation process is already underway. Please wait until it finished before trying again.", + "OK"); + return; + } + + packagesToInstall.Clear(); + requiredPackageCount = 0; + + foreach(var config in configs) + { + BuildInstallList(config, forceInstall); + config.hasPromptedUser = true; + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + if(packagesToInstall.Count == 0) + { + if(requiredPackageCount == 0) + { + if(forceInstall) + { + EditorUtility.DisplayDialog( + "Synty Package Helper", + "All required packages installed.", + "OK"); + } + return; + } + else + { + EditorUtility.DisplayDialog( + "Synty Package Helper", + "No packages to install. You skipped the installation of " + requiredPackageCount + " packages.", + "OK"); + return; + } + } + + InstallPackages(packagesToInstall.ToArray()); + } + + public static void BuildInstallList( SyntyPackageHelperConfig config, bool forceInstall = false ) + { + if(!forceInstall && config.hasPromptedUser) + { + return; + } + + foreach(var packageId in config.packageIds) + { + if(IsPackageInstalled(packageId)) + { + continue; + } + + if(packagesToInstall.Contains(packageId)) + { + continue; + } + + requiredPackageCount++; + bool addPackage = PromptPackageInstall(config.assetPackDisplayName, packageId); + + if(addPackage) + { + packagesToInstall.Add(packageId); + } + } + } + + static bool PromptPackageInstall(string packName, string packageName) + { + return EditorUtility.DisplayDialog( + "Synty Package Helper", + packName + " requires the package " + packageName + " to function correctly. Do you want to install this package now?", + "Install", "Skip"); + } + + static string[] requestPackages = null; + static void InstallPackages(string[] packagesToInstall) + { + if(Request != null) + { + Debug.LogError( "Trying to install a packages when when packages are already being installed." ); + return; + } + + // Add a package to the project + requestPackages = packagesToInstall; + Request = Client.AddAndRemove(packagesToInstall); + EditorApplication.update += Progress; + Progress(); + } + + static void Progress() + { + if(Request == null) + { + EditorApplication.update -= Progress; + } + + if(requestPackages != null) + { + int installed = 0; + foreach(var package in requestPackages) + { + if(IsPackageInstalled(package)) + { + installed++; + } + } + + EditorUtility.DisplayProgressBar("Synty Package Helper", "Installing packages... " + installed + "/" + requestPackages.Length + ".", (float)installed / (float)requestPackages.Length); + } + + if (Request.IsCompleted) + { + EditorUtility.ClearProgressBar(); + if (Request.Status == StatusCode.Success) + { + string message = requestPackages.Length + " packages installed successfully!"; + int skipped = requiredPackageCount - requestPackages.Length; + if(skipped > 0) + { + message = message + "\n" + (requiredPackageCount - requestPackages.Length) + " were skipped."; + } + EditorUtility.DisplayDialog("Synty Package Helper", message, "OK"); + } + else if (Request.Status >= StatusCode.Failure) + { + EditorUtility.DisplayDialog("Synty Package Helper", "There was an error installing the required packages.\n\nError:\n" + Request.Error.message, "OK"); + } + + Request = null; + EditorApplication.update -= Progress; + } + } +} #endif \ No newline at end of file diff --git a/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs.meta b/Assets/External/Tools/SyntyPackageHelper/Editor/SyntyPackageHelper.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs b/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs old mode 100644 new mode 100755 index 1b57fcc5..8bbac5a0 --- a/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs +++ b/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs @@ -1,466 +1,466 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -#if UNITY_2021_2_OR_NEWER -using UnityEditor.SceneManagement; -#else -using UnityEditor.Experimental.SceneManagement; -#endif - -namespace Synty.Tools.SyntyPropBoneTool -{ - /// - /// Utility class to help configure many characters with prop bone binders at once. - /// - public static class PropBoneBinderEditorUtil - { - // Path where the prop bone binder tool stores the default config file. - private const string CONFIG_ASSET_NAME_DEFAULT = "Animation_PropBoneBindingConfig_Default.asset"; - private const string CONFIG_ASSET_PATH_DEFAULT = FOLDER_PATH_DEFAULT + CONFIG_ASSET_NAME_DEFAULT; - - // Folder path where the prop bone binder tool stores config files by default. - private const string FOLDER_PATH_DEFAULT = "Assets/Synty/Tools/SyntyPropBoneTool/Configs/"; - - /// - /// Generates a file name based on the targetRigName and the defined config folder path. - /// - /// A string that can be used as a file path for a config asset. This path is not gauranteed to be unique. - private static string GenerateNewConfigFileName(string targetRigName) - { - PropBoneConfigAsset defaultAsset = GetDefaultConfigAsset(); - - string targetFileName = targetRigName + "_PropBoneBindingConfig.asset"; - string targetPath = defaultAsset.path.Replace(CONFIG_ASSET_NAME_DEFAULT, targetFileName); - - return targetPath; - } - - /// - /// Class used to help manage config assets in the AssetDatabase. - /// - private class PropBoneConfigAsset - { - public bool savedInAssetDatabase; // is true when loaded from or saved to the AssetDatabase - public PropBoneConfig config; - public string path; - } - - /// - /// Returns true if the given PropBneBinder is part of a prefab asset. - /// - /// The PropBoneBinder to test if it is part of a prefab asset. - /// A bool. True when the binder is part of a prefab asset. - public static bool IsPrefabAsset(PropBoneBinder binder) - { - return PrefabUtility.IsPartOfPrefabAsset(binder); - } - - /// - /// Attemps to automatically configure all given PropBoneBinders. - /// - /// All the PropBoneBinder components to setup. - public static void AutomaticSetup(List binders) - { - SetupAnimatorReferences(binders); - SetupPropBoneConfigs(binders); - CreatePropBones(binders); - BindPropBones(binders); - } - - /// - /// Attemps to reset all given PropBoneBinders. - /// - /// All the PropBoneBinder components to reset. - public static void AutomaticReset(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - binders[i].Reset(); - } - } - - /// - /// Attempts to find the first PropBoneConfigAsset with the given fileName. - /// - /// The file name of the config to find. - /// The first found PropBoneConfigAsset with file name matching the given fileName or null if none is found. - private static PropBoneConfigAsset FindFirstConfig(string fileName) - { - string[] guids = AssetDatabase.FindAssets("t:PropBoneConfig"); - for (int i = 0; i < guids.Length; ++i) - { - string path = AssetDatabase.GUIDToAssetPath(guids[i]); - if (path.Contains(fileName)) - { - return LoadPropBoneConfig(path); - } - } - - return null; - } - - /// - /// Attempts to load the default PropBoneConfigAsset or if one is not found creates a new default PropBoneConfigAsset. - /// - /// A PropBoneConfigAsset that contains the default settings to use for PropBoneBingings. - private static PropBoneConfigAsset GetDefaultConfigAsset() - { - PropBoneConfigAsset defaultConfigAsset = FindFirstConfig(CONFIG_ASSET_NAME_DEFAULT); - - if (defaultConfigAsset == null) - { - PropBoneConfig defaultConfig = CreatePropBoneConfig(PropBoneDefinitionPresets.PolygonBoneDefinition); - defaultConfigAsset = CreatePropBoneConfigAsset(defaultConfig, CONFIG_ASSET_PATH_DEFAULT); - SavePropBoneAssetToProject(defaultConfigAsset); - } - - return defaultConfigAsset; - } - - /// - /// Attempts to load the default PropBoneConfig or if one is not found creates a new default PropBoneConfig. - /// - /// A PropBoneConfig that contains the default settings to use for PropBoneBingings. - private static PropBoneConfig GetDefaultConfig() - { - return GetDefaultConfigAsset().config; - } - - /// - /// Attempts to find and load a config that matched the given sourceRig and targetRig. - /// - /// The source rig to match when finding the PropBoneConfig. - /// The target rig to match when finding the PropBoneConfig. - /// A PropBoneConfig that matches the sourceRig and targetRig or returns the default PropBoneConfig if a match is not found. - public static PropBoneConfig FindFirstMatchingConfig(GameObject sourceRig, GameObject targetRig) - { - string[] guids = AssetDatabase.FindAssets("t:PropBoneConfig"); - for (int i = 0; i < guids.Length; ++i) - { - string path = AssetDatabase.GUIDToAssetPath(guids[i]); - PropBoneConfig config = LoadPropBoneConfig(path).config; - if (config != null) - { - if (config.targetRig == targetRig && config.sourceRig == sourceRig) - { - return config; - } - } - } - - return GetDefaultConfig(); - } - - /// - /// Attempts to find matching PropBoneConfigs or creates a new ones and assigns them to all the given PropBoneBinders. - /// - /// All the PropBoneBinder components to setup. - public static void SetupPropBoneConfigs(List binders) - { - PropBoneConfig defaultConfig = GetDefaultConfig(); - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - if (binders[i].propBoneConfig == null) - { - GameObject targetRig = null; - if (binders[i].animator != null) - { - targetRig = binders[i].animator.gameObject; - } - - if (PrefabUtility.IsPartOfPrefabInstance(targetRig)) - { - string path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(targetRig); - if (path != null) - { - targetRig = AssetDatabase.LoadAssetAtPath(path); - } - } - else if (PrefabStageUtility.GetCurrentPrefabStage() != null) - { - string path = PrefabStageUtility.GetCurrentPrefabStage().assetPath; - if (path != null) - { - targetRig = AssetDatabase.LoadAssetAtPath(path); - } - } - - if (targetRig == null) - { - Debug.LogError($"Cannot locate target model asset for binder: {binders[i].gameObject.name}. You will need to set up the prop bone config for this character manually and then run setup again.", binders[i].gameObject); - continue; - } - - PropBoneConfig targetConfig = FindFirstMatchingConfig(defaultConfig.sourceRig, targetRig); - - if (targetConfig.targetRig != targetRig) - { - PropBoneConfig newConfig = ClonePropBoneConfig(defaultConfig); - newConfig.targetRig = targetRig; - newConfig.CalculateOffsetValues(); - Debug.Log($"Set up {targetRig.name} as target rig for {binders[i].gameObject.name}", targetRig); - PropBoneConfigAsset configAsset = CreatePropBoneConfigAsset(newConfig, GenerateNewConfigFileName(targetRig.name)); - SavePropBoneAssetToProject(configAsset); - targetConfig = configAsset.config; - } - - binders[i].propBoneConfig = targetConfig; - } - } - } - - /// - /// Creates new PropBoneConfig files based on the ones assigned to the given binders or bases new configs on the default PropBoneConfig if none are assigned. - /// - /// All the PropBoneBinder components to create new bone configs for. - public static void CreateNewBoneConfigs(List binders) - { - PropBoneConfig defaultConfig = GetDefaultConfig(); - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - PropBoneConfig newConfigBase = binders[i].propBoneConfig != null ? binders[i].propBoneConfig : defaultConfig; - - PropBoneConfig newConfig = ClonePropBoneConfig(newConfigBase); - PropBoneConfigAsset configAsset = CreatePropBoneConfigAsset(newConfig, GenerateNewConfigFileName(binders[i].name)); - SavePropBoneAssetToProject(configAsset); - binders[i].propBoneConfig = configAsset.config; - } - } - - /// - /// Attempts to assign the animator referenec on all the given binders. - /// - /// All the PropBoneBinder components to setup the animator references of. - public static void SetupAnimatorReferences(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - PropBoneBinder binder = binders[i]; - if (binder != null) - { - binder.SetupAnimatorReference(); - } - } - } - - /// - /// Attempts to create all the prop bones for all the given binders. - /// - /// All the PropBoneBinder components to create prop bones for. - public static void CreatePropBones(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - PropBoneBinder binder = binders[i]; - if (binder != null) - { - binder.CreatePropBones(); - } - } - } - - /// - /// Attempts to clear all the prop bone bindings for all the given binders. - /// - /// All the PropBoneBinder components to create prop bones bindings for. - public static void ClearPropBoneBindings(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - PropBoneBinder binder = binders[i]; - if (binder != null) - { - binder.ClearPropBoneBindings(); - } - } - } - - /// - /// Attempts to destroy all the prop bones on all the given bindings. - /// - /// All the PropBoneBinder components to destroy prop bones. - public static void DestroyPropBones(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - PropBoneBinder binder = binders[i]; - if (binder != null) - { - binder.DestroyPropBones(); - } - } - } - - /// - /// Attempts to bind all the prop bones on all the given bindings. - /// - /// All the PropBoneBinder components to bind prop bones. - public static void BindPropBones(List binders) - { - for (int i = 0; i < binders.Count; ++i) - { - if (IsPrefabAsset(binders[i])) - { - Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); - continue; - } - - PropBoneBinder binder = binders[i]; - if (binder != null) - { - binder.BindPropBones(); - binder.UpdateBones(); - } - } - } - - /// - /// Loads a PropBoneConfig file at the given path. - /// - /// The path to load the PropBoneConfig. - /// A PropBoneConfigAsset found at the given path or null if no asset of type PropBoneConfigAsset exists at that path. - private static PropBoneConfigAsset LoadPropBoneConfig(string path) - { - PropBoneConfig config = AssetDatabase.LoadAssetAtPath(path); - if (config != null) - { - PropBoneConfigAsset configAsset = new PropBoneConfigAsset(); - configAsset.config = config; - configAsset.savedInAssetDatabase = true; - configAsset.path = path; - return configAsset; - } - - return null; - } - - /// - /// Creates a new PropBoneConfig based on the given source config. - /// - /// The PropBoneConfig to clone. - /// A new PropBoneConfig clones from the source PropBoneConfig. - private static PropBoneConfig ClonePropBoneConfig(PropBoneConfig source) - { - PropBoneConfig newPropBoneConfig = ScriptableObject.CreateInstance(); - newPropBoneConfig.propBoneDefinitions = source.propBoneDefinitions; - newPropBoneConfig.sourceRig = source.sourceRig; - newPropBoneConfig.targetRig = source.targetRig; - return newPropBoneConfig; - } - - /// - /// Creates a new PropBoneConfig containing the given PropBoneDefinitions. - /// - /// The prop bone definitions to be used by the new PropBoneConfig. - /// A PropBoneConfig with the given PropBoneDefinitions. - private static PropBoneConfig CreatePropBoneConfig(PropBoneDefinition[] definitions) - { - PropBoneConfig newPropBoneConfig = ScriptableObject.CreateInstance(); - newPropBoneConfig.propBoneDefinitions = definitions; - return newPropBoneConfig; - } - - /// - /// Creates a new PropBoneConfigAsset of the given PropBoneConfig and with the given path. - /// - /// The config of the config asset. - /// The desired path for the config asset. The path used ma. - /// When true the path is altered as necessary to ensure it is unique. - /// A new PropBoneConfigAsset based on the given parameters. - private static PropBoneConfigAsset CreatePropBoneConfigAsset(PropBoneConfig config, string path, bool ensureUniquePath = true) - { - PropBoneConfigAsset result = new PropBoneConfigAsset(); - result.savedInAssetDatabase = false; - result.path = path; - if (ensureUniquePath) - { - result.path = AssetDatabase.GenerateUniqueAssetPath(result.path); - if (string.IsNullOrEmpty(result.path)) - { - // AssetDatabase.GenerateUniqueAssetPath(result.path); returns an empty path if the folder structure in the file path does not exist. - result.path = path; - } - } - result.config = config; - return result; - } - - /// - /// Saves the given PropBoneConfigAsset to the AssetDatabase. - /// - /// The PropBoneConfigAsset to save. - private static void SavePropBoneAssetToProject(PropBoneConfigAsset asset) - { - EnsureFolderExists(asset.path); - - AssetDatabase.CreateAsset(asset.config, asset.path); - AssetDatabase.SaveAssets(); - asset.savedInAssetDatabase = true; - Debug.Log($"Successfully created prop bone config asset at path: {asset.path}.", asset.config); - } - - /// - /// Checks if the folder at the given path exists, if not then the folder and all parent folders in the hierarchy are created. - /// - /// The folder path. - private static void EnsureFolderExists(string path) - { - string[] split = path.Split('/'); - string parentPath = split[0]; - for (int i = 1; i < split.Length - 1; ++i) - { - string head = split[i]; - if (!AssetDatabase.IsValidFolder(parentPath + "/" + head)) - { - AssetDatabase.CreateFolder(parentPath, head); - } - - parentPath += "/" + head; - } - } - - } +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +#if UNITY_2021_2_OR_NEWER +using UnityEditor.SceneManagement; +#else +using UnityEditor.Experimental.SceneManagement; +#endif + +namespace Synty.Tools.SyntyPropBoneTool +{ + /// + /// Utility class to help configure many characters with prop bone binders at once. + /// + public static class PropBoneBinderEditorUtil + { + // Path where the prop bone binder tool stores the default config file. + private const string CONFIG_ASSET_NAME_DEFAULT = "Animation_PropBoneBindingConfig_Default.asset"; + private const string CONFIG_ASSET_PATH_DEFAULT = FOLDER_PATH_DEFAULT + CONFIG_ASSET_NAME_DEFAULT; + + // Folder path where the prop bone binder tool stores config files by default. + private const string FOLDER_PATH_DEFAULT = "Assets/Synty/Tools/SyntyPropBoneTool/Configs/"; + + /// + /// Generates a file name based on the targetRigName and the defined config folder path. + /// + /// A string that can be used as a file path for a config asset. This path is not gauranteed to be unique. + private static string GenerateNewConfigFileName(string targetRigName) + { + PropBoneConfigAsset defaultAsset = GetDefaultConfigAsset(); + + string targetFileName = targetRigName + "_PropBoneBindingConfig.asset"; + string targetPath = defaultAsset.path.Replace(CONFIG_ASSET_NAME_DEFAULT, targetFileName); + + return targetPath; + } + + /// + /// Class used to help manage config assets in the AssetDatabase. + /// + private class PropBoneConfigAsset + { + public bool savedInAssetDatabase; // is true when loaded from or saved to the AssetDatabase + public PropBoneConfig config; + public string path; + } + + /// + /// Returns true if the given PropBneBinder is part of a prefab asset. + /// + /// The PropBoneBinder to test if it is part of a prefab asset. + /// A bool. True when the binder is part of a prefab asset. + public static bool IsPrefabAsset(PropBoneBinder binder) + { + return PrefabUtility.IsPartOfPrefabAsset(binder); + } + + /// + /// Attemps to automatically configure all given PropBoneBinders. + /// + /// All the PropBoneBinder components to setup. + public static void AutomaticSetup(List binders) + { + SetupAnimatorReferences(binders); + SetupPropBoneConfigs(binders); + CreatePropBones(binders); + BindPropBones(binders); + } + + /// + /// Attemps to reset all given PropBoneBinders. + /// + /// All the PropBoneBinder components to reset. + public static void AutomaticReset(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + binders[i].Reset(); + } + } + + /// + /// Attempts to find the first PropBoneConfigAsset with the given fileName. + /// + /// The file name of the config to find. + /// The first found PropBoneConfigAsset with file name matching the given fileName or null if none is found. + private static PropBoneConfigAsset FindFirstConfig(string fileName) + { + string[] guids = AssetDatabase.FindAssets("t:PropBoneConfig"); + for (int i = 0; i < guids.Length; ++i) + { + string path = AssetDatabase.GUIDToAssetPath(guids[i]); + if (path.Contains(fileName)) + { + return LoadPropBoneConfig(path); + } + } + + return null; + } + + /// + /// Attempts to load the default PropBoneConfigAsset or if one is not found creates a new default PropBoneConfigAsset. + /// + /// A PropBoneConfigAsset that contains the default settings to use for PropBoneBingings. + private static PropBoneConfigAsset GetDefaultConfigAsset() + { + PropBoneConfigAsset defaultConfigAsset = FindFirstConfig(CONFIG_ASSET_NAME_DEFAULT); + + if (defaultConfigAsset == null) + { + PropBoneConfig defaultConfig = CreatePropBoneConfig(PropBoneDefinitionPresets.PolygonBoneDefinition); + defaultConfigAsset = CreatePropBoneConfigAsset(defaultConfig, CONFIG_ASSET_PATH_DEFAULT); + SavePropBoneAssetToProject(defaultConfigAsset); + } + + return defaultConfigAsset; + } + + /// + /// Attempts to load the default PropBoneConfig or if one is not found creates a new default PropBoneConfig. + /// + /// A PropBoneConfig that contains the default settings to use for PropBoneBingings. + private static PropBoneConfig GetDefaultConfig() + { + return GetDefaultConfigAsset().config; + } + + /// + /// Attempts to find and load a config that matched the given sourceRig and targetRig. + /// + /// The source rig to match when finding the PropBoneConfig. + /// The target rig to match when finding the PropBoneConfig. + /// A PropBoneConfig that matches the sourceRig and targetRig or returns the default PropBoneConfig if a match is not found. + public static PropBoneConfig FindFirstMatchingConfig(GameObject sourceRig, GameObject targetRig) + { + string[] guids = AssetDatabase.FindAssets("t:PropBoneConfig"); + for (int i = 0; i < guids.Length; ++i) + { + string path = AssetDatabase.GUIDToAssetPath(guids[i]); + PropBoneConfig config = LoadPropBoneConfig(path).config; + if (config != null) + { + if (config.targetRig == targetRig && config.sourceRig == sourceRig) + { + return config; + } + } + } + + return GetDefaultConfig(); + } + + /// + /// Attempts to find matching PropBoneConfigs or creates a new ones and assigns them to all the given PropBoneBinders. + /// + /// All the PropBoneBinder components to setup. + public static void SetupPropBoneConfigs(List binders) + { + PropBoneConfig defaultConfig = GetDefaultConfig(); + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + if (binders[i].propBoneConfig == null) + { + GameObject targetRig = null; + if (binders[i].animator != null) + { + targetRig = binders[i].animator.gameObject; + } + + if (PrefabUtility.IsPartOfPrefabInstance(targetRig)) + { + string path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(targetRig); + if (path != null) + { + targetRig = AssetDatabase.LoadAssetAtPath(path); + } + } + else if (PrefabStageUtility.GetCurrentPrefabStage() != null) + { + string path = PrefabStageUtility.GetCurrentPrefabStage().assetPath; + if (path != null) + { + targetRig = AssetDatabase.LoadAssetAtPath(path); + } + } + + if (targetRig == null) + { + Debug.LogError($"Cannot locate target model asset for binder: {binders[i].gameObject.name}. You will need to set up the prop bone config for this character manually and then run setup again.", binders[i].gameObject); + continue; + } + + PropBoneConfig targetConfig = FindFirstMatchingConfig(defaultConfig.sourceRig, targetRig); + + if (targetConfig.targetRig != targetRig) + { + PropBoneConfig newConfig = ClonePropBoneConfig(defaultConfig); + newConfig.targetRig = targetRig; + newConfig.CalculateOffsetValues(); + Debug.Log($"Set up {targetRig.name} as target rig for {binders[i].gameObject.name}", targetRig); + PropBoneConfigAsset configAsset = CreatePropBoneConfigAsset(newConfig, GenerateNewConfigFileName(targetRig.name)); + SavePropBoneAssetToProject(configAsset); + targetConfig = configAsset.config; + } + + binders[i].propBoneConfig = targetConfig; + } + } + } + + /// + /// Creates new PropBoneConfig files based on the ones assigned to the given binders or bases new configs on the default PropBoneConfig if none are assigned. + /// + /// All the PropBoneBinder components to create new bone configs for. + public static void CreateNewBoneConfigs(List binders) + { + PropBoneConfig defaultConfig = GetDefaultConfig(); + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + PropBoneConfig newConfigBase = binders[i].propBoneConfig != null ? binders[i].propBoneConfig : defaultConfig; + + PropBoneConfig newConfig = ClonePropBoneConfig(newConfigBase); + PropBoneConfigAsset configAsset = CreatePropBoneConfigAsset(newConfig, GenerateNewConfigFileName(binders[i].name)); + SavePropBoneAssetToProject(configAsset); + binders[i].propBoneConfig = configAsset.config; + } + } + + /// + /// Attempts to assign the animator referenec on all the given binders. + /// + /// All the PropBoneBinder components to setup the animator references of. + public static void SetupAnimatorReferences(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + PropBoneBinder binder = binders[i]; + if (binder != null) + { + binder.SetupAnimatorReference(); + } + } + } + + /// + /// Attempts to create all the prop bones for all the given binders. + /// + /// All the PropBoneBinder components to create prop bones for. + public static void CreatePropBones(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + PropBoneBinder binder = binders[i]; + if (binder != null) + { + binder.CreatePropBones(); + } + } + } + + /// + /// Attempts to clear all the prop bone bindings for all the given binders. + /// + /// All the PropBoneBinder components to create prop bones bindings for. + public static void ClearPropBoneBindings(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + PropBoneBinder binder = binders[i]; + if (binder != null) + { + binder.ClearPropBoneBindings(); + } + } + } + + /// + /// Attempts to destroy all the prop bones on all the given bindings. + /// + /// All the PropBoneBinder components to destroy prop bones. + public static void DestroyPropBones(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + PropBoneBinder binder = binders[i]; + if (binder != null) + { + binder.DestroyPropBones(); + } + } + } + + /// + /// Attempts to bind all the prop bones on all the given bindings. + /// + /// All the PropBoneBinder components to bind prop bones. + public static void BindPropBones(List binders) + { + for (int i = 0; i < binders.Count; ++i) + { + if (IsPrefabAsset(binders[i])) + { + Debug.LogWarning($"Cannot edit prefab asset {binders[i].gameObject.name}. Open the asset in prefab edit mode or create a scene instance and try again.", binders[i].gameObject); + continue; + } + + PropBoneBinder binder = binders[i]; + if (binder != null) + { + binder.BindPropBones(); + binder.UpdateBones(); + } + } + } + + /// + /// Loads a PropBoneConfig file at the given path. + /// + /// The path to load the PropBoneConfig. + /// A PropBoneConfigAsset found at the given path or null if no asset of type PropBoneConfigAsset exists at that path. + private static PropBoneConfigAsset LoadPropBoneConfig(string path) + { + PropBoneConfig config = AssetDatabase.LoadAssetAtPath(path); + if (config != null) + { + PropBoneConfigAsset configAsset = new PropBoneConfigAsset(); + configAsset.config = config; + configAsset.savedInAssetDatabase = true; + configAsset.path = path; + return configAsset; + } + + return null; + } + + /// + /// Creates a new PropBoneConfig based on the given source config. + /// + /// The PropBoneConfig to clone. + /// A new PropBoneConfig clones from the source PropBoneConfig. + private static PropBoneConfig ClonePropBoneConfig(PropBoneConfig source) + { + PropBoneConfig newPropBoneConfig = ScriptableObject.CreateInstance(); + newPropBoneConfig.propBoneDefinitions = source.propBoneDefinitions; + newPropBoneConfig.sourceRig = source.sourceRig; + newPropBoneConfig.targetRig = source.targetRig; + return newPropBoneConfig; + } + + /// + /// Creates a new PropBoneConfig containing the given PropBoneDefinitions. + /// + /// The prop bone definitions to be used by the new PropBoneConfig. + /// A PropBoneConfig with the given PropBoneDefinitions. + private static PropBoneConfig CreatePropBoneConfig(PropBoneDefinition[] definitions) + { + PropBoneConfig newPropBoneConfig = ScriptableObject.CreateInstance(); + newPropBoneConfig.propBoneDefinitions = definitions; + return newPropBoneConfig; + } + + /// + /// Creates a new PropBoneConfigAsset of the given PropBoneConfig and with the given path. + /// + /// The config of the config asset. + /// The desired path for the config asset. The path used ma. + /// When true the path is altered as necessary to ensure it is unique. + /// A new PropBoneConfigAsset based on the given parameters. + private static PropBoneConfigAsset CreatePropBoneConfigAsset(PropBoneConfig config, string path, bool ensureUniquePath = true) + { + PropBoneConfigAsset result = new PropBoneConfigAsset(); + result.savedInAssetDatabase = false; + result.path = path; + if (ensureUniquePath) + { + result.path = AssetDatabase.GenerateUniqueAssetPath(result.path); + if (string.IsNullOrEmpty(result.path)) + { + // AssetDatabase.GenerateUniqueAssetPath(result.path); returns an empty path if the folder structure in the file path does not exist. + result.path = path; + } + } + result.config = config; + return result; + } + + /// + /// Saves the given PropBoneConfigAsset to the AssetDatabase. + /// + /// The PropBoneConfigAsset to save. + private static void SavePropBoneAssetToProject(PropBoneConfigAsset asset) + { + EnsureFolderExists(asset.path); + + AssetDatabase.CreateAsset(asset.config, asset.path); + AssetDatabase.SaveAssets(); + asset.savedInAssetDatabase = true; + Debug.Log($"Successfully created prop bone config asset at path: {asset.path}.", asset.config); + } + + /// + /// Checks if the folder at the given path exists, if not then the folder and all parent folders in the hierarchy are created. + /// + /// The folder path. + private static void EnsureFolderExists(string path) + { + string[] split = path.Split('/'); + string parentPath = split[0]; + for (int i = 1; i < split.Length - 1; ++i) + { + string head = split[i]; + if (!AssetDatabase.IsValidFolder(parentPath + "/" + head)) + { + AssetDatabase.CreateFolder(parentPath, head); + } + + parentPath += "/" + head; + } + } + + } } \ No newline at end of file diff --git a/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs.meta b/Assets/External/Tools/SyntyPropBoneTool/Editor/Utils/PropBoneToolEditorUtil.cs.meta old mode 100644 new mode 100755 diff --git a/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs b/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs old mode 100644 new mode 100755 index 4c78698d..3ef9f2e0 --- a/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs +++ b/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs @@ -1,486 +1,486 @@ -// Copyright (c) 2024 Synty Studios Limited. All rights reserved. -// -// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) -// available at: https://syntystore.com/pages/end-user-licence-agreement -// -// For additional details, see the LICENSE.MD file bundled with this software. - -#if UNITY_EDITOR -using UnityEditor; -#endif -using UnityEngine; -using System.Collections.Generic; - -namespace Synty.Tools.SyntyPropBoneTool -{ - /// - /// The PropBoneBinder is responsible for creating, managing and updating the prop bones at runtime. - /// Only one of these components is needed per character. It will manage all prop bones defined in the propBoneConfig. - /// - [ExecuteInEditMode] - public class PropBoneBinder : MonoBehaviour - { - [Tooltip("Reference to the animator for this character")] - public Animator animator; - - [Tooltip("Configures how the bones are set up on the rig.")] - public PropBoneConfig propBoneConfig; - - [Tooltip("Determins when this script will update the transforms. For best results run this script later than the animator.")] - public UpdateType updateType = UpdateType.LateUpdate; - public bool updateInEditMode = true; - - [Tooltip("Rebinds all the bones on awake. Useful if your rigs change often, saves needing to rebind them at edit time.")] - public bool rebindOnAwake = false; - - [Space] - [Tooltip("Bindings and offset values applied at runtime.")] - [SerializeField] - private List _propBoneBindings = new List(); - - /// - /// Returns true if the PropBoneBinder is configured correctly. - /// - public bool IsConfigured => AreReferencesConfigured() && AreBindingsConfigured(); - - /// - /// Returns true if the reference variables are configured correctly. - /// - /// A bool that is true when the reference variables are correctly configured. - public bool AreReferencesConfigured() - { - return animator != null && propBoneConfig != null; - } - - /// - /// Returns true if the hierarchy is configured correctly according to the propBoneConfig. - /// - /// A bool that is true when the hierarchy is correctly configured. - public bool IsPropBoneHierarchyConfigured() - { - for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) - { - Transform propBone = TransformUtil.SearchHierarchy(transform, propBoneConfig.propBoneDefinitions[i].boneName); - Transform propBoneSocket = TransformUtil.SearchHierarchy(transform, propBoneConfig.propBoneDefinitions[i].socketName); - if (propBone == null || propBoneSocket == null || propBone.parent == null || propBone.parent.name != propBoneConfig.propBoneDefinitions[i].parentBoneName) - { - return false; - } - } - - return true; - } - - /// - /// Returns true if all the prop bone bindings are configured correctly according to the propBoneConfig. - /// - /// A bool that is true when all the prop bone bindings are correctly configured. - public bool AreBindingsConfigured() - { - if (_propBoneBindings.Count != propBoneConfig.propBoneDefinitions.Length) - { - return false; - } - - for (int i = 0; i < _propBoneBindings.Count; ++i) - { - if (!_propBoneBindings[i].IsMatch(propBoneConfig.propBoneDefinitions[i])) - { - return false; - } - } - - return true; - } - - /// - /// Rebinds the PropBoneBindings on awake if rebindOnAwake is set to true. - /// - private void Awake() - { - if (rebindOnAwake) - { - BindPropBones(); - } - } - - /// - /// Attempts to create a PropBoneBinding in accordance to the giving PropBoneDefinition. - /// - /// The definition of the prop bone to be created. - /// A PropBoneBinding that is the new binding or null if the binding failed to be created. - private PropBoneBinding CreateBoneBinding(PropBoneDefinition boneDefinition) - { - Transform parent = TransformUtil.SearchHierarchy(transform, boneDefinition.parentBoneName); - if (parent == null) - { - Debug.LogError($"Cannot find parent bone {boneDefinition.parentBoneName}.", transform); - return null; - } - - Transform bone = TransformUtil.SearchHierarchy(transform, boneDefinition.boneName); - if (bone == null) - { - Debug.LogError($"Cannot find bone {boneDefinition.boneName}.", transform); - } - else if (bone.parent.name != boneDefinition.parentBoneName) - { - Debug.LogError($"bone.parent {bone.parent.name} does not match {boneDefinition.parentBoneName} in hierarchy.", bone); - return null; - } - - Transform socket = TransformUtil.SearchHierarchy(transform, boneDefinition.socketName); - if (socket == null) - { - Debug.LogError($"Cannot find socket {boneDefinition.socketName}.", transform); - return null; - } - else if (socket.parent != bone) - { - Debug.LogError($"socket {socket.name} is not parented to bone {bone.name}.", socket); - return null; - } - - PropBoneBinding binding = new PropBoneBinding() - { - bone = bone, - socket = socket, - rotationOffset = boneDefinition.rotationOffset, - scale = boneDefinition.scale - }; - - return binding; - } - - /// - /// Updates the prop bones if updateType is set to 'Update'. - /// - private void Update() - { - if (updateType == UpdateType.Update) - { - UpdateBones(); - } - } - - /// - /// Updates the prop bones if updateType is set to 'FixedUpdate'. - /// - private void FixedUpdate() - { - if (updateType == UpdateType.FixedUpdate) - { - UpdateBones(); - } - } - - /// - /// Updates the prop bones if updateType is set to 'LateUpdate'. - /// - private void LateUpdate() - { - if (updateType == UpdateType.LateUpdate) - { - UpdateBones(); - } - } - - /// - /// Updates the prop bones according to the prop bone bindings configuration. - /// If updateType is set to 'Manual' call this yourself when it is time to update the bones. - /// - public void UpdateBones() - { +// Copyright (c) 2024 Synty Studios Limited. All rights reserved. +// +// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA) +// available at: https://syntystore.com/pages/end-user-licence-agreement +// +// For additional details, see the LICENSE.MD file bundled with this software. + +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +using System.Collections.Generic; + +namespace Synty.Tools.SyntyPropBoneTool +{ + /// + /// The PropBoneBinder is responsible for creating, managing and updating the prop bones at runtime. + /// Only one of these components is needed per character. It will manage all prop bones defined in the propBoneConfig. + /// + [ExecuteInEditMode] + public class PropBoneBinder : MonoBehaviour + { + [Tooltip("Reference to the animator for this character")] + public Animator animator; + + [Tooltip("Configures how the bones are set up on the rig.")] + public PropBoneConfig propBoneConfig; + + [Tooltip("Determins when this script will update the transforms. For best results run this script later than the animator.")] + public UpdateType updateType = UpdateType.LateUpdate; + public bool updateInEditMode = true; + + [Tooltip("Rebinds all the bones on awake. Useful if your rigs change often, saves needing to rebind them at edit time.")] + public bool rebindOnAwake = false; + + [Space] + [Tooltip("Bindings and offset values applied at runtime.")] + [SerializeField] + private List _propBoneBindings = new List(); + + /// + /// Returns true if the PropBoneBinder is configured correctly. + /// + public bool IsConfigured => AreReferencesConfigured() && AreBindingsConfigured(); + + /// + /// Returns true if the reference variables are configured correctly. + /// + /// A bool that is true when the reference variables are correctly configured. + public bool AreReferencesConfigured() + { + return animator != null && propBoneConfig != null; + } + + /// + /// Returns true if the hierarchy is configured correctly according to the propBoneConfig. + /// + /// A bool that is true when the hierarchy is correctly configured. + public bool IsPropBoneHierarchyConfigured() + { + for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) + { + Transform propBone = TransformUtil.SearchHierarchy(transform, propBoneConfig.propBoneDefinitions[i].boneName); + Transform propBoneSocket = TransformUtil.SearchHierarchy(transform, propBoneConfig.propBoneDefinitions[i].socketName); + if (propBone == null || propBoneSocket == null || propBone.parent == null || propBone.parent.name != propBoneConfig.propBoneDefinitions[i].parentBoneName) + { + return false; + } + } + + return true; + } + + /// + /// Returns true if all the prop bone bindings are configured correctly according to the propBoneConfig. + /// + /// A bool that is true when all the prop bone bindings are correctly configured. + public bool AreBindingsConfigured() + { + if (_propBoneBindings.Count != propBoneConfig.propBoneDefinitions.Length) + { + return false; + } + + for (int i = 0; i < _propBoneBindings.Count; ++i) + { + if (!_propBoneBindings[i].IsMatch(propBoneConfig.propBoneDefinitions[i])) + { + return false; + } + } + + return true; + } + + /// + /// Rebinds the PropBoneBindings on awake if rebindOnAwake is set to true. + /// + private void Awake() + { + if (rebindOnAwake) + { + BindPropBones(); + } + } + + /// + /// Attempts to create a PropBoneBinding in accordance to the giving PropBoneDefinition. + /// + /// The definition of the prop bone to be created. + /// A PropBoneBinding that is the new binding or null if the binding failed to be created. + private PropBoneBinding CreateBoneBinding(PropBoneDefinition boneDefinition) + { + Transform parent = TransformUtil.SearchHierarchy(transform, boneDefinition.parentBoneName); + if (parent == null) + { + Debug.LogError($"Cannot find parent bone {boneDefinition.parentBoneName}.", transform); + return null; + } + + Transform bone = TransformUtil.SearchHierarchy(transform, boneDefinition.boneName); + if (bone == null) + { + Debug.LogError($"Cannot find bone {boneDefinition.boneName}.", transform); + } + else if (bone.parent.name != boneDefinition.parentBoneName) + { + Debug.LogError($"bone.parent {bone.parent.name} does not match {boneDefinition.parentBoneName} in hierarchy.", bone); + return null; + } + + Transform socket = TransformUtil.SearchHierarchy(transform, boneDefinition.socketName); + if (socket == null) + { + Debug.LogError($"Cannot find socket {boneDefinition.socketName}.", transform); + return null; + } + else if (socket.parent != bone) + { + Debug.LogError($"socket {socket.name} is not parented to bone {bone.name}.", socket); + return null; + } + + PropBoneBinding binding = new PropBoneBinding() + { + bone = bone, + socket = socket, + rotationOffset = boneDefinition.rotationOffset, + scale = boneDefinition.scale + }; + + return binding; + } + + /// + /// Updates the prop bones if updateType is set to 'Update'. + /// + private void Update() + { + if (updateType == UpdateType.Update) + { + UpdateBones(); + } + } + + /// + /// Updates the prop bones if updateType is set to 'FixedUpdate'. + /// + private void FixedUpdate() + { + if (updateType == UpdateType.FixedUpdate) + { + UpdateBones(); + } + } + + /// + /// Updates the prop bones if updateType is set to 'LateUpdate'. + /// + private void LateUpdate() + { + if (updateType == UpdateType.LateUpdate) + { + UpdateBones(); + } + } + + /// + /// Updates the prop bones according to the prop bone bindings configuration. + /// If updateType is set to 'Manual' call this yourself when it is time to update the bones. + /// + public void UpdateBones() + { if (!Application.isPlaying && !updateInEditMode) - { + { return; - } - - for (int index = 0; index < _propBoneBindings.Count; ++index) - { - UpdateBone(_propBoneBindings[index]); - } - } - - - /// - /// Updates the prop bone's position and rotation according to the prop bone binding configuration. - /// - /// The prop bone binding to update. - public void UpdateBone(PropBoneBinding boneInstance) - { - if (boneInstance.IsValid) - { - Quaternion offsetRotation = Quaternion.Euler(boneInstance.rotationOffset); - Matrix4x4 localRotation = Matrix4x4.Rotate(offsetRotation); - Matrix4x4 localScale = Matrix4x4.Scale(Vector3.one * boneInstance.scale); - - Matrix4x4 localTransform = localScale * localRotation; - - boneInstance.socket.SetPositionAndRotation( - boneInstance.bone.parent.localToWorldMatrix.MultiplyPoint(localTransform.MultiplyPoint(boneInstance.bone.localPosition)), - boneInstance.bone.parent.rotation * offsetRotation * boneInstance.bone.localRotation); - } - } - - /// - /// Attempts to find and set the animator reference. - /// - public void SetupAnimatorReference() - { - if (animator == null) - { - animator = GetComponent(); - } - if (animator == null) - { - Debug.LogError($"Animator reference is null. New bones may not bind correctly.", transform); - } - -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Completely resets the prop bones and bindings including Destroying all bones instantiated by the PropBoneBinder. - /// Any objects parented to those bones will not be destroyed and will be reparented up the hierarchy. - /// - public void Reset() - { - animator = null; - propBoneConfig = null; - ClearPropBoneBindings(); - DestroyPropBones(); -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Attempts to create all the PropBoneBindings in accordance to the propBondConfig - /// - public void BindPropBones() - { - if (animator == null) - { - Debug.LogError($"animator reference is null.", transform); - } - - _propBoneBindings.Clear(); - - if (propBoneConfig == null) - { - Debug.LogError($"Prop bone config is null.", transform); - return; - } - - for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) - { - PropBoneBinding binding = CreateBoneBinding(propBoneConfig.propBoneDefinitions[i]); - if (binding == null) - { - Debug.LogError($"Could not create binding for prop bone definition {propBoneConfig.propBoneDefinitions[i].ToString()}.", transform); - continue; - } - - _propBoneBindings.Add(binding); - if (binding.bone != null && binding.socket != null) - { - Debug.Log($"Successfully bound {binding.socket.name} to {binding.bone.name}", binding.socket); - } - } - -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Clears all the current bindings - /// - public void ClearPropBoneBindings() - { - _propBoneBindings.Clear(); - -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Instantiates new Game Objects where nessessary to create the prop bones. - /// - public void CreatePropBones() - { - if (propBoneConfig == null) - { - Debug.LogError($"Prop bone config is null.", transform); - return; - } - - for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) - { - CreatePropBones(gameObject, propBoneConfig.propBoneDefinitions[i]); - } -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Instantiates new Game Objects where nessessary to create the prop bones. - /// - /// The root game object to create the prop bone under. - /// The definition of the prop bone to be created. - /// The prop bone binding to update. - private void CreatePropBones(GameObject editScope, PropBoneDefinition boneDefinition) - { - Transform parent = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.parentBoneName); - if (parent == null) - { - Debug.LogError($"Cannot find parent prop bone {boneDefinition.parentBoneName} in hierarchy.", transform); - return; - } - - Transform bone = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.boneName); - if (bone == null) - { - bone = CreatePropBone(boneDefinition.boneName, parent); - if (bone == null) - { - return; - } - } - else if (bone.parent.name != boneDefinition.parentBoneName) - { - Debug.LogError($"bone.parent {bone.parent.name} does not match {boneDefinition.parentBoneName} in hierarchy.", bone); - return; - } - - Transform socket = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.socketName); - if (socket == null) - { - socket = CreatePropBone(boneDefinition.socketName, bone); - } - else if (socket.parent != bone) - { - Debug.LogError($"socket {socket.name} is not parented to bone {bone.name}.", socket); - return; - } -#if UNITY_EDITOR - EditorGUIUtility.PingObject(socket); -#endif - } - - /// - /// Instantiates a new Game Object called 'name' and parents it to 'parent'. - /// - /// The name of the new bone to be created. - /// The transform to parent the new bone to. - private Transform CreatePropBone(string name, Transform parent) - { - // does not check if there is already a bone called this. we should check before calling create - Transform boneInstance = new GameObject(name).transform; - boneInstance.SetParent(parent); - if (boneInstance.parent != parent) - { - Debug.LogError($"Something went wrong when creating prop bone {boneInstance.name}. You may need to enter prefab edit mode to set up this character.", gameObject); - DestroyImmediate(boneInstance.gameObject); - return null; - } - boneInstance.localPosition = Vector3.zero; - boneInstance.localRotation = Quaternion.identity; - boneInstance.localScale = Vector3.one; - // mark that these have been created by the tool - boneInstance.gameObject.AddComponent().WasSpawnedBySyntyTool = true; - - Debug.Log($"Successfully created prop bone {boneInstance.name}.", boneInstance); - - return boneInstance; - } - - /// - /// Destroys all the prop bones that have been created by the PropBoneBinder and clears all bindings. - /// - public void DestroyPropBones() - { - DestroyPropBones(gameObject); -#if UNITY_EDITOR - EditorUtility.SetDirty(gameObject); - PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); -#endif - } - - /// - /// Destroys all the prop bones that have been created by the PropBoneBinder and clears all bindings - /// - /// The root game objects to destroy prop bones from. - private void DestroyPropBones(GameObject editScope) - { - _propBoneBindings.Clear(); - PropBone[] bones = editScope.GetComponentsInChildren(); - for (int i = 0; i < bones.Length; ++i) - { - if (bones[i].WasSpawnedBySyntyTool) - { - // Let's not destroy peoples swords and stuff. - for (int c = 0; c < bones[i].transform.childCount; ++c) - { - Transform child = bones[i].transform.GetChild(c); - child.SetParent(bones[i].transform.parent); - bool hasPropBone = child.GetComponent() != null; - if (!hasPropBone) - { - Debug.Log($"Successfully reparented object {child.name}.", child); - } - } - - string boneName = bones[i].gameObject.name; - Transform parent = bones[i].transform.parent; - - if (Application.isEditor && !Application.isPlaying) - { - DestroyImmediate(bones[i].gameObject); - } - else - { - Destroy(bones[i].gameObject); - } - - if (parent != null) - { - Debug.Log($"Successfully destroyed bone {boneName} under {parent.name}.", parent); - } - else - { - Debug.Log($"Successfully destroyed bone {boneName}."); - } - } - else - { - GameObject gameObject = bones[i].gameObject; - // Remove the component but don't destroy the object. - if (Application.isEditor && !Application.isPlaying) - { - DestroyImmediate(bones[i]); - } - else - { - Destroy(bones[i]); - } - - if (gameObject != null) - { - Debug.Log($"Successfully removed SyntyPropBone component from {gameObject.name}.", gameObject); - } - } - } - } - } + } + + for (int index = 0; index < _propBoneBindings.Count; ++index) + { + UpdateBone(_propBoneBindings[index]); + } + } + + + /// + /// Updates the prop bone's position and rotation according to the prop bone binding configuration. + /// + /// The prop bone binding to update. + public void UpdateBone(PropBoneBinding boneInstance) + { + if (boneInstance.IsValid) + { + Quaternion offsetRotation = Quaternion.Euler(boneInstance.rotationOffset); + Matrix4x4 localRotation = Matrix4x4.Rotate(offsetRotation); + Matrix4x4 localScale = Matrix4x4.Scale(Vector3.one * boneInstance.scale); + + Matrix4x4 localTransform = localScale * localRotation; + + boneInstance.socket.SetPositionAndRotation( + boneInstance.bone.parent.localToWorldMatrix.MultiplyPoint(localTransform.MultiplyPoint(boneInstance.bone.localPosition)), + boneInstance.bone.parent.rotation * offsetRotation * boneInstance.bone.localRotation); + } + } + + /// + /// Attempts to find and set the animator reference. + /// + public void SetupAnimatorReference() + { + if (animator == null) + { + animator = GetComponent(); + } + if (animator == null) + { + Debug.LogError($"Animator reference is null. New bones may not bind correctly.", transform); + } + +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Completely resets the prop bones and bindings including Destroying all bones instantiated by the PropBoneBinder. + /// Any objects parented to those bones will not be destroyed and will be reparented up the hierarchy. + /// + public void Reset() + { + animator = null; + propBoneConfig = null; + ClearPropBoneBindings(); + DestroyPropBones(); +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Attempts to create all the PropBoneBindings in accordance to the propBondConfig + /// + public void BindPropBones() + { + if (animator == null) + { + Debug.LogError($"animator reference is null.", transform); + } + + _propBoneBindings.Clear(); + + if (propBoneConfig == null) + { + Debug.LogError($"Prop bone config is null.", transform); + return; + } + + for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) + { + PropBoneBinding binding = CreateBoneBinding(propBoneConfig.propBoneDefinitions[i]); + if (binding == null) + { + Debug.LogError($"Could not create binding for prop bone definition {propBoneConfig.propBoneDefinitions[i].ToString()}.", transform); + continue; + } + + _propBoneBindings.Add(binding); + if (binding.bone != null && binding.socket != null) + { + Debug.Log($"Successfully bound {binding.socket.name} to {binding.bone.name}", binding.socket); + } + } + +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Clears all the current bindings + /// + public void ClearPropBoneBindings() + { + _propBoneBindings.Clear(); + +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Instantiates new Game Objects where nessessary to create the prop bones. + /// + public void CreatePropBones() + { + if (propBoneConfig == null) + { + Debug.LogError($"Prop bone config is null.", transform); + return; + } + + for (int i = 0; i < propBoneConfig.propBoneDefinitions.Length; ++i) + { + CreatePropBones(gameObject, propBoneConfig.propBoneDefinitions[i]); + } +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Instantiates new Game Objects where nessessary to create the prop bones. + /// + /// The root game object to create the prop bone under. + /// The definition of the prop bone to be created. + /// The prop bone binding to update. + private void CreatePropBones(GameObject editScope, PropBoneDefinition boneDefinition) + { + Transform parent = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.parentBoneName); + if (parent == null) + { + Debug.LogError($"Cannot find parent prop bone {boneDefinition.parentBoneName} in hierarchy.", transform); + return; + } + + Transform bone = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.boneName); + if (bone == null) + { + bone = CreatePropBone(boneDefinition.boneName, parent); + if (bone == null) + { + return; + } + } + else if (bone.parent.name != boneDefinition.parentBoneName) + { + Debug.LogError($"bone.parent {bone.parent.name} does not match {boneDefinition.parentBoneName} in hierarchy.", bone); + return; + } + + Transform socket = TransformUtil.SearchHierarchy(editScope.transform, boneDefinition.socketName); + if (socket == null) + { + socket = CreatePropBone(boneDefinition.socketName, bone); + } + else if (socket.parent != bone) + { + Debug.LogError($"socket {socket.name} is not parented to bone {bone.name}.", socket); + return; + } +#if UNITY_EDITOR + EditorGUIUtility.PingObject(socket); +#endif + } + + /// + /// Instantiates a new Game Object called 'name' and parents it to 'parent'. + /// + /// The name of the new bone to be created. + /// The transform to parent the new bone to. + private Transform CreatePropBone(string name, Transform parent) + { + // does not check if there is already a bone called this. we should check before calling create + Transform boneInstance = new GameObject(name).transform; + boneInstance.SetParent(parent); + if (boneInstance.parent != parent) + { + Debug.LogError($"Something went wrong when creating prop bone {boneInstance.name}. You may need to enter prefab edit mode to set up this character.", gameObject); + DestroyImmediate(boneInstance.gameObject); + return null; + } + boneInstance.localPosition = Vector3.zero; + boneInstance.localRotation = Quaternion.identity; + boneInstance.localScale = Vector3.one; + // mark that these have been created by the tool + boneInstance.gameObject.AddComponent().WasSpawnedBySyntyTool = true; + + Debug.Log($"Successfully created prop bone {boneInstance.name}.", boneInstance); + + return boneInstance; + } + + /// + /// Destroys all the prop bones that have been created by the PropBoneBinder and clears all bindings. + /// + public void DestroyPropBones() + { + DestroyPropBones(gameObject); +#if UNITY_EDITOR + EditorUtility.SetDirty(gameObject); + PrefabUtility.RecordPrefabInstancePropertyModifications(gameObject); +#endif + } + + /// + /// Destroys all the prop bones that have been created by the PropBoneBinder and clears all bindings + /// + /// The root game objects to destroy prop bones from. + private void DestroyPropBones(GameObject editScope) + { + _propBoneBindings.Clear(); + PropBone[] bones = editScope.GetComponentsInChildren(); + for (int i = 0; i < bones.Length; ++i) + { + if (bones[i].WasSpawnedBySyntyTool) + { + // Let's not destroy peoples swords and stuff. + for (int c = 0; c < bones[i].transform.childCount; ++c) + { + Transform child = bones[i].transform.GetChild(c); + child.SetParent(bones[i].transform.parent); + bool hasPropBone = child.GetComponent() != null; + if (!hasPropBone) + { + Debug.Log($"Successfully reparented object {child.name}.", child); + } + } + + string boneName = bones[i].gameObject.name; + Transform parent = bones[i].transform.parent; + + if (Application.isEditor && !Application.isPlaying) + { + DestroyImmediate(bones[i].gameObject); + } + else + { + Destroy(bones[i].gameObject); + } + + if (parent != null) + { + Debug.Log($"Successfully destroyed bone {boneName} under {parent.name}.", parent); + } + else + { + Debug.Log($"Successfully destroyed bone {boneName}."); + } + } + else + { + GameObject gameObject = bones[i].gameObject; + // Remove the component but don't destroy the object. + if (Application.isEditor && !Application.isPlaying) + { + DestroyImmediate(bones[i]); + } + else + { + Destroy(bones[i]); + } + + if (gameObject != null) + { + Debug.Log($"Successfully removed SyntyPropBone component from {gameObject.name}.", gameObject); + } + } + } + } + } } \ No newline at end of file diff --git a/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs.meta b/Assets/External/Tools/SyntyPropBoneTool/Runtime/PropBoneBinder.cs.meta old mode 100644 new mode 100755